5.3 KiB
5.3 KiB
name, overview, todos
| name | overview | todos | |||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 修复支付业务逻辑问题 | 修复二次审查发现的支付业务问题:2 个资损级缺陷(虚拟支付订单取消漏洞、道具价格不同步)+ 5 个逻辑缺陷(iOS 最低价校验、退款状态判断、PaidTime 兜底等)+ 2 处文档同步,全部在现有支付代码上做定点修复。 |
|
产品概述
对支付业务逻辑二次审查发现的 2 个资损级问题、5 个逻辑缺陷与 2 个文档问题做定点修复,不改变支付链路整体架构与权益发放回退幂等机制。
核心修复内容
P0 资损级
- P0-1 虚拟支付订单取消漏洞:虚拟支付订单(pay_channel=2)不可再取消(新增 70007 错误码);发货推送补「已取消订单补发货」防御分支,杜绝「用户取消后继续支付、钱已扣但权益永不发放」。
- P0-2 道具价格不同步:道具同步改为全量刷新全部上架商品(含已发布),每次启动重新上传发布道具信息与价格,保证微信侧道具价格与本地改价一致,避免金额校验失败导致付款不发货。
P1 逻辑缺陷
- iOS 下单校验最低 1 元(100 分),低于此金额拒绝(70008)。
- 退款推送仅「成功」状态才回退权益,防中间状态误回退。
- 发货推送 PaidTime 缺失或异常时兜底为当前时间。
- iOS 退款问询保持默认建议退款,补充策略注释。
P2 文档与提示
- 订单响应增加 pay_channel 字段(1=微信支付 2=虚拟支付)。
- 接口文档补充虚拟支付退款操作路径(虚拟支付后台 Midas)、道具价格刷新运营约定、新错误码说明。
技术方案
修复策略
定点修复,复用现有架构与幂等机制:不动 benefit_grant_tasks 发放凭证、唯一索引幂等、settleRefundSuccess/revokeOrderBenefits 回退链路;不新增表结构与迁移 SQL。
关键改动
1. 错误码(pkg/errcode/order_code.go)
- 新增
VirtualOrderCancelNotAllowed = NewError(70007, "虚拟支付订单不支持取消") - 新增
VirtualPayAmountTooLow = NewError(70008, "iOS 虚拟支付最低 1 元") - 70007/70008 空闲无冲突(70005/70006 已占用)。
2. 取消漏洞(internal/service/order.go + virtualpay.go)
Cancel:getOwnedOrder后加if order.PayChannel == PayChannelVirtual { return nil, errcode.VirtualOrderCancelNotAllowed }(置于状态校验前,统一拒绝提示);同时避免对虚拟订单误调 JSAPICloseOrder。handleGoodsDeliver:switch 增加case OrderStatusCancelled:,条件流转Cancelled → Paid成功后finalizeVirtualPaidOrder补发货,与Expired分支并列(防御历史数据与竞态)。
3. 道具全量同步(internal/mysqldao/goods.go + virtualpay.go)
GoodsListVirtualSync查询条件改为Where("status = ?", 1),返回全部上架商品(含已发布)。SyncVirtualGoods/syncOneGoods注释更新为全量同步语义:重复 upload+publish 同 goods_id 视为更新道具信息与价格;商品 SKU 少(5 类),启动一次开销可忽略;失败仍置GoodsProductPublishFail。
4. P1 系列(internal/service/virtualpay.go)
VirtualOrderCreate:goods 上架校验后、落单前加if request.Platform == XPayPlatformIOS && payAmount < 100→ 返回 70008。handleRefundNotify:仅RefundStatus == ""或== "SUCCESS"时调用settleRefundSuccess,其他状态slog.WarnContext记录并返回(枚举联调确认)。finalizeVirtualPaidOrder:paidTime <= 0时兜底nowUnix()。handleIOSRefundQuery:补充策略注释(默认建议退款、已用权益不回退、后续可按权益使用情况细化拒绝)。
5. 文档与 DTO(internal/dto/order.go + service/order.go + 接口文档.md)
OrderResponse加PayChannel int8 json:"pay_channel";buildOrderResponse加映射。- 接口文档:订单对象(4.5 节)补 pay_channel 字段;退款章节补「虚拟支付订单请在虚拟支付后台(Midas)发起退款」;虚拟支付下单章节补 70007/70008 说明与「改价后重启服务自动刷新道具价格」运营约定;错误码表补 70007/70008。
验证
go build ./...、go vet ./...、go test ./pkg/wechat/通过。- read_lints 检查改动文件无新增错误。
约束
- 不改支付架构、权益幂等机制、表结构;不修改 configs/config.yaml(本地文件,含非法 YAML)。