Files
junhong_cmp_fiber/docs/feature-034-agent-wallet-qr-recharge/代理钱包扫码充值接口对接说明.md
break 8fc667daee
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: 按用户要求未运行自动化测试及真实支付联调
2026-07-30 11:41:50 +08:00

13 KiB
Raw Blame History

代理钱包扫码充值实现与接口对接说明

面向:产品、前端和联调人员
范围:代理微信/支付宝桌面扫码自充、平台线下代充来源区分、支付状态轮询
接口细节:以 docs/admin-openapi.yaml 为准,本文说明前端调用顺序、字段口径和页面状态。

一、先看这几个关键结论

  1. 同一个创建接口有两条业务路径:代理账号使用 wechat|alipay 在线自充;平台或超级管理员使用 offline 线下代充。
  2. 前端必须使用 recharge_source 区分来源platform_offline 是平台线下代充,agent_online 是代理在线自充;不要根据账号名称、备注或审批字段猜测。
  3. 代理不能选择充值店铺:在线充值的店铺和主钱包由登录上下文确定,请求不得发送 shop_id、支付凭证或备注。
  4. 二维码由前端渲染:后端在 qr_content 返回支付 HTTPS URL不返回二维码图片。
  5. 网络重试不能创建新请求 ID:同一次提交重试复用原 request_id;用户主动发起下一笔充值时生成新的 request_id
  6. 支付和钱包到账是两个阶段status=2 表示第三方已收款、钱包入账处理中;只有 status=3 才表示钱包到账完成。
  7. 页面轮询只调用本地状态接口:前端不得直接调用微信、支付宝查单,也不要反复调用创建接口查询状态。
  8. 在线金额单位为分:最低 10000100 元),最高 100000000100 万元);不要提交浮点元金额。

二、本次需求怎么实现

能力 后端实现 前端要做什么
可用支付方式 根据当前有效支付配置返回真正可用的 wechatalipay 打开充值弹窗时先查询;只展示返回数组中的方式
代理在线自充 从登录账号取得当前店铺和主钱包,创建充值单、支付单并按配置生成微信 v3 H5/v2 MWEB 或支付宝 WAP 支付 URL 只提交金额、支付方式和请求 IDqr_content 渲染二维码
平台线下代充 保留既有目标店铺、凭证和企业微信审批流程 平台页面继续提交 offline 请求并只读展示审批状态
充值来源 根据受控创建方式返回稳定来源枚举 列表、详情和支付状态统一展示 recharge_source_name
支付确认 微信/支付宝回调确认第三方收款事实 前端无需调用回调接口
钱包入账 Outbox/Worker 幂等增加代理主钱包余额 status=2 展示“入账处理中”,status=3 展示“已到账”
回调丢失恢复 Worker 使用原支付单号主动查单并收敛状态 页面继续轮询本地状态,无需提供“重新查单”按钮

三、接口对接表

