Files
2026-09-10 16:50:06 +08:00

8.9 KiB

Payment Merchant Pool Management Specification

ADDED Requirements

Requirement: 平台专属的商户池管理入口

系统 SHALL 仅向超级管理员和平台用户开放支付商户、商户池及微信授权配置的管理入口和操作。

Scenario: 超级管理员可见并访问

  • GIVEN 当前登录账号的 user_type1
  • WHEN 用户加载设置菜单或访问 /settings/payment-merchant-pools
  • THEN 系统 MUST 展示商户池管理入口并允许进入页面

Scenario: 平台用户可见并访问

  • GIVEN 当前登录账号的 user_type2
  • WHEN 用户加载设置菜单或访问 /settings/payment-merchant-pools
  • THEN 系统 MUST 展示商户池管理入口并允许进入页面

Scenario: 非平台账号被拒绝

  • GIVEN 当前登录账号的 user_type34
  • WHEN 用户加载设置菜单或直接输入 /settings/payment-merchant-pools
  • THEN 系统 MUST NOT 展示商户池管理入口
  • AND 系统 MUST 拒绝直接访问该页面
  • AND 系统 MUST NOT 返回商户、商户池或授权配置数据

Requirement: 支付商户管理接口

系统 SHALL 提供支付商户的分页查询、创建、详情、按需更新和删除接口。

Scenario: 查询和筛选支付商户

  • WHEN 管理员请求 GET /api/admin/payment-merchants
  • THEN 系统 MUST 支持 pagepage_sizepayment_methodenabled 查询参数
  • AND payment_method MUST 支持 wechatalipay
  • AND 响应中的每个商户 MUST 包含 idnamepayment_methodprovider_typemerchant_identityenabledremarkcredential_versioncreated_atupdated_at

Scenario: 创建支付商户

  • WHEN 管理员向 POST /api/admin/payment-merchants 提交 namepayment_methodprovider_typemerchant_identitycredentialsenabledremark
  • THEN 系统 MUST 创建支付商户并返回新商户记录
  • AND provider_typewechat 时 MUST 只接受 wechatwechat_v2fuiou
  • AND provider_typealipay 时 MUST 只接受 alipay

Scenario: 查询支付商户详情

  • WHEN 管理员请求 GET /api/admin/payment-merchants/{id}
  • THEN 系统 MUST 返回指定商户的详情
  • AND 响应 MUST NOT 包含任何支付凭证明文

Scenario: 按需更新和切换商户状态

  • WHEN 管理员请求 PUT /api/admin/payment-merchants/{id} 并只提交 enabled
  • THEN 系统 MUST 只更新该商户的 enabled 字段
  • AND 系统 MUST 保留未提交字段的原值

Scenario: 确认后删除支付商户

  • WHEN 管理员请求 DELETE /api/admin/payment-merchants/{id} 并提交 confirm=true
  • THEN 系统 MUST 删除目标商户
  • AND 前端 MUST 在发送请求前展示二次确认

Requirement: 支付商户列表与启停交互

后台商户管理页 SHALL 展示支付商户状态,并允许有权限的管理员按接口契约切换启用状态。

Scenario: 列表不展示支付凭证

  • GIVEN 支付商户列表已加载
  • THEN 表格 MUST 展示商户名称、支付方式、服务商类型、商户标识、启停状态、凭证版本、更新时间和备注
  • AND 表格、详情弹层和页面状态 MUST NOT 展示 credentials 原始值

Scenario: 切换商户启停状态

  • GIVEN 管理员位于支付商户列表
  • WHEN 管理员启用或停用一个商户并确认操作
  • THEN 前端 MUST 调用 PUT /api/admin/payment-merchants/{id} 提交新的 enabled
  • AND 成功后 MUST 使用接口结果刷新该商户状态

Requirement: 支付凭证写入与缓存隔离

系统 SHALL 将支付商户凭证视为只写敏感数据,禁止在读取、展示、缓存或日志中保留原始值。

Scenario: 创建时只写凭证

  • GIVEN 管理员正在创建支付商户或显式更换凭证
  • WHEN 管理员在密码型输入控件中输入凭证并提交
  • THEN 前端 MUST 仅在当前表单生命周期内保留凭证输入值
  • AND 提交成功、取消、关闭弹层或组件卸载后 MUST 立即清空该值
  • AND 系统 MUST NOT 提供查看、复制、下载或历史明文回显能力

Scenario: 读取时不回填凭证

  • GIVEN 商户列表或详情接口已返回数据
  • WHEN 前端构建页面模型
  • THEN 前端 MUST 丢弃 credentials 原始值
  • AND 页面 MUST 只展示“已配置/未配置”状态和 credential_version
  • AND 前端 MUST NOT 将 credentials 写入 Pinia persisted state、localStoragesessionStorage、URL、查询参数、日志、埋点或错误上报

