148 lines
8.5 KiB
Markdown
148 lines
8.5 KiB
Markdown
---
|
||
name: 修复中高等级代码问题
|
||
overview: 修复三次代码审查报告中「中等及以上」问题(排除限流 M11、虚拟订单垃圾堆积 M15):广告激励加配置开关+服务端定价、退款改为管理员操作、XPay 退款反查、vip_type 推导、iOS 退款问询、platform 校验、pay_time 兜底、上传请求体限制。
|
||
todos:
|
||
- id: adreward-config
|
||
content: 新增 AdReward 配置段与错误码,改造广告激励为开关加服务端定价
|
||
status: completed
|
||
- id: xpay-refund-verify
|
||
content: 新增微信侧退款查询并接入 XPay 退款推送反查
|
||
status: completed
|
||
- id: refund-manual-review
|
||
content: 重写自动退款为待审核退款单并兼容已取消订单退款流转
|
||
status: completed
|
||
- id: vip-type-derive
|
||
content: 改造 VIPGrantIdempotent 按最终到期时长推导会员类型
|
||
status: completed
|
||
- id: virtualpay-fixes
|
||
content: 修复 iOS 退款问询、平台真实性校验与支付时间兜底
|
||
status: completed
|
||
- id: upload-body-limit
|
||
content: 上传 handler 入口增加请求体大小限制
|
||
status: completed
|
||
- id: update-report-verify
|
||
content: 更新审查报告修复状态并执行编译与静态检查验证
|
||
status: completed
|
||
dependencies:
|
||
- adreward-config
|
||
- xpay-refund-verify
|
||
- refund-manual-review
|
||
- vip-type-derive
|
||
- virtualpay-fixes
|
||
- upload-body-limit
|
||
---
|
||
|
||
## 用户需求
|
||
|
||
针对三次代码审查报告,修复中等及以上问题(排除公开接口限流、虚拟支付订单禁取消带来的垃圾订单堆积两项),并落实两项产品调整:
|
||
|
||
1. **广告激励配置化与防刷**:广告激励额度在 config 中配置「是否开启」;每种 reward_type 的发放金额改为服务端配置固定值,前端不再传金额,从根源杜绝刷额度。
|
||
2. **退款管理员操作**:取消订单自动调微信退款的行为改为生成待审核退款单,由管理员在后台手动退款,所有退款均由管理员操作。
|
||
3. **修复范围**:严重问题 S1-new(XPay 退款推送无反查)、S2-new(广告激励刷额度);中等问题 M1-new(自动退款卡死)、M2-new(会员类型覆盖)、M3(iOS 退款问询无条件建议退款)、M4(platform 可伪造)、M9(并发支付时间无兜底)、M12(上传请求体无大小限制)。
|
||
|
||
## 核心功能
|
||
|
||
- 广告激励开关关闭时接口返回明确的「未开启」错误;开启后按服务端配置金额发放,前端仅传奖励类型与广告记录 ID。
|
||
- XPay 退款推送在处理前反查微信侧退款真实性,未通过拒绝发放并触发微信重试。
|
||
- 取消后已付款订单生成待审核退款单,退款回调兼容「已取消」订单的退款流转,且不误回收从未发放的权益。
|
||
- 会员续费时会员类型按最终到期时长自动推导,年度会员续月包不再被降级。
|
||
- iOS 退款问询按权益消耗情况细化同意/拒绝。
|
||
- 虚拟支付发货时校验微信侧真实平台,支付时间统一兜底。
|
||
- 上传接口在解析 multipart 前限制请求体大小。
|
||
|
||
## 视觉/交互
|
||
|
||
本任务为后端逻辑修复,不涉及界面视觉与交互变更。
|
||
|
||
## 技术栈
|
||
|
||
- 语言:Go 1.27
|
||
- 框架:Gin v1.12、GORM + MySQL(含 soft_delete)、go-redis v9、viper(仅读 YAML)
|
||
- 微信:微信支付 V3 官方 SDK、小程序虚拟支付(XPay)自研 HMAC-SHA256 签名客户端
|
||
- 复用项目既有模式:`errcode` 语义化错误、事务幂等、best-effort 告警、`*int64` 配置指针区分「未配置/显式 0」
|
||
|
||
## 实现方式
|
||
|
||
按 8 个修复点分 6 组独立实施,均沿既有分层(handler → service → dao / pkg 客户端)推进,不改动架构:
|
||
|
||
1. **广告激励(S2)**:新增 `AdReward` 配置段与错误码,DTO 移除金额字段,`Grant` 校验开关并从配置取金额。
|
||
2. **XPay 退款反查(S1)**:`wechat` 层补退款状态查询,`handleRefundNotify` 在权益回退前反查微信侧真实性。
|
||
3. **退款管理员操作(M1)**:`autoRefundCancelledOrder` 重写为待审核退款单,`settleRefundSuccess` 兼容「已取消」订单。
|
||
4. **会员类型推导(M2)**:`VIPGrantIdempotent` 原生 SQL 按最终到期时长推导会员类型。
|
||
5. **虚拟支付细节(M3/M4/M9)**:iOS 退款问询细化、平台真实性校验、支付时间兜底。
|
||
6. **上传限制(M12)**:handler 入口加 `http.MaxBytesReader`。
|
||
|
||
## 架构设计
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[config AdReward] --> B[adreward.Grant]
|
||
B --> C[QuotaGrant]
|
||
|
||
D[XPay 退款推送] --> E[handleRefundNotify]
|
||
E --> F[QueryOrder 反查]
|
||
F --> G[settleRefundSuccess]
|
||
|
||
H[PayNotify Cancelled] --> I[autoRefundCancelledOrder]
|
||
I --> J[待审核 RefundFlowLog]
|
||
|
||
K[grantVIP] --> L[VIPGrantIdempotent SQL 推导类型]
|
||
|
||
M[Upload handler] --> N[MaxBytesReader] --> O[service.Upload]
|
||
```
|
||
|
||
## 目录结构
|
||
|
||
以下为本次修改/新增的文件:
|
||
|
||
```
|
||
zt-closet-backend/
|
||
├── configs/
|
||
│ └── config.example.yaml # [MODIFY] 新增 AdReward 配置段(Enable + 各类型金额,含注释)
|
||
├── global/
|
||
│ └── setting.go # [MODIFY] 注册 AdRewardSetting 全局指针
|
||
├── main.go # [MODIFY] setupSetting() 读取 AdReward 段并做默认值兜底
|
||
├── pkg/
|
||
│ ├── setting/
|
||
│ │ └── section.go # [MODIFY] 新增 AdRewardSettingS 结构体
|
||
│ ├── errcode/
|
||
│ │ └── quota_code.go # [MODIFY] 新增 AdRewardDisabled 错误码
|
||
│ └── wechat/
|
||
│ └── virtualpay.go # [MODIFY] XPayOrderInfo 补退款状态字段 + 退款状态判断
|
||
└── internal/
|
||
├── dto/
|
||
│ └── adreward.go # [MODIFY] 移除 Amount 字段
|
||
├── mysqldao/
|
||
│ └── user.go # [MODIFY] VIPGrantIdempotent 按最终到期时长推导 vip_type
|
||
├── routers/api/v1/
|
||
│ └── clothes.go # [MODIFY] Upload handler 入口加 MaxBytesReader
|
||
└── service/
|
||
├── adreward.go # [MODIFY] Grant 校验开关 + 服务端定价
|
||
├── virtualpay.go # [MODIFY] 退款反查、iOS 问询细化、platform 校验、pay_time 兜底
|
||
└── order.go # [MODIFY] autoRefundCancelledOrder 改待审核、settleRefundSuccess 兼容 Cancelled、grantVIP 调整
|
||
```
|
||
|
||
## 实现注意事项
|
||
|
||
- **S1 字段待确认**:XPay 官方退款查询/平台字段未联调确认,新增字段与状态枚举处必须保留「待确认」注释,不臆造字段名;未通过反查一律 `OrderRealityCheckFailed(70009)` + `ErrCode:1` 触发微信重试。
|
||
- **M1 防误回收**:「已取消但已付款」的订单权益从未发放,`settleRefundSuccess` 对该场景只做 `Cancelled->Refunded` 流转与退款信息记录,**跳过 `revokeOrderBenefits`**,避免误扣用户其他来源的会员天数/额度凭证。
|
||
- **M2 保持 Trial**:`ensureTrialVIP` 复用 `VIPGrantIdempotent` 传 `Trial(4)`,SQL 推导时须保留 Trial 不参与年度/月度推导。
|
||
- **M2 SQL 求值顺序**:依赖 MySQL 单表 UPDATE SET 从左到右求值,先计算 `vip_expire` 再推导 `vip_type`,与现有「显式控制 SET 顺序」注释保持一致。
|
||
- **M4 不信任前端**:platform 的资损判断改为以微信侧反查结果为准,保留 env 校验。
|
||
- **M12 余量**:`MaxBytesReader` 上限按 `MaxSizeMB*1024*1024 + 1MB`(multipart 边界开销),超限返回上传超限语义错误,避免误伤合法请求。
|
||
- **安全**:广告激励金额服务端定价后,不再接收客户端金额;退款反查沿 HMAC 签名服务端 API,无法被伪造。
|
||
- **验证**:全部改动完成后 `go build ./...` 与 `go vet ./...` 通过,并核对 linter。
|
||
|
||
## 推荐扩展
|
||
|
||
### Skill
|
||
|
||
- **lsp-code-analysis**
|
||
- 用途:追踪 `settleRefundSuccess`、`VIPGrantIdempotent`、`QuotaGrant`、`verifyXPayOrderPaid` 等关键符号的定义与全部调用点,确认改动影响面,避免遗漏调用链或误改 Trial 场景。
|
||
- 预期结果:明确各修复点的完整调用链,验证「Cancelled 订单跳过权益回退」「Trial 保持」等分支覆盖所有相关调用方。
|
||
|
||
### SubAgent
|
||
|
||
- **code-explorer**
|
||
- 用途:跨目录核对涉及文件与调用点,补充确认 `errcode` 分段、`QuotaGrantDao` 查询能力、`RefundFlowLog` 字段等实现细节。
|
||
- 预期结果:产出修复所需的精确文件与函数清单,支撑分组实施。 |