让代理充值复用现有网页支付能力
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m7s

微信按当前 v2/v3 配置分别生成 MWEB/H5 链接,支付宝复用 C 端 WAP 链接,并让可用支付方式基于生效配置判断。

Constraint: 支付链接统一通过 qr_content 返回,由前端渲染二维码;按要求不运行测试

Rejected: 微信 Native 与支付宝当面付 | 会引入非当前商户配置所需的额外产品开通

Confidence: high

Scope-risk: moderate

Directive: 微信 H5/MWEB 二维码仅承诺系统相机或外部浏览器扫码链路

Tested: 相关 Go 包编译通过;gofmt 与 git diff --check 通过

Not-tested: 按用户要求未运行自动化测试及真实支付联调
This commit is contained in:
2026-07-30 11:41:50 +08:00
parent 0f4f0d1176
commit 8fc667daee
24 changed files with 692 additions and 352 deletions

View File

@@ -6,7 +6,7 @@ Status: ready-for-agent
## Problem Statement
当前代理充值接口只创建本地充值记录,没有真正创建微信 Native 或支付宝 PreCreate 支付单并返回可供前端渲染的付款内容。在线回调直接在一次事务中尝试完成钱包入账,支付事实与钱包处理结果无法独立表达;回调也没有完整校验支付配置、金额、第三方交易号和业务关联。网络超时、回调丢失、重复回调、钱包事务失败和第三方迟到成功都缺少可靠恢复边界。
当前代理充值接口只创建本地充值记录,没有按当前配置复用微信 H5/MWEB 与支付宝 WAP 支付能力返回可供前端渲染的支付 URL。在线回调直接在一次事务中尝试完成钱包入账,支付事实与钱包处理结果无法独立表达;回调也没有完整校验支付配置、金额、第三方交易号和业务关联。网络超时、回调丢失、重复回调、钱包事务失败和第三方迟到成功都缺少可靠恢复边界。
当前同一个创建接口还允许代理或平台提交目标 `shop_id`,平台可以替任意代理创建在线支付,容易混淆真实付款人和受益钱包。线下代充值仍通过本地 `offline-pay``reject` 和全局操作密码完成人工入账,没有接入已经冻结的企业微信审批公共能力;附件仍是字符串 Key 列表,审批结论、充值状态和钱包入账状态也未独立建模。
@@ -16,7 +16,7 @@ Status: ready-for-agent
保留代理充值资源,建立两条严格隔离的创建路径:代理只为当前店铺主钱包选择 `wechat``alipay` 发起在线充值,不提交目标店铺,也不进入审批;平台或超级管理员只为指定代理店铺发起 `offline` 线下代充值,提交固定金额、备注和 15 个结构化付款凭证,并接入 UR#37 的真实企业微信审批。
在线充值为每次用户主动创建生成新的充值单和支付单。微信 Native 或支付宝 PreCreate 返回的字符串或 HTTPS URL 通过 `qr_content` 原样返回,前端自行渲染二维码,后端不生成二维码图片。前端支付状态轮询只读取本地状态;后端通过支付回调和受控查单任务同步第三方真实状态。支付成功先可靠固化收款事实,再由独立 Worker 幂等增加代理主钱包并写唯一流水,钱包失败不回滚支付成功事实。
在线充值为每次用户主动创建生成新的充值单和支付单。微信 H5/MWEB 或支付宝 WAP 返回的 HTTPS URL 通过 `qr_content` 原样返回,前端自行渲染二维码,后端不生成二维码图片。前端支付状态轮询只读取本地状态;后端通过支付回调和受控查单任务同步第三方真实状态。支付成功先可靠固化收款事实,再由独立 Worker 幂等增加代理主钱包并写唯一流水,钱包失败不回滚支付成功事实。
线下充值创建时把充值单、唯一企微审批实例和提交 Outbox 原子落库。企微只能同意或拒绝固定金额;同意后复用与在线充值相同的钱包入账 Worker拒绝后原单终结。无论在线还是线下只要主钱包实际入账成功都向目标代理发送防重的站内到账通知。
@@ -79,7 +79,7 @@ Status: ready-for-agent
- `data` 固定包含:`methods:string[]``min_amount:int64=10000``max_amount:int64=100000000`。没有可用方式时 `methods=[]`,接口本身仍成功。
- 接口不返回商户号、应用私钥、支付通道、支付配置 ID或具体缺失的敏感配置。支付方式顺序固定为 `wechat``alipay`,仅保留可用项。
- 创建接口必须再次校验所选支付方式。配置在查询列表后失效时拒绝创建,不能只信任前端先前取得的列表。
- 微信只有在当前微信支付配置支持本需求所需的扫码预下单、回调验签和查单能力时才视为可用;支付宝只有在 PreCreate 所需参数完整时才视为可用。
- 微信只有在当前微信支付配置支持对应协议的 H5/MWEB 下单、回调验签和查单能力时才视为可用;支付宝只有在 WAP 支付链接签名、回调验签和查单所需参数完整时才视为可用。
### 创建接口与请求幂等
@@ -94,7 +94,7 @@ Status: ready-for-agent
### 在线充值创建与付款内容
- 在线创建先在同一 PostgreSQL 事务写充值单和 `tb_payment`。支付单增加稳定 `order_type=agent_recharge`,关联充值 ID、支付方式、金额、创建时支付配置 ID和支付单号充值单初始 `status=1`,支付单初始 `status=0`,处理状态为 0。
- 微信使用 Native 扫码预下单;支付宝使用 `alipay.trade.precreate`。支付宝不再返回 WAP 支付链接作为本需求的扫码实现
- 微信`provider_type` 使用 v3 H5 返回 `h5_url` 或 v2 MWEB 返回 `mweb_url`;支付宝复用 C 端 `alipay.trade.wap.pay` 签名 URL。前端统一将 HTTPS URL 渲染为二维码,不要求开通微信 Native 或支付宝当面付
- 微信或支付宝返回的二维码码串、协议字符串或 HTTPS URL 原样保存为 `qr_content` 并返回。前端使用二维码组件渲染;后端不生成、上传或返回二维码图片,也不新增“生成二维码”“重新生成二维码”接口。
- 创建成功的在线 `data` 至少包含:`recharge_id``recharge_no``amount``payment_method``qr_content``status/status_name``payment_status/payment_status_name``processing_status/processing_status_name``approval_source=none`。不返回 `expires_at``payment_channel` 或支付配置 ID。
- 本地计算时间不能代表第三方支付订单真实有效期。后台在线充值接口不返回 `expires_at`,前端不展示精确倒计时,也不根据本地时间判定二维码仍然有效。
@@ -235,7 +235,7 @@ Status: ready-for-agent
- HTTP 创建覆盖:代理成功、平台/超管在线拒绝、企业拒绝、请求携带 `shop_id` 拒绝、微信/支付宝可用性、配置在列表后失效、金额 9999/10000/100000000/100000001、支付方式非法和支付方式创建后不可切换。
- 幂等覆盖:同账号同 `request_id` 同载荷返回原单,不同载荷冲突,并发重复只有一张充值单和支付单;新 `request_id` 在金额相同且旧单待支付时仍创建新单。
- Adapter 预下单覆盖微信 Native 与支付宝 PreCreate 成功、明确失败、超时但未创建、超时后第三方已创建、响应丢失、恢复仍未知和重复恢复;断言不会因同一请求再建支付单。
- Adapter 支付链接覆盖微信 v3 H5/v2 MWEB 成功、明确失败、结果未知和支付宝 WAP 本地签名成功/失败;同一请求不得重复创建支付单。
- 响应覆盖原样 `qr_content`、前端可渲染字符串/HTTPS URL、不返回 `expires_at`、支付通道或配置,不创建二维码图片文件。
- 回调覆盖签名/验签失败、订单不存在、业务类型错误、支付方式不符、配置不符、金额不符、第三方交易号冲突、业务关联错误、成功、重复成功和乱序通知。
- 查单覆盖明确待支付、已支付、已关闭/失效、不存在、未知、超时和限流;证明前端状态接口不调用 Adapter查单与回调并发只固化一次支付成功。
@@ -263,7 +263,7 @@ Status: ready-for-agent
- 信息投影分别以平台和代理读取同一线下充值:平台在具备业务权限时可见完整审批资料,代理只能看到业务资料和最小审批摘要;任何响应不返回支付配置、通道或内部错误。
- 迁移演练覆盖支付状态盘点、默认值/注释/约束不一致、历史终态 legacy、可迁移待处理线下单、缺少平台绑定或附件的异常清单、重复执行幂等以及旧 `offline-pay``reject``resubmit` 路由确实不存在。
- 前端验收覆盖可用方式加载、每次主动新建、二维码渲染、无倒计时、3 秒本地轮询、页面隐藏暂停、支付成功/入账处理中/失败、余额刷新、线下表单、企微只读详情、审批与到账两类通知、加载/空/失败状态。
- 本地自动化不要求真实微信或支付宝。部署到测试环境后由用户手工完成一笔微信 Native 和一笔支付宝 PreCreate 最低金额扫码,验证真实付款内容、回调/查单、本地支付状态、钱包入账和到账通知;该人工联调不阻塞本地实现完成门禁,但属于上线前验收。
- 本地自动化不要求真实微信或支付宝。部署到测试环境后按生效配置手工完成一笔微信 H5/MWEB 和一笔支付宝 WAP 最低金额扫码,验证真实支付 URL、回调/查单、本地支付状态、钱包入账和到账通知;该人工联调不阻塞本地实现完成门禁,但属于上线前验收。
- 完成门禁至少包括目标单元/集成测试、相关包测试、全量 Go 测试、并发/竞态专项、静态检查、迁移演练、OpenAPI 生成校验、真实 S3和真实企微线下充值。新增 Handler 时同步两个接口文档生成入口。
## Out of Scope
@@ -284,8 +284,8 @@ Status: ready-for-agent
## Further Notes
- 当前代码已经有代理充值表、主钱包和流水、统一 `tb_payment`、微信回调基础、支付宝 WAP 支付基础及支付配置,但代理充值创建只支持 `wechat/offline`,未创建支付单或返回付款内容;支付宝 PreCreate、微信 Native 后台充值、支付查单补偿和两阶段入账需要补齐。
- 当前代码已经有代理充值表、主钱包和流水、统一 `tb_payment`、微信 H5/MWEB/回调基础、支付宝 WAP 支付基础及支付配置,但代理充值创建只支持 `wechat/offline`,未创建支付单或返回付款内容;代理端复用现有网页支付 URL、支付查单补偿和两阶段入账需要补齐。
- 当前支付配置模型把微信提供方和支付宝参数放在同一条全局生效配置中。UR#34 按现状复用,不把它扩成多通道路由系统。
- 当前微信 v3 已有查单/关单能力,微信 v2适配器缺少查单;支付宝 SDK具备 PreCreate、TradeQueryTradeClose。支付方式可用性必须以本需求实际需要的 Adapter能力为准不能只判断某个字段非空。
- 当前微信 v3 已有查单/关单能力,微信 v2 已补 MWEB 下单与查单;支付宝 SDK 具备 WAP、TradeQueryTradeClose。支付方式可用性必须以本需求实际需要的 Adapter 能力为准,不能只判断某个字段非空。
- 当前 `tb_payment` 迁移写的是 `14`,运行代码和 DTO使用 `03`;这是实施前必须通过存量核查解决的历史一致性问题,不是新 Agent可以忽略的文档差异。
- 当前旧线下充值使用字符串 Key列表、操作密码和本地 `offline-pay/reject`。新实现以本 PRD 和 UR#37公共企微契约为准,旧实现仅用于迁移事实核对,不代表目标行为。