## 1. 数据库迁移（建新表）

- [ ] 1.1 创建迁移文件：新建 `tb_recharge_order` 表（含所有字段和索引，参考 design.md 决策 4 的字段定义）
- [ ] 1.2 创建迁移文件：新建 `tb_payment` 表（含所有字段和索引，参考 design.md 决策 3 的字段定义）

## 2. Model 层

- [ ] 2.1 新建 `internal/model/recharge_order.go`：定义 `RechargeOrder` 模型、状态常量（1待支付 2已支付 3已关闭 4已退款）、`AutoPurchaseStatus` 常量（pending/success/failed）
- [ ] 2.2 新建 `internal/model/payment.go`：定义 `Payment` 模型、状态常量（1待支付 2已支付 3已失败 4已退款）、`OrderType` 常量（package_order / recharge_order）

## 3. Store 层

- [ ] 3.1 新建 `internal/store/postgres/recharge_order_store.go`：实现 Create、GetByRechargeOrderNo、GetByID、UpdateStatus（乐观锁）、ListByCard、ListByDevice
- [ ] 3.2 新建 `internal/store/postgres/payment_store.go`：实现 Create、GetByPaymentNo、UpdateStatus、UpdatePaymentInfo、ListByOrderID
- [ ] 3.3 在 `internal/bootstrap/stores.go` 中注册 `RechargeOrderStore` 和 `PaymentStore`

## 4. 强充创建流程重写

- [ ] 4.1 修改 `internal/service/client_order/service.go` 的 `createForceRechargeOrder`：改为写 `tb_recharge_order` + `tb_payment`，移除对 `rechargeRecordStore` 的调用
- [ ] 4.2 修改幂等键逻辑：`!claimed` 时 GET Redis 值，若为 recharge_order_no 则查 `tb_recharge_order`，status=1 时返回已有充值订单（含 `idempotent: true` 标志），status≠1 时删 key 允许重建
- [ ] 4.3 调整 `markClientPurchaseCreated`：存入 `recharge_order_no`（来自 `tb_recharge_order`，不再存充值记录号）
- [ ] 4.4 修改 `ClientOrderService` 结构体：注入 `rechargeOrderStore` 和 `paymentStore`，移除 `rechargeRecordStore` 字段
- [ ] 4.5 修改 `internal/bootstrap/handlers.go`：更新 `ClientOrderService` 的依赖注入

## 5. 支付回调链路完全重写

- [ ] 5.1 新建 `internal/service/recharge_order/service.go`：实现 `HandlePaymentCallback(ctx, paymentNo, paymentMethod, transactionID)`——查 `tb_payment` → 乐观锁更新 `tb_payment.status=2` → 更新 `tb_recharge_order.status=2` → 事务内增加钱包余额 + 创建钱包流水 + 更新累计充值 → 触发 auto_purchase 任务（若 linked_package_ids 非空）
- [ ] 5.2 修改 `internal/handler/callback/payment.go`：`dispatchWechatCallback` 改为查 `tb_payment` by payment_no，找到则调 `rechargeOrderService.HandlePaymentCallback`；CRCH 前缀单号不再路由到旧 `RechargeService`
- [ ] 5.3 修改 `internal/bootstrap/handlers.go`：注入 `rechargeOrderService` 到支付回调 Handler
- [ ] 5.4 修改 `internal/service/wechat_config/service.go` 的 `resolvePaymentConfigID`：CRCH 前缀路由从 `AssetRechargeStore.GetByRechargeNo` 改为 `RechargeOrderStore.GetByRechargeOrderNo`，获取 `payment_config_id` 用于微信支付回调验签
- [ ] 5.5 修改 `internal/store/postgres/wechat_config_store.go` 的 `CountPendingRechargesByConfigID`：SQL 从 `tb_asset_recharge_record` 改为查询 `tb_recharge_order`（按 `payment_config_id` 统计待支付充值数，用于删除配置前检查）

## 6. 普通充值流程迁移

- [ ] 6.1 修改 `internal/handler/app/client_wallet.go` 的 `CreateRecharge`：改为调用新的充值订单创建逻辑，写 `tb_recharge_order` + `tb_payment`，移除对旧 `RechargeService.Create` 的调用
- [ ] 6.2 修改 `internal/handler/app/client_wallet.go` 的 `GetRechargeRecords`：改为从 `tb_recharge_order` 查询