Scenario: 接口异常不泄露凭证

  • WHEN 创建、更新或删除商户请求失败
  • THEN 错误提示和错误上报 MUST NOT 包含请求体中的支付凭证

Requirement: 商户池管理接口

系统 SHALL 提供商户池的分页查询、创建、详情、更新、启用和停用接口。

Scenario: 查询和创建商户池

  • WHEN 管理员请求 GET /api/admin/payment-merchant-pools 或创建商户池
  • THEN 系统 MUST 返回分页 data 或新建商户池记录
  • AND 商户池对象 MUST 支持 idnamepayment_methodmember_idsenabledstrategystatistic_cyclethreshold_amountthreshold_counttime_period_started_attime_period_unittime_period_valuerouting_epochremark
  • AND payment_method MUST 支持 wechatalipay

Scenario: 查询和更新商户池详情

  • WHEN 管理员请求 GET /api/admin/payment-merchant-pools/{id} 或向同一路径提交 PUT
  • THEN 系统 MUST 返回指定商户池详情或保存更新后的商户池
  • AND 更新请求 MUST 按创建商户池的字段模型接受可提交字段

Scenario: 启用和停用商户池

  • WHEN 管理员请求 POST /api/admin/payment-merchant-pools/{id}/enable
  • THEN 系统 MUST 将目标商户池设置为启用状态
  • WHEN 管理员请求 POST /api/admin/payment-merchant-pools/{id}/disable
  • THEN 系统 MUST 将目标商户池设置为停用状态

Requirement: 商户池成员排序与路由配置

商户池管理页 SHALL 支持可验证的成员排序,并按轮询策略配置对应阈值。

Scenario: 成员顺序按数组顺序保存

  • GIVEN 商户池表单中存在多个同支付方式的候选商户
  • WHEN 管理员拖拽调整成员顺序并提交
  • THEN member_ids MUST 按拖拽后的顺序提交
  • AND 系统 MUST 拒绝重复的商户 ID
  • AND 更新详情或重新编辑时 MUST 按接口返回的 member_ids 顺序展示

Scenario: 按金额轮换

  • GIVEN 管理员选择 strategy=amount
  • WHEN 管理员填写金额阈值并提交
  • THEN 页面 MUST 使用元作为输入单位并转换为整数分写入 threshold_amount
  • AND statistic_cycle MUST 为 rounddaymonth
  • AND threshold_amount MUST 为大于零的整数

Scenario: 按笔数轮换

  • GIVEN 管理员选择 strategy=count
  • WHEN 管理员填写笔数阈值并提交
  • THEN 页面 MUST 写入正整数 threshold_count
  • AND statistic_cycle MUST 为 rounddaymonth

Scenario: 按时间轮换

  • GIVEN 管理员选择 strategy=time
  • WHEN 管理员填写时间周期并提交
  • THEN time_period_unit MUST 为 minutehourday
  • AND time_period_value MUST 为大于零的整数
  • AND 系统 MUST 支持提交 time_period_started_at

Scenario: 路由世代只读

  • GIVEN 商户池详情返回 routing_epoch
  • THEN 页面 MUST 只读展示该值
  • AND 页面 MUST NOT 提供编辑或提交该字段的控件

Requirement: 微信授权配置管理

系统 SHALL 提供当前微信授权配置的读取和保存能力,并允许管理员切换授权配置的启停状态。

Scenario: 读取当前微信授权配置状态

  • WHEN 管理员请求 GET /api/admin/wechat-authorizations
  • THEN 页面 MUST 展示 enabledminiapp_app_idoa_app_idoa_oauth_redirect_url 等非敏感字段
  • AND 页面 MUST NOT 回填或展示 miniapp_app_secretoa_app_secretoa_tokenoa_aes_key 的原始值

Scenario: 保存或切换微信授权启停状态

  • WHEN 管理员向 PUT /api/admin/wechat-authorizations/current 保存配置
  • THEN 请求 MUST 支持 enabledminiapp_app_idminiapp_app_secretoa_app_idoa_app_secretoa_tokenoa_aes_keyoa_oauth_redirect_url
  • AND 保存成功后页面 MUST 使用接口结果刷新启停状态
  • AND 敏感字段 MUST 只在当前编辑会话内存在,并在保存、取消、关闭或卸载后清空

Scenario: 未更换敏感字段时保留后端原值

  • GIVEN 页面只修改 enabled 或其他非敏感字段
  • WHEN 管理员提交微信授权配置
  • THEN 请求 MUST NOT 使用脱敏占位值覆盖后端已有敏感字段
  • AND 页面 MUST NOT 在提交后缓存敏感字段值