Files
junhong_cmp_fiber/openspec/changes/archive/2026-01-29-fix-order-activation-idempotency/tasks.md
huang 1290160728
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m22s
fix: 修复订单支付幂等性问题,防止重复激活套餐
- 使用条件更新实现支付状态原子转换(pending -> paid)
- 重复请求返回幂等成功,不再重复激活套餐
- 新增 tb_package_usage 唯一索引(order_id, package_id)
- 新增幂等性和异常状态测试,测试覆盖率 71.7%
- 归档 OpenSpec 变更 fix-order-activation-idempotency
2026-01-29 16:33:53 +08:00

3.0 KiB
Raw Blame History

订单激活幂等性修复 - 实现任务

1. 状态原子转换

  • 1.1 在 internal/service/order/service.go 中修改钱包支付和支付回调逻辑
    • 将支付状态更新改为条件更新:WHERE id = ? AND payment_status = ?(只允许 pending -> paid
    • 使用 result.RowsAffected == 0 检查是否已被其他请求处理
  • 1.2 实现重复请求处理逻辑
    • RowsAffected == 0 时,重新查询订单当前状态
    • 订单状态为 model.PaymentStatusPaid:返回 nil(幂等成功)
    • 订单状态为 model.PaymentStatusCancelled:返回 errors.New(errors.CodeInvalidStatus, "订单已取消,无法支付")
    • 订单状态为 model.PaymentStatusRefunded:返回 errors.New(errors.CodeInvalidStatus, "订单已退款,无法支付")

2. 激活幂等与事务一致性

  • 2.1 调整 activatePackage 调用时机
    • 只在条件更新成功(RowsAffected > 0)后执行
    • 幂等场景(订单已支付)直接返回,不再调用 activatePackage
  • 2.2 审查 activatePackage 内部数据访问
    • 确保所有订单明细、套餐信息查询使用事务 tx 参数
    • 避免使用非事务的 s.dbs.orderStore 直接查询(应使用 tx 包装的 Store

3. 防御性约束(可选)

  • 3.1 创建数据库迁移文件
    • migrations/ 目录创建迁移文件对up/down
    • 文件命名:000033_add_unique_index_package_usage_order_package.up.sql
    • 文件命名:000033_add_unique_index_package_usage_order_package.down.sql
    • Up 内容:CREATE UNIQUE INDEX idx_package_usage_order_package ON tb_package_usage(order_id, package_id) WHERE deleted_at IS NULL;
    • Down 内容:DROP INDEX IF EXISTS idx_package_usage_order_package;
  • 3.2 代码中处理唯一冲突
    • activatePackage 插入 tb_package_usage 前,先查询是否已存在
    • 若已存在:记录警告日志,返回成功(防御性幂等)
    • 若插入失败且为唯一冲突错误:返回成功(数据库层防御)

4. 测试与验证

  • 4.1 新增集成测试到 internal/service/order/service_test.go
    • 幂等支付测试:串行多次调用 WalletPay,验证只生成一条 PackageUsage 记录
    • 重复回调测试:连续多次调用支付回调,验证返回成功且不重复插入
    • 已取消订单支付:创建已取消订单,调用支付接口,验证返回错误码 1050
    • 已取消订单回调:创建已取消订单,调用支付回调,验证返回错误码 1050
  • 4.2 运行测试并验证
    • 执行 source .env.local && go test -v ./internal/service/order/...
    • 确保所有测试通过
    • 测试覆盖率71.7%

5. 文档更新

  • 5.1 创建功能总结文档
    • 创建目录:docs/fix-order-activation-idempotency/
    • 创建文件:docs/fix-order-activation-idempotency/功能总结.md
    • 内容包含:问题背景、解决方案、技术实现、测试验证
  • 5.2 更新 README.md如有必要
    • 内部幂等性修复,无需更新 README.md