Files
break 370fd3e67f
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m49s
update
2026-09-03 09:28:28 +08:00

58 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Context
现有 `tb_wechat_config` 同时承担支付渠道配置;订单、充值和 `tb_payment` 通过 `payment_config_id` 供回调加载创建时配置。`tb_payment` 已有非敏感 `merchant_identity` 快照,但不足以区分商户池、服务商和完整路由。新模型必须让新单和旧单分流,不能把历史订单指向迁移后新商户。
## Decisions
### 独立实体与不可变路由快照
新增商户、商户池、池成员、微信授权配置及金额/笔数统计事实;支付单扩展实际商户和商户池 ID 及非敏感快照。商户凭证只留在商户表受控字段,支付单/审计不复制。被引用后锁定商户支付方式、服务商与身份,避免历史验签与退款语义漂移。
### 路由和统计在支付创建/成功边界闭合
支付创建在事务内读取唯一启用池、按方式选择成员并冻结路由;无成员/池失败即返回。金额/笔数统计只在现有“支付成功首次生效”路径按实际商户条件递增,以支付 ID 唯一约束避免重复回调累计;不在预下单预占。时间方式由当前时间和受控起点计算,不写逐次路由日志。
### 新旧配置双读切换
新支付单具有 merchant ID 时支付加载、回调验签、查询和退款均从商户加载服务商凭证merchant ID 为空的历史单保持现有 `payment_config_id` 路径。迁移先复制生效配置中完整凭证,再发布新支付路径;不可将现有记录批量回填为新商户,因为其实际历史身份无法保证一致。
### 敏感配置边界
后台管理响应按 PRD 向两类已认证管理角色完整返回凭证;所有 logger、错误、审计 payload、支付单快照和导出只允许写 ID、名称和脱敏/非敏感身份。更新凭证后使现有配置加载缓存失效;历史回调读取最新有效凭证以支持轮换。
## 管理与支付动作契约
以下路径为本 Change 新增后台管理契约;所有管理写操作仅限超级管理员和平台用户,金额均为分,敏感凭证只在已认证管理请求的写入/详情响应中传输,绝不进入支付快照、审计、日志或导出。
### 商户
- `POST /payment-merchants`:请求 `name``payment_method``wechat`/`alipay`)、`provider_type``merchant_identity``credentials``enabled``remark`。同一支付方式下身份标识不得重复;凭证缺失或与服务商类型不匹配时拒绝。
- `PUT /payment-merchants/:id`:未被任何支付单引用时可修改全部字段;被引用后仅可改名称、凭证、启停、备注,修改支付方式、服务商类型或商户身份返回“已被支付单引用,不能修改收款身份”。
- `DELETE /payment-merchants/:id`:被引用或仍属于任一商户池时拒绝;删除前必须显式二次确认。停用不影响已冻结该商户的查单、验签和退款。
### 商户池
- `POST /payment-merchant-pools`:请求 `name``payment_method``enabled``strategy`(金额/笔数/时间)、策略参数和有序 `member_ids`。成员均须存在、启用、与池支付方式一致且不重复;同一支付方式最多一个启用池,冲突返回“该支付方式已有启用商户池”。
- `PUT /payment-merchant-pools/:id`:修改阈值只保留当前统计;修改金额/笔数统计周期、时间周期、起始时间或每轮成员排序时开启新统计周期;自然周期仅调整排序时保留未移除成员累计。成员移除后不再选择,但历史支付快照不改写。
- `POST /payment-merchant-pools/:id/enable``/disable`:启用时再次校验唯一启用池和可用成员;停用后新支付创建明确失败,不回退综合支付配置。
### 微信授权配置
- `GET /wechat-authorizations`:最多返回一个启用配置;仅管理角色可读取。`PUT /wechat-authorizations/current` 创建或更新唯一配置,写入公众号 H5/JSSDK、小程序登录及支付 AppID 所需字段。
- 启用第二个配置返回“平台已有启用微信授权配置”;停用后 C 端微信登录/OpenID/微信支付 AppID 不得静默回退其他支付商户或旧配置。
### 新旧支付分流
- C 端套餐订单、资产钱包充值、代理在线预存款创建支付时,在同一事务内读取对应支付方式唯一启用池并冻结 `merchant_id``merchant_pool_id`、非敏感收款身份与轮询快照;无可用成员返回“暂无可用商户”。
- `merchant_id` 非空的支付,在回调、查单、退款时加载该商户当前凭证;为空的历史支付仅按既有 `payment_config_id` 处理。不得按当前启用池为历史单推断商户。
- 首次支付成功消费者以支付 ID 唯一记账金额/笔数统计;重复回调不重复累计。预下单、失败、关闭和退款均不变更统计。
## Risks / Trade-offs
- 并发成功回调超过阈值:这是“只统计成功、不预占”的明确结果,下一次选路才跳过。
- 商户停用后的退款:停用不阻断历史退款,实际调用仍由凭证/渠道结果决定。
- 迁移缺失凭证:不造空商户池,受影响新支付明确失败。
- 旧回调误入新路径:以支付单 merchant ID 为唯一分流条件,严禁按当前启用池推断。
## Migration Plan
1. 新增成对迁移创建商户/池/成员/微信授权表、唯一启用约束、支付单路由列和成功统计索引。
2. 在迁移事务中从唯一生效综合配置复制完整凭证并创建单成员池;全过程禁止日志输出密钥/证书。
3. 隔离库验证微信直连、富友、支付宝、空配置、停用历史商户、回调兼容、三种轮询及 up/down/up。
4. 回滚前停止新支付创建;有新路由单时仅回退应用流量,不执行会破坏新支付事实的 down。