页面动作 接口 前端调用说明
打开代理在线充值弹窗 GET /api/admin/agent-recharges/payment-methods 仅代理账号调用;返回支付方式和金额上下限
创建在线扫码充值 POST /api/admin/agent-recharges 代理只传 amount + payment_method + request_id
创建平台线下代充 POST /api/admin/agent-recharges 平台/超级管理员传 shop_id + amount + payment_method=offline + payment_voucher_key + remark
查询充值列表 GET /api/admin/agent-recharges 支持 `recharge_source=platform_offline
查询充值详情 GET /api/admin/agent-recharges/:id 使用返回的来源、充值状态和审批状态展示
轮询在线支付状态 GET /api/admin/agent-recharges/:id/payment-status 仅在线单使用;页面可见时每 3 秒调用,终态停止
支付回调 微信/支付宝既有回调地址 只由支付渠道调用,前端禁止调用

所有接口都使用 Bearer Token成功响应统一为

{
  "code": 0,
  "msg": "success",
  "data": {},
  "timestamp": "2026-07-27T16:00:00+08:00"
}

前端应同时检查 HTTP 状态和响应体 code,失败时优先展示后端返回的 msg

四、代理在线扫码充值调用流程

4.1 查询可用支付方式

GET /api/admin/agent-recharges/payment-methods
Authorization: Bearer {token}

响应示例:

{
  "code": 0,
  "msg": "success",
  "data": {
    "methods": ["wechat", "alipay"],
    "min_amount": 10000,
    "max_amount": 100000000
  },
  "timestamp": "2026-07-27T16:00:00+08:00"
}

前端处理规则:

  • methods=[]:隐藏或禁用提交按钮,提示“当前暂无可用在线支付方式”。
  • 只显示返回的支付方式,不自行补充微信或支付宝。
  • 金额校验直接使用返回的 min_amountmax_amount,提交值仍为整数分。
  • 平台、超级管理员和企业账号不调用此接口。

4.2 创建在线充值单

POST /api/admin/agent-recharges
Authorization: Bearer {token}
Content-Type: application/json

微信请求示例:

{
  "amount": 10000,
  "payment_method": "wechat",
  "request_id": "recharge-20260727-8f73d95d"
}

支付宝只需将 payment_method 改为 alipay

在线请求禁止发送:

  • shop_id
  • payment_voucher_key
  • remark
  • 商户号、应用 ID、密钥、支付配置 ID

成功响应示例:

{
  "code": 0,
  "msg": "success",
  "data": {
    "recharge_id": 101,
    "recharge_no": "ARCH20260727160000123456",
    "payment_no": "PAY20260727160000987654",
    "payment_method": "wechat",
    "recharge_source": "agent_online",
    "recharge_source_name": "代理在线自充",
    "amount": 10000,
    "qr_content": "https://pay.example.com/...",
    "status": 1,
    "status_name": "待支付"
  },
  "timestamp": "2026-07-27T16:00:00+08:00"
}

前端处理规则:

  1. qr_content 原样交给二维码组件,不解析、不改写、不拼接。
  2. 二维码页面保存 recharge_id,后续轮询使用该 ID不使用 payment_no 查询。
  3. 同一次请求超时或网络断开时,重试必须复用原 request_id;后端会返回原充值单和原二维码内容。
  4. 用户关闭弹窗后重新点击“立即充值”,视为新一笔主动提交,必须生成新的 request_id
  5. 相同 request_id 改变金额或支付方式会返回冲突,前端不得自动覆盖原请求。

4.3 轮询支付和到账状态

GET /api/admin/agent-recharges/101/payment-status
Authorization: Bearer {token}

响应示例:

{
  "code": 0,
  "msg": "success",
  "data": {
    "recharge_id": 101,
    "recharge_no": "ARCH20260727160000123456",
    "recharge_source": "agent_online",
    "recharge_source_name": "代理在线自充",
    "status": 2,
    "status_name": "已支付",
    "payment_status": 1,
    "payment_status_name": "已支付",
    "paid_at": "2026-07-27 16:01:20",
    "completed_at": null
  },
  "timestamp": "2026-07-27T16:01:21+08:00"
}

页面建议每 3 秒轮询一次,仅在二维码弹窗可见时执行。按以下状态展示:

status 含义 页面展示 是否继续轮询
1 待支付 等待用户扫码付款
2 已支付 支付成功,钱包入账处理中
3 已完成 充值成功,钱包已到账
4 已关闭 订单已关闭,请重新发起充值
5 已退款 已退款
6 已驳回 已驳回

payment_status 的值为:0=待支付1=已支付2=已失败3=已退款。页面主流程优先根据充值 status 判断;payment_status 用于补充支付阶段文案。

进入 status=3 后,前端刷新钱包余额和充值列表。不要在 status=2 时提前增加页面余额。

五、平台线下代充调用流程

平台或超级管理员继续调用同一个创建接口:

{
  "shop_id": 20,
  "amount": 50000,
  "payment_method": "offline",
  "payment_voucher_key": ["recharge-voucher/20260727/abc.png"],
  "remark": "银行转账"
}

线下代充响应和后续列表/详情会返回:

{
  "recharge_source": "platform_offline",
  "recharge_source_name": "平台线下代充",
  "approval_provider": "wecom",
  "approval_status": 1,
  "approval_status_name": "审批中"
}

前端处理规则:

  • 代理账号不得展示线下代充表单。
  • 平台线下单展示凭证、备注和企微审批状态,不展示扫码二维码。
  • 存在 approval_instance_idapproval_provider=wecom 时,只读展示审批进度,不显示旧的本地确认/驳回按钮。
  • 在线充值的 approval_instance_idnull,不要显示企微审批区域。
  • /:id/payment-status 是在线支付状态接口,线下代充详情使用 GET /:id,不要轮询支付状态接口。

六、列表和详情对接

列表请求示例:

GET /api/admin/agent-recharges?page=1&page_size=20&recharge_source=agent_online&status=1

可用筛选参数:

参数 说明
page 页码,默认 1
page_size 每页条数,默认 20最大 100
shop_id 店铺 ID按既有数据权限生效
status 充值状态 16
recharge_source platform_offlineagent_online
start_date 开始日期,格式 YYYY-MM-DD
end_date 结束日期,格式 YYYY-MM-DD

列表成功响应的分页数据位于:

{
  "data": {
    "items": [],
    "total": 0,
    "page": 1,
    "size": 20
  }
}

建议列表至少展示:充值单号、店铺、金额、recharge_source_name、支付方式、status_name、提交人和创建时间。

详情接口:

GET /api/admin/agent-recharges/{id}

页面分支必须以 recharge_source 为准:

  • agent_online:展示支付方式、第三方流水号、支付时间、完成时间;隐藏凭证和企微审批操作。
  • platform_offline:展示支付凭证、备注、提交人和企微审批状态;隐藏二维码和在线轮询区域。

七、充值来源与状态字段

7.1 充值来源

字段值 中文名 创建人和路径
platform_offline 平台线下代充 平台/超级管理员提交 payment_method=offline
agent_online 代理在线自充 代理提交 `payment_method=wechat

