fix: 代理

This commit is contained in:
luo
2026-09-12 11:27:50 +08:00
parent d3d257cdf8
commit 2308d82d0f
44 changed files with 5470 additions and 200 deletions

View File

@@ -0,0 +1,155 @@
## ADDED Requirements
### Requirement: 商户池详情入口
系统 SHALL 与支付商户保持一致,以点击列表中商户池名称的方式进入独立详情页,并且不再在行操作中提供“详情”入口。
#### Scenario: 点击商户池名称进入详情页
- **GIVEN** 管理员位于支付商户与商户池管理页的“商户池”页签
- **WHEN** 管理员点击列表中某个商户池名称
- **THEN** 系统 MUST 跳转到该商户池的详情页
- **AND** 详情页 MUST 通过 `GET /api/admin/payment-merchant-pools/{id}` 加载数据
- **AND** 列表行操作 MUST NOT 再提供“详情”操作
#### Scenario: 商户池名称以可点击样式展示
- **GIVEN** 商户池列表加载成功
- **WHEN** 页面渲染商户池名称列
- **THEN** 商户池名称 MUST 以可点击样式展示
- **AND** 点击名称 MUST NOT 触发表格行选中或其他行操作
#### Scenario: 非平台账号不能查看商户池详情
- **GIVEN** 当前登录账号的 `user_type` 不是 `1``2`
- **WHEN** 用户点击商户池名称或直接访问商户池详情页地址
- **THEN** 系统 MUST NOT 展示商户池详情数据
- **AND** 路由 MUST 按平台账号限制拦截该访问
### Requirement: 商户池详情信息完整
系统 SHALL 在商户池详情页展示详情接口返回的全部业务字段,并 SHALL 以支付商户名称展示成员商户,不得展示 `id``member_ids` 原始标识。
#### Scenario: 展示轮询策略与阈值字段
- **GIVEN** 管理员进入某个商户池详情页
- **WHEN** 详情数据加载成功
- **THEN** 详情 MUST 展示商户池名称、支付方式、启停状态、轮询策略、路由世代和备注
- **AND** `strategy``amount``count` 时 MUST 展示统计周期和对应阈值
- **AND** `strategy``time` 时 MUST 展示时间单位、时间长度和时间起点
#### Scenario: 成员商户按名称展示
- **GIVEN** 商户池详情返回 `member_ids`
- **WHEN** 页面展示成员信息
- **THEN** 页面 MUST 展示成员商户名称和成员数量
- **AND** 页面 MUST NOT 展示 `member_ids` 原始 ID
- **AND** 成员名称无法解析时 MUST 展示“未知商户”而不是 ID
#### Scenario: 未返回的字段不渲染
- **GIVEN** 商户池详情接口未返回创建时间或更新时间
- **WHEN** 页面展示商户池详情
- **THEN** 页面 MUST NOT 渲染对应字段的空白行
### Requirement: 商户池成员顺序单一数据源
系统 SHALL 使用单一数据源维护商户池成员顺序,保证新增、编辑和拖拽排序成员时不会出现递归更新错误,并且提交顺序与页面展示顺序一致。
#### Scenario: 新增商户池不再递归更新
- **WHEN** 管理员点击“新增商户池”
- **THEN** 系统 MUST NOT 抛出 `Maximum recursive updates exceeded`
- **AND** 表单 MUST 正常打开并允许选择成员
#### Scenario: 拖拽后按展示顺序提交
- **GIVEN** 商户池表单中存在多个成员商户
- **WHEN** 管理员拖拽调整成员顺序并提交
- **THEN** `member_ids` MUST 按拖拽后的顺序提交
- **AND** 再次编辑该商户池时 MUST 按提交顺序展示成员
### Requirement: 商户凭证字段枚举契约
系统 SHALL 按 `payment_method``provider_type` 组合枚举商户凭证的必填键与可选键,并在提交前校验字段枚举、必填键、值类型与商户标识一致性。
字段枚举以后端契约为准(键名与渠道配置字段一致),前端必须与后端保持一致,后端新增或调整字段时需同步更新前端枚举。`credentials` MUST 为扁平 JSON 对象,必填键为:
- `payment_method=wechat``provider_type=wechat``wx_mch_id``wx_api_v3_key``wx_cert_content``wx_key_content``wx_serial_no``wx_notify_url`
- `payment_method=wechat``provider_type=wechat_v2``wx_mch_id``wx_api_v2_key``wx_notify_url`
- `payment_method=wechat``provider_type=fuiou``fy_mchnt_cd``fy_ins_cd``fy_term_id``fy_private_key``fy_public_key``fy_api_url``fy_notify_url`
- `payment_method=alipay``provider_type=alipay``ali_app_id``ali_private_key``ali_public_key``ali_notify_url``ali_return_url`
可选键为:`wechat` 可附 `wx_api_v2_key``alipay` 可附 `ali_production`(布尔,是否生产环境)与 `ali_pay_expire_minutes`(整数,支付过期分钟数)。除 `ali_production``ali_pay_expire_minutes` 外,凭证值 MUST 为字符串。`merchant_identity` MUST 分别等于 `wx_mch_id``fy_mchnt_cd``ali_app_id`
#### Scenario: 提交微信直连凭证
- **GIVEN** 管理员提交 `payment_method=wechat``provider_type=wechat` 的商户凭证
- **THEN** 请求 MUST 包含 `wx_mch_id``wx_api_v3_key``wx_cert_content``wx_key_content``wx_serial_no``wx_notify_url`
- **AND** 请求 MAY 附带 `wx_api_v2_key`
- **AND** `merchant_identity` MUST 等于 `wx_mch_id`
#### Scenario: 提交微信直连 V2 凭证
- **GIVEN** 管理员提交 `payment_method=wechat``provider_type=wechat_v2` 的商户凭证
- **THEN** 请求 MUST 包含 `wx_mch_id``wx_api_v2_key``wx_notify_url`
- **AND** `merchant_identity` MUST 等于 `wx_mch_id`
#### Scenario: 提交富友凭证
- **GIVEN** 管理员提交 `payment_method=wechat``provider_type=fuiou` 的商户凭证
- **THEN** 请求 MUST 包含 `fy_mchnt_cd``fy_ins_cd``fy_term_id``fy_private_key``fy_public_key``fy_api_url``fy_notify_url`
- **AND** `merchant_identity` MUST 等于 `fy_mchnt_cd`
#### Scenario: 提交支付宝凭证
- **GIVEN** 管理员提交 `payment_method=alipay``provider_type=alipay` 的商户凭证
- **THEN** 请求 MUST 包含 `ali_app_id``ali_private_key``ali_public_key``ali_notify_url``ali_return_url`
- **AND** 请求 MAY 附带 `ali_production``ali_pay_expire_minutes`
- **AND** `merchant_identity` MUST 等于 `ali_app_id`
#### Scenario: 缺少必填字段时拒绝提交
- **WHEN** 提交的凭证缺少当前服务商组合的必填键
- **THEN** 前端 MUST 阻止提交并提示缺失的凭证字段名
#### Scenario: 拒绝不属于当前服务商的凭证字段
- **WHEN** 提交的凭证包含必填键与可选键之外的字段名
- **THEN** 前端 MUST 阻止提交并提示该字段不属于当前服务商支持的字段
#### Scenario: 校验凭证值类型
- **GIVEN** 凭证包含 `ali_production``ali_pay_expire_minutes`
- **WHEN** 管理员提交凭证
- **THEN** `ali_production` MUST 以布尔值提交
- **AND** `ali_pay_expire_minutes` MUST 以正整数提交
- **AND** 其余凭证字段 MUST 以字符串提交
#### Scenario: 校验商户标识一致性
- **WHEN** `merchant_identity``wx_mch_id``fy_mchnt_cd``ali_app_id` 的值不一致
- **THEN** 前端 MUST 阻止提交并提示商户标识必须与对应凭证字段一致
### Requirement: 商户凭证访问控制
系统 SHALL 仅允许超级管理员(`user_type=1`)与平台用户(`user_type=2`)读取和写入商户凭证,且凭证内容 MUST NOT 进入日志、审计记录或支付快照。
#### Scenario: 平台账号可读写凭证
- **GIVEN** 当前登录账号的 `user_type``1``2`
- **WHEN** 账号打开支付商户管理页、支付商户详情页或提交商户凭证
- **THEN** 系统 MUST 允许读取凭证配置状态与写入凭证
#### Scenario: 非平台账号不可读写凭证
- **GIVEN** 当前登录账号的 `user_type``3``4`
- **WHEN** 账号访问支付商户管理页或支付商户详情页
- **THEN** 系统 MUST 拒绝访问并 MUST NOT 返回凭证字段或凭证状态
- **AND** 页面 MUST NOT 渲染凭证写入入口
#### Scenario: 凭证不写入日志与快照
- **WHEN** 创建、更新或删除支付商户成功或失败
- **THEN** 凭证内容 MUST NOT 出现在浏览器存储、页面日志、错误上报或支付快照中
- **AND** 页面 MUST 只展示“已配置/未配置”状态与 `credential_version`