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

97 lines
7.1 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.

# 目标与范围
- 目标:落地微信小程序(JSAPI)支付,完善后台订单管理与退款闭环,支持对账与运营漏斗统计。
- 范围:预下单→前端调起→支付回调→订单状态推进→退款申请/执行→账单对账→后台运营管理。
# 背景与现状
- 已有:订单/订单项/积分流水/工作台漏斗统计与请求日志。
- 工作台漏斗接口:`internal/api/admin/dashboard_admin.go:754`;路由:`internal/router/router.go:72`
- 用户订单查询:`internal/service/user/orders_list.go:16/40`;系统发放订单与订单号生成:`internal/service/user/reward_grant.go:76/220`
- 缺失:微信支付接入(预下单、SDK、证书/签名)、支付回调与幂等、退款接口与模型、对账流程、订单唯一约束与支付幂等、防重复回调处理。
# 总体架构
- 分层Controller(HTTP) → Service(业务/状态机) → Repository(Gorm/DAO) → PayClient(微信支付SDK) → Infra(配置、证书、日志、幂等/锁)。
- 关键域:
- 订单域:`orders/order_items`维持业务订单与行项目。
- 支付域:新增`payment_preorders/payment_transactions/payment_refunds/payment_notify_events/payment_bills`
- 记账域:`user_points_ledger`扩展退款恢复落账。
# 数据模型设计
- `payment_preorders` 预下单记录
- `id``order_id``order_no`(唯一) 、`channel`(wechat_jsapi)、`prepay_id``out_trade_no`(唯一)、`amount_total`(分)、`payer_openid``status`(created/expired/paid)、`notify_url``created_at``expired_at`
- `payment_transactions` 支付成功交易
- `id``order_id``order_no`(唯一) 、`channel``transaction_id`(微信流水号唯一) 、`amount_total``success_time``raw`(JSON) 、`created_at`
- `payment_refunds` 退款记录
- `id``order_id``order_no``refund_no`(唯一) 、`channel``status`(submitted/success/abnormal/closed) 、`amount_refund`(分/支持部分退款) 、`reason``raw`(JSON) 、`created_at``success_time`
- `payment_notify_events` 回调事件
- `id``notify_id`(唯一) 、`resource_type``event_type``summary``raw`(JSON) 、`processed`(bool) 、`created_at`
- `payment_bills`/`payment_bill_diff` 对账与差异
- `bill_date``type`(tradebill/refundbill) 、`file_url``digest``imported`;差异记录`local_tx_id/wechat_tx_id/diff_type/diff_detail`
- 约束与索引:`orders.order_no`唯一索引;`payment_*`关键幂等字段唯一索引;`notify_id/out_trade_no/transaction_id/refund_no`均唯一。
# 接口设计
- App(用户态)
- `POST /api/app/pay/wechat/jsapi/preorder`:入参`order_no/openid`,出参`timeStamp/nonceStr/package(pay=prepay_id)/signType/paySign`
- `GET /api/app/orders/:order_no/payment`:查询订单支付状态与交易详情。
- Pay通知(平台回调)
- `POST /api/pay/wechat/notify`:验签/解密后入库`payment_notify_events`,幂等推进订单状态,写`payment_transactions`,更新`orders.status=2/paid_at`
- Admin(运营态)
- `GET /api/admin/pay/orders`:订单列表(筛选:状态、时间、渠道)。
- `POST /api/admin/pay/refunds`:创建退款,入参`order_no/amount/reason`;支持全/部分退款。
- `GET /api/admin/pay/refunds`/`GET /api/admin/pay/refunds/:refund_no`:查询退款状态。
- `POST /api/admin/orders/:order_no/close`:关闭未支付订单(同时调用微信`close`)。
- 漏斗统计继续沿用现有接口,支付口径改为“支付交易成功”(来源于transactions)。
# 业务流程
- 预下单(JSAPI)
- 校验订单`status=1`与金额,绑定`openid`→调用`/v3/pay/transactions/jsapi`→落库`payment_preorders`并返回客户端调起参数。参考“JSAPI预下单与签名串”[微信支付文档]。
- 前端调起
- 小程序端`wx.requestPayment`使用服务端返回的`timeStamp/nonceStr/package/signType/paySign`
- 支付回调
- 后端接收`notify`→验签(平台证书)与解密→事件幂等检查(`notify_id`)→查询交易状态或直接推进→更新`orders`为已支付,写`payment_transactions`与触发履约逻辑(虚拟商品使用`is_consumed`)。
- 失败重试
- 回调验签失败/解密失败→告警并拒收;订单未推进→后台定时查询`/v3/pay/transactions/out-trade-no/{out_trade_no}`兜底。
- 退款
- 管理端创建退款→调用`/v3/refund/domestic/refunds`→落库`payment_refunds`→回调/查询成功后更新为`success`并写`user_points_ledger(action=refund_restore)`与订单状态`4已退款`(支持部分退款:订单保持`2已支付`,以累计退款判断)。
- 对账
- 每日拉取交易/退款账单→入库`payment_bills`→与本地`payment_transactions/payment_refunds`比对→生成差异`payment_bill_diff`→运营报表与修复。
# 幂等与一致性
- 订单:`order_no`唯一;预下单多次返回同一`prepay_id`;使用`out_trade_no=order_no`作为业务幂等键。
- 回调:`notify_id`去重;状态推进使用原子事务与“当前状态→新状态”的校验。
- 退款:`refund_no`唯一;重复请求直接返回现有状态。
- 事务Service层统一开启Gorm事务对并发推进加行级乐观锁或显式`UPDATE ... WHERE status=...`
# 配置与密钥管理
- `.env`加载:`WECHAT_APPID/WECHAT_MCHID/WECHAT_SERIAL_NO/WECHAT_PRIVATE_KEY_PATH/WECHAT_API_V3_KEY/WECHAT_NOTIFY_URL`
- 证书落盘PEM私钥与平台证书SDK负责签名与应答验签。禁止将密钥提交仓库。
# SDK选型与规范
- 后端Go采用官方`/wechatpay-apiv3/wechatpay-go`(API v3支持签名/验签/回调解密)。
- 按微信文档“JSAPI签名串四行格式与RSA签名”构造客户端参数。
# 安全与合规
- 验签必做;来源白名单;请求体原样落库审计。
- 金额单位统一“分”;防止小数误差;禁止信任前端金额。
- 日志与告警:失败重试/签名失败/金额不一致必须告警。
# 测试与验收
- 单元:签名参数构造、金额边界、幂等推进、退款部分/全额。
- 集成:模拟回调事件、订单查询兜底、对账导入与差异比对。
- 验收标准:
- 小程序端正常拉起并支付成功,后台订单状态正确推进;
- 管理端可发起退款并正确落账;
- 回调/对账全链路无漏处理且有幂等保障;
- 漏斗“支付用户/完成订单”口径与交易/发货一致。
# 实施步骤
1. 引入微信支付Go SDK与配置加载建立PayClient与证书管理。
2. 建表与唯一索引:`orders.order_no``payment_*`系列关键字段唯一。
3. 实现预下单接口,返回前端调起参数并记录`payment_preorders`
4. 实现支付回调路由:验签/解密→事件入库→幂等推进订单与交易记录。
5. 实现退款接口与回调处理;联动`user_points_ledger`落账。
6. 实现对账拉取与差异比对;补充运营漏斗统计数据来源为交易表。
7. 覆盖测试与监控告警;上线灰度并观察。
# 参考文档(已核对)
- JSAPI预下单与签名串、调起参数与`prepay_id`有效期:`/websites/pay_weixin_qq_doc_v3`
- 官方Go SDK`/wechatpay-apiv3/wechatpay-go`