Files
one-pipe-system/openspec/changes/update-payment-merchant-pool-optimization/design.md
2026-09-12 11:27:50 +08:00

55 lines
4.5 KiB
Markdown
Raw 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
支付商户与商户池管理页已经上线,运营在使用时遇到三个问题:商户池详情入口和支付商户不一致且信息不完整、新增商户池直接报错、商户凭证缺少字段枚举与类型校验。本次优化只新增详情页、收敛成员顺序数据源,并在既有凭证写入表单上叠加契约校验,不改变接口路径与请求结构。
## Goals
- 让商户池详情的入口和展示完整度与支付商户详情对齐。
- 让新增/编辑商户池恢复可用,并且拖拽排序结果仍按顺序提交。
- 让前端提交的商户凭证满足后端的字段枚举、必填键、值类型与商户标识约束。
## Non-Goals
- 不改变“更换凭证”表单的交互方式与凭证值不回显约束。
- 不新增后端接口。
## Decisions
### 商户池详情复用支付商户详情的入口模式
支付商户详情已采用“列表点击名称 → 独立详情页”的模式,因此商户池改为同样方式:列表名称列渲染为可点击文本,点击后跳转 `/settings/payment-merchant-pools/pool-detail/:id`,并移除行操作里的“详情”抽屉。
详情页复用 `src/components/common/DetailPage.vue`,按“基本信息”“轮询配置”“运行状态”三组展示字段。创建时间、更新时间只在接口返回时渲染,避免出现空白字段行。
替代方案是保留抽屉并补齐字段;但两个详情入口不一致会让运营难以形成稳定预期,因此不采用。
### 成员商户名称由前端解析
详情接口只返回 `member_ids`。详情页在加载详情后按该商户池的 `payment_method` 拉取支付商户列表,把成员 ID 映射为商户名称展示,同时保留成员数量。解析不到名称时展示“未知商户”,不展示 `member_ids` 原始 ID避免把内部标识暴露给运营。
### 成员顺序使用单一数据源
原实现同时监听 `form.member_ids``orderedMemberIds`,并在两个回调中互相赋新数组,形成“赋值 → 触发 → 再赋值”的无限循环,从而在新增商户池时触发 `Maximum recursive updates exceeded`
修复方式是把成员顺序收敛为单一数据源:`orderedMemberIds` 改为基于 `form.member_ids``computed`get 返回成员数组set 写回成员数组)。`VueDraggable` 通过 `v-model` 触发 setter 写回 `form.member_ids`,不再存在互相触发的 watch。
### 凭证字段枚举固化在类型模块并在提交前校验
凭证必填键由后端契约按 `payment_method``provider_type` 组合给出,前端与该契约保持一致,因此把枚举定义在 `src/types/api/paymentMerchantPools.ts``PAYMENT_CREDENTIAL_FIELD_SPECS` 描述每个 `provider_type` 的必填键与可选键,`PAYMENT_CREDENTIAL_BOOLEAN_KEYS``PAYMENT_CREDENTIAL_INTEGER_KEYS` 描述 `ali_production``ali_pay_expire_minutes` 的值类型,`PAYMENT_MERCHANT_IDENTITY_KEYS` 描述商户标识必须一致的凭证字段。枚举之外的字段名一律拦截,避免提交必然被后端拒绝的请求。
`buildPaymentCredentials` 负责提交前校验并转换:拒绝不属于当前服务商的字段名、补齐必填键检查、把布尔字段与整数字段从输入框字符串转换为布尔值/数字、校验 `merchant_identity` 与对应凭证字段一致。表单继续使用“字段名 + 字段值”的通用编辑方式,只在分隔线下方展示当前服务商的必填/可选字段提示。
替代方案是把凭证表单改成按服务商渲染固定中文标签字段;该方案会改变既有交互与凭证只写约定,本次不采用。
### 凭证仅平台账号可读写
凭证读取与写入入口复用既有平台账号限制:`/settings/payment-merchant-pools` 及其详情路由都带 `allowedUserTypes: [1, 2]`,页面内 `canManage` 再按 `isPlatformAccount` 过滤操作。凭证值只在当前编辑会话内存中存在,提交、取消或关闭后清空,不进入 Pinia 持久化、浏览器存储、日志或错误上报。
## Risks and Trade-offs
- 详情页与支付商户详情一样受 `allowedUserTypes: [1, 2]` 限制,代理与企业账号无法访问。
- 商户池成员名称依赖支付商户列表接口,成员数量超过单页上限时可能解析不到名称,此时展示“未知商户”而不是原始 ID。
- 凭证字段枚举与后端校验规则必须保持一致;后端新增字段时前端需要同步更新枚举,否则提交会被前端拦截。