bindbox-game/.trae/documents/微信支付全量真实接入与后台订单_退款_对账方案.md
邹方成 6ee627139c
Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 40s
feat: 新增支付测试小程序与微信支付集成
feat(pay): 添加支付API基础结构
feat(miniapp): 创建支付测试小程序页面与配置
feat(wechatpay): 配置微信支付参数与证书
fix(guild): 修复成员列表查询条件
docs: 更新代码规范文档与需求文档
style: 统一前后端枚举显示与注释格式
refactor(admin): 重构用户奖励发放接口参数处理
test(title): 添加称号效果参数验证测试
2025-11-17 00:42:08 +08:00

6.1 KiB
Raw Blame History

目标

  • 以微信支付 API v3 的真实流程实现:小程序 JSAPI 预下单→前端调起→支付回调验签与解密→订单推进→退款(全额/部分)→账单拉取与对账→管理端完整的订单/退款展示与操作。
  • 严格按金额单位“分”、幂等与安全规范落地;所有敏感配置走环境变量与证书文件。

架构与分层

  • Controllerinternal/api/*app 用户态、admin 运营态、pay 通知态)
  • Serviceinternal/service/pay/*(支付域核心:预下单、推进、退款、对账、状态机与幂等)
  • Repositoryinternal/repository/mysql/*(新增支付域模型与 DAO扩展索引
  • PayClientinternal/pkg/pay/*(微信官方 Go SDK client 初始化、回调验签与解密、账单下载)
  • Infra配置与证书、日志、告警、幂等键与重试策略。

数据模型(新增表与索引)

  1. payment_preorders
  • id PK、order_idorder_no(唯一)、channel(wechat_jsapi)、prepay_idout_trade_no(唯一)、amount_total(分)、payer_openidstatus(created/expired/paid)、notify_urlcreated_atexpired_at
  • 索引:order_no 唯一、out_trade_no 唯一
  1. payment_transactions
  • id PK、order_idorder_no(唯一)、channeltransaction_id(微信流水号唯一)、amount_totalsuccess_timeraw(JSON)、created_at
  • 索引:transaction_id 唯一、order_no 唯一
  1. payment_refunds
  • id PK、order_idorder_norefund_no(唯一)、channelstatus(submitted/success/abnormal/closed)、amount_refund(分)、reasonsuccess_timeraw(JSON)、created_at
  • 索引:refund_no 唯一、order_no 索引
  1. payment_notify_events
  • id PK、notify_id(唯一)、resource_typeevent_typesummaryraw(JSON)、processed(bool)、created_at
  • 索引:notify_id 唯一
  1. payment_bills / payment_bill_diff
  • 账单拉取与差异记录,支持日级对账
  1. 订单表约束
  • orders.order_no 唯一索引;基于现有字段建立缺失索引

配置与证书

  • 环境变量:WECHAT_APPID/WECHAT_MCHID/WECHAT_SERIAL_NO/WECHAT_PRIVATE_KEY_PATH/WECHAT_API_V3_KEY/WECHAT_NOTIFY_URL
  • 证书路径:./configs/cert/apiclient_key.pem(商户私钥);平台证书走 SDK 自动下载与缓存(WithWechatPayAutoAuthCipher),无需入库
  • 不提交任何密钥与证书文件到仓库

SDK与真实流程

  1. 预下单JSAPI
  • 初始化 clientoption.WithWechatPayAutoAuthCipher(mchid, serial_no, private_key, api_v3_key)
  • 调用 services/payments/jsapi.JsapiApiService.Prepay(或 PrepayWithRequestPayment)生成 prepay_id
  • 使用四行签名串 RSA-SHA256 构造小程序 wx.requestPayment 参数
  • 落库 payment_preordersout_trade_no=order_no 幂等
  1. 支付回调notify
  • 使用 notify.NewNotifyHandler(api_v3_key, NewSHA256WithRSAVerifier(certificateVisitor)) 验签并解密得到 payments.Transaction
  • 幂等:notify_id 去重;如已处理直接 ACK
  • 状态推进:WHERE status=1 条件更新订单为已支付,写入 payment_transactions,记录交易时间与原始报文
  • 失败场景兜底:按 out_trade_no 定时查询交易状态
  1. 退款(真实):
  • 管理端创建退款:生成 refund_no 并调用 SDK services/refunddomestic(具体路径以官方包为准),成功回写 payment_refunds 与回调推进;支持部分/全额退款
  • 数据还原:积分恢复按策略记录 user_points_ledger(action=refund_restore);订单全额退款置 status=4,部分退款保持 status=2 并维护累计退款
  • 幂等:refund_no 唯一;重复请求返回已有结果
  1. 对账:
  • 下载交易/退款账单 GET /v3/bill;入库 payment_bills;比对本地 payment_transactions/payment_refunds 生成 payment_bill_diff;支持导出与修复流程

后端接口(最终版)

  • App
    • POST /api/app/pay/wechat/jsapi/preorder(真实预下单,返回调起参数)
    • GET /api/app/orders/:order_no/payment(查询支付状态)
  • Pay通知
    • POST /api/pay/wechat/notify(真实验签与解密,推进订单与交易)
  • Admin
    • 订单列表/详情/备注/取消/履约(已实现基础版,依据真实交易补充支付字段)
    • POST /api/admin/pay/refunds(真实退款)/查询退款列表与详情
    • 导出与对账入口:GET /api/admin/pay/orders/exportPOST /api/admin/pay/bills/import

前端管理端orders模块

  • 列表与详情中文枚举显示(已完成基础);补充:展示真实 transaction_idrefund_nochannel支付方式
  • 退款入口:支持部分退款(金额/原因),显示可退余额;展示退款记录(来源 payment_refunds
  • 对账入口:载入对账结果与差异列表

幂等与安全

  • 业务幂等键:order_no(预下单/订单推进)、notify_id(回调)、refund_no(退款)
  • 事务Service 层统一事务包裹;状态推进以条件更新控制并发
  • 日志与告警:回调验签失败、金额不一致、退款异常、对账差异均告警

测试与验收

  • 单元:签名参数构造、金额边界、幂等推进、退款全额/部分、回调解析
  • 集成:模拟回调事件、订单查询兜底、账单导入与差异比对
  • 验收标准:
    • 小程序支付全链路通;订单与交易记录准确;
    • 管理端退款成功并正确落账与还原;
    • 对账拉取与差异比对可用;
    • 漏斗“支付用户/完成订单”口径对齐真实交易。

实施阶段

  1. 数据库与DAO新增 payment_* 表与索引生成模型与DAO
  2. SDK接入统一初始化 client预下单返回参数notify 验签与解密退款API封装
  3. 业务实现:订单推进、幂等、退款落账与数据还原
  4. 前端完善:展示交易/退款字段、可退余额、退款记录;对账入口
  5. 测试与联调:完成单元与集成测试;灰度上线观测

依赖

  • 官方 Go SDKgithub.com/wechatpay-apiv3/wechatpay-goAPI v3
  • 证书:商户私钥 PEM平台证书自动下载与缓存