## 7. PayOrder 增加支付记录

- [ ] 7.1 修改 `internal/service/order/service.go` 的 `WalletPay`：在扣款事务中增加 `INSERT tb_payment`（method=wallet，status=2，order_type=package_order）
- [ ] 7.2 在 `WalletPay` 中增加幂等检查：若 `tb_payment` 中已有该 order_id 且 status=2 的记录，直接返回成功，不重复扣款

## 8. auto_purchase 任务迁移

- [ ] 8.1 修改 `internal/task/auto_purchase.go`：任务 payload 改为传 `recharge_order_id`，从 `tb_recharge_order` 读取 linked_package_ids，移除对 `tb_asset_recharge_record` 的读取
- [ ] 8.2 修改 `auto_purchase.go`：创建套餐订单（`tb_order`）的同时在同一事务内创建 `tb_payment`（method=wallet，status=2，order_type=package_order）
- [ ] 8.3 修改 `auto_purchase.go`：任务完成/失败后更新 `tb_recharge_order.auto_purchase_status`，移除对 `tb_asset_recharge_record` 的写入

## 9. 新增充值订单独立接口

- [ ] 9.1 新增 `internal/handler/app/client_recharge_order.go`：实现 `ListRechargeOrders`（GET `/api/c/v1/recharge-orders`，按 identifier + generation 查 `tb_recharge_order`，支持 status 过滤）和 `GetRechargeOrderDetail`（GET `/api/c/v1/recharge-orders/:id`）
- [ ] 9.2 新增对应 DTO：`ClientRechargeOrderListRequest`、`ClientRechargeOrderListItem`（含 auto_purchase_status、recharge_order_no、amount、status、status_name、created_at）
- [ ] 9.3 注册路由：在 C 端路由组中注册 `/api/c/v1/recharge-orders` 相关路由
- [ ] 9.4 修改 `ClientCreateOrderResponse`：`recharge` 分支返回 `recharge_order_no`（来自新表），增加 `idempotent` bool 字段

## 10. 删除旧代码

- [ ] 10.1 删除 `internal/service/recharge/service.go` 中全部写方法和回调处理（HandlePaymentCallback、Create 等），若无其他引用则删除整个文件
- [ ] 10.2 删除 `internal/store/postgres/asset_recharge_store.go` 全部内容（无需保留任何方法）
- [ ] 10.3 删除 `internal/model/asset_wallet.go` 中的 `AssetRechargeRecord` 模型定义
- [ ] 10.4 从 `internal/bootstrap/stores.go` 和 `handlers.go` 中移除 `AssetRechargeStore` 的所有注册和注入
- [ ] 10.5 从 `internal/service/client_order/service.go` 中移除 `rechargeRecordStore` 字段和全部引用
- [ ] 10.6 运行 `go build ./...`，修复所有因删除旧代码引起的编译错误

## 11. 验证

- [ ] 11.1 用 PostgreSQL MCP 验证：发起强充后 `tb_recharge_order` 和 `tb_payment` 均有新记录，`tb_asset_recharge_record` 无新记录
- [ ] 11.2 用 PostgreSQL MCP 验证：微信支付回调后 `tb_payment.status=2`，`tb_recharge_order.status=2`，钱包余额正确增加
- [ ] 11.3 用 PostgreSQL MCP 验证：auto_purchase 完成后 `tb_order` 新增套餐订单，`tb_recharge_order.auto_purchase_status=success`
- [ ] 11.4 手动验证：GET `/api/c/v1/recharge-orders` 正确返回充值订单列表；GET `/api/c/v1/orders` 仍只返回套餐订单
- [ ] 11.5 手动验证：重复发起相同参数的下单请求，返回 HTTP 200 且 `idempotent=true`，不报"订单正在创建中"
- [ ] 11.6 手动验证：普通充值（非强充）写 `tb_recharge_order`，回调后钱包余额正确增加
- [ ] 11.7 手动验证：PayOrder 支付套餐后 `tb_payment` 有对应 wallet 支付记录，重复调用幂等返回成功

## 12. 删除旧表（最后执行）

- [ ] 12.1 确认 `tb_asset_recharge_record` 无任何新写入（检查该表 updated_at 最新时间是否在部署前）
- [ ] 12.2 创建迁移文件：`DROP TABLE tb_asset_recharge_record`
- [ ] 12.3 执行迁移，确认表已删除