前端展示中文时优先使用后端返回的 recharge_source_name,业务分支使用稳定枚举 recharge_source

7.2 充值状态

状态 名称 说明
1 待支付 在线单等待扫码;线下单等待审批
2 已支付 第三方收款已确认,钱包可能仍在入账
3 已完成 钱包余额和唯一流水已提交
4 已关闭 在线支付关闭或预下单失败
5 已退款 充值已退款
6 已驳回 线下代充审批驳回

八、权限和错误处理

操作 平台/超级管理员 代理账号 企业账号
创建在线扫码充值 禁止 仅当前店铺主钱包 禁止
创建线下代充 允许 禁止 禁止
查询在线支付方式 禁止 允许 禁止
查询列表/详情 按既有数据范围 按店铺层级数据范围 禁止
查询在线支付状态 按既有数据范围 按店铺层级数据范围 禁止

前端不要根据错误文案判断资源是否存在。无权限或资源不可见时,后端可能统一返回“无权限操作该资源或资源不存在”。常见处理:

  • 400:保留表单输入并展示参数错误,不自动重试。
  • 401:按现有登录失效流程处理。
  • 403:关闭无权限操作入口,不尝试换账号类型绕过。
  • 409 或业务冲突码:检查是否错误复用了 request_id
  • 500/超时:在线创建可使用原 request_id 重试一次;不要生成新 ID否则可能创建第二张充值单。

九、前端本期最容易漏掉的工作

  • 在线充值表单不要复用线下表单对象后整体序列化,避免携带 shop_id、凭证或备注。
  • 支付方式必须来自 /payment-methods,不要写死微信和支付宝都可用。
  • 金额显示元、提交分;禁止使用浮点数直接乘除后提交。
  • 二维码内容原样渲染,不记录到埋点、错误日志或浏览器持久化缓存。
  • 同一次网络重试复用 request_id,新一笔主动充值换新 ID。
  • status=2 只表示已收款、入账中,不能提前刷新成“钱包已到账”。
  • 列表、详情的页面分支使用 recharge_source,不要用 payment_method 或审批字段猜来源。
  • 线下单不调用支付状态接口;在线单不展示企微审批按钮。
  • 页面隐藏或浏览器切到后台时停止轮询,恢复可见后再继续。
  • 进入终态后停止轮询并刷新钱包余额、充值列表。

十、联调和验收边界

  • OpenAPI 已包含 /payment-methods、在线创建、列表来源筛选、详情来源字段和 /payment-status
  • 后端已完成微信 v3 H5/v2 MWEB、支付宝 WAP 支付 URL、支付确认、异步钱包入账和回调丢失恢复的代码装配。
  • 当前交付已通过 go build ./...go vet ./... 和 OpenSpec 严格校验。
  • 按需求方要求,本次未启动 API/Worker未连接 PostgreSQL/Redis未调用真实支付渠道未发送真实回调也未运行自动化测试。
  • 前端联调环境需具备完整支付配置;至少确认微信和支付宝创建响应分别返回非空 qr_content
  • 本需求不支持 JSAPI、H5、WAP、同设备拉起支付、主动取消、支付方式切换、二维码图片接口或在线退款。