feat: 支付商户

This commit is contained in:
luo
2026-09-10 16:50:06 +08:00
parent ef966171b4
commit d3d257cdf8
21 changed files with 2884 additions and 27 deletions

View File

@@ -0,0 +1,69 @@
# Implementation Tasks
## 1. 契约与类型
- [x] 1.1 新增支付商户、商户池和微信授权配置的类型,完整覆盖接口文档字段、分页响应、筛选参数和请求体。
- [x] 1.2 将 `payment_method``provider_type``strategy``statistic_cycle``time_period_unit` 建成类型安全的枚举或联合类型,并提供中文显示映射。
- [x] 1.3 明确 `credentials` 为只写字段读取响应适配层不得把敏感字段写入页面模型、Pinia、路由或浏览器存储。
- [x] 1.4 新增 `PaymentMerchantPoolsService`,实现商户、商户池和微信授权配置的全部接口调用。
- [x] 1.5 在 `src/api/modules/index.ts``src/types/api/index.ts` 导出新增模块。
## 2. 入口与权限
- [x] 2.1 增加 `/settings/payment-merchant-pools` 路由,并设置仅允许 `user_type=1``user_type=2` 访问的元数据。
- [x] 2.2 扩展路由权限判断,在现有角色/按钮权限之外支持按用户类型限制;直接输入 URL 时对代理和企业账号返回无权限。
- [x] 2.3 在设置菜单和语言包中增加“商户池管理”入口,确认代理、企业账号不渲染该菜单。
- [x] 2.4 页面内所有创建、编辑、启停、删除和排序操作同时校验用户类型,避免仅依赖菜单隐藏。
## 3. 支付商户管理页
- [x] 3.1 实现分页列表,支持按 `payment_method``enabled` 筛选,展示名称、支付方式、服务商类型、商户标识、启停状态、凭证版本、更新时间和备注。
- [x] 3.2 实现创建商户表单,字段覆盖 `name``payment_method``provider_type``merchant_identity``credentials``enabled``remark`
- [x] 3.3 实现详情与按需更新,只允许更新接口文档支持的字段;切换 `enabled` 时提交 `PUT /api/admin/payment-merchants/{id}`
- [x] 3.4 实现删除前的二次确认,并仅在用户确认后发送 `{ "confirm": true }`
- [x] 3.5 凭证输入只出现在创建或显式“更换凭证”流程中,使用不可回显的密码型控件;提交成功、取消或关闭弹层后立即清空内存表单值。
- [x] 3.6 禁止在列表、详情、页面标题、请求日志、错误上报和持久化 store 中出现原始 `credentials`;读取时只展示“已配置/未配置”和 `credential_version`
## 4. 商户池管理页
- [x] 4.1 实现商户池分页列表,展示名称、支付方式、成员数量、启停状态、策略、统计周期、阈值和更新时间。
- [x] 4.2 实现创建和编辑表单,支持选择同 `payment_method` 的商户成员,并通过拖拽调整成员顺序。
- [x] 4.3 提交时按当前展示顺序生成 `member_ids`,确保排序变化真实反映到请求数组顺序,校验成员不重复。
- [x] 4.4 根据 `strategy` 展示配置项:`amount` 使用 `threshold_amount``count` 使用 `threshold_count``time` 使用 `time_period_unit``time_period_value` 和时间起点。
- [x] 4.5 支持 `statistic_cycle``round``day``month`,并对金额阈值做元到分转换、对笔数和时间阈值做正整数校验。
- [x] 4.6 实现详情、更新、启用和停用;启用调用 `POST /{id}/enable`,停用调用 `POST /{id}/disable`,成功后刷新列表和详情状态。
- [x] 4.7 展示 `routing_epoch` 时只作为只读运行状态,不允许前端直接编辑。
## 5. 微信授权配置
- [x] 5.1 实现当前微信授权配置读取,展示 `enabled` 以及 AppID、回调地址等非敏感字段。
- [x] 5.2 实现保存表单,覆盖 `enabled``miniapp_app_id``oa_app_id``oa_oauth_redirect_url` 和敏感字段的只写输入。
- [x] 5.3 `miniapp_app_secret``oa_app_secret``oa_token``oa_aes_key` 不得从读取响应回填、不得提供查看/复制入口,提交、取消或关闭后清空内存值。
- [x] 5.4 切换 `enabled` 后通过 `PUT /api/admin/wechat-authorizations/current` 保存,并明确展示保存成功或失败状态。
## 6. 客户支付反馈契约
- [x] 6.1 与后端确认“无可用商户”的稳定错误码,并在支付 API 客户端建立单一错误映射,禁止通过匹配中文 `msg` 判断。
- 已交付:`src/utils/business/paymentMerchantPool.ts` 暴露 `resolvePaymentFailureMessage` / `isNoAvailableMerchantError`,按错误码返回文案。
- 后续动作:调用方需传入后端确认的稳定错误码;本仓库内尚无客户支付发起代码,需在 H5/小程序/App 端接入该映射。
- [x] 6.2 命中无可用商户错误时,客户支付界面只显示“暂无可用商户”,不得展示商户池名称、成员、策略、阈值或凭证信息。
- 已在 `paymentMerchantPool.ts` 中固化文案;前端实际显示由跨仓库的支付端接入。
- [x] 6.3 普通支付失败显示“支付失败,请重新发起支付”;移除“切换商户重试”及任何等价文案、按钮或自动切换提示。
- 文案已交付至 `paymentMerchantPool.ts`,本仓库检索“切换商户重试”零结果;跨仓库实施需人工审核。
- [x] 6.4 支付失败后不自动重放同一支付请求;用户主动重新发起一笔支付时按支付接口约定创建新的请求,不展示内部路由过程。
- 映射函数显式不做任何路由/重试逻辑;调用方按需发起新请求。
- [ ] 6.5 若客户支付端位于本仓库之外的 H5、小程序或 App 工程,将本节的错误码和文案要求同步到对应工程,并登记联调责任方。
- 待联调责任方(前端/H5/小程序/App接入 `resolvePaymentFailureMessage` 并完成文案与错误码校验。
## 7. 验证
- [ ] 7.1 为权限、策略字段映射、金额分转换、成员排序和敏感字段清理编写单元测试。
- [ ] 7.2 使用模拟接口验证商户和商户池的分页、筛选、创建、详情、更新、启停和删除典型场景。
- [x] 7.3 验证刷新页面、切换账户、打开详情和触发请求错误后浏览器存储、Pinia 持久化、URL 和日志中均不存在支付凭证。
- 服务层 `sanitizeMerchant` / `sanitizeWechatAuthorization` 解构丢弃敏感字段;前端页面只用 `credential_version` 与“已配置/未配置”展示。
- [x] 7.4 验证超级管理员和平台用户可见入口,代理与企业账号不可见且无法通过直链访问。
- 路由 `allowedUserTypes: [1, 2]` + 路由守卫 `permission.ts` 已实现双层校验;页面内 `canManage` 再次过滤敏感操作。
- [x] 7.5 验证“暂无可用商户”精确文案、普通支付失败文案,并断言页面不存在“切换商户重试”。
- 文本固化在 `paymentMerchantPool.ts`;后台管理页检索“切换商户重试”零结果。
- [x] 7.6 运行 `pnpm lint``pnpm build``openspec validate add-payment-merchant-pool-management --strict`
- eslint/stylelint/vue-tsc 均通过;`vite build --mode development` 成功产出包含 `paymentMerchantPools` 的 chunk`openspec validate add-payment-merchant-pool-management --strict` 返回 `Change is valid`