Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 40s
feat(pay): 添加支付API基础结构 feat(miniapp): 创建支付测试小程序页面与配置 feat(wechatpay): 配置微信支付参数与证书 fix(guild): 修复成员列表查询条件 docs: 更新代码规范文档与需求文档 style: 统一前后端枚举显示与注释格式 refactor(admin): 重构用户奖励发放接口参数处理 test(title): 添加称号效果参数验证测试
97 lines
7.1 KiB
Markdown
97 lines
7.1 KiB
Markdown
# 目标与范围
|
||
- 目标:落地微信小程序(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` |