Files
junhong_cmp_fiber/openspec/changes/add-payment-config-management/tasks.md
huang 3e8f613475
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m2s
fix: 修复 OpenAPI 文档生成器启动 panic,路由缺少 path parameter 定义
- 新增 UpdateWechatConfigParams/AgentOfflinePayParams 聚合结构体,嵌入 IDReq 提供 path:id 标签
- 修复 PUT /:id 和 POST /:id/offline-pay 路由的 Input 引用
- 修复 Makefile 构建路径从单文件改为包路径,解决多文件编译问题
- 标记 tasks.md 中 1.2.4 迁移任务为已完成
2026-03-17 09:45:51 +08:00

116 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Goal 1微信参数配置管理 + 支付流程改造
### 1.1 前置准备:常量重命名
- [x] 1.1.1 `pkg/constants/wallet.go`:将 `Card*` 前缀常量重命名为 `Asset*`CardWalletResourceType* → AssetWalletResourceType*、CardWalletStatus* → AssetWalletStatus*、CardTransactionType* → AssetTransactionType*、CardRechargeOrderPrefix → AssetRechargeOrderPrefix、CardRechargeMinAmount → AssetRechargeMinAmount、CardRechargeMaxAmount → AssetRechargeMaxAmount段落标题 `卡钱包常量``资产钱包常量`
- [x] 1.1.2 旧 `Card*` 常量保留为废弃别名(`const CardRechargeOrderPrefix = AssetRechargeOrderPrefix`),更新废弃注释中的引用
- [x] 1.1.3 全局替换引用:将所有使用 `Card*` 常量的代码替换为 `Asset*`
### 1.1b 删除 YAML 支付配置遗留代码
> **必须在 1.3 之前完成**:这些是原有方案的残留,新方案部署后若不删除,配置和行为会产生歧义。
- [x] 1.1b.1 修改 `pkg/config/config.go`:删除 `PaymentConfig` 结构体(整体删除,含 `AppID`/`MchID`/`APIV3Key`/`APIV2Key`/`CertPath`/`KeyPath`/`SerialNo`/`NotifyURL`/`HttpDebug`/`Timeout` 所有字段);删除 `WechatConfig.Payment PaymentConfig` 字段;删除对应注释
- [x] 1.1b.2 修改 `pkg/config/defaults/config.yaml`:删除 `wechat.payment:` 整个配置节(约 10 行),**保留** `wechat.official_account:` 节不变OAuth 仍使用 YAML 配置)
- [x] 1.1b.3 修改 `pkg/wechat/config.go`:删除 `NewPaymentApp(cfg *config.Config, ...)` 函数(从 YAML CertPath/KeyPath 文件路径创建 Payment 实例的方式已被 DB Base64 方案完全取代)
- [x] 1.1b.4 修改 `cmd/api/main.go`:从 `validateWechatConfig` 中删除所有 `wechatCfg.Payment.*` 相关校验代码(包括对 `CertPath`/`KeyPath``os.Stat` 检查、缺失字段的 `appLogger.Fatal`**保留**对 `wechatCfg.OfficialAccount` 的校验不变
- [x] 1.1b.5 确认编译通过:删除后运行 `go build ./...` 确保无编译错误(此时 `wechatPayment` 相关代码仍保留,因为留桩期间仍在用单例)
### 1.2 数据库与基础模型
- [x] 1.2.1 创建数据库迁移文件:新建 `tb_wechat_config`基础字段、OAuth 公众号字段、OAuth 小程序字段、微信直连支付字段、富友支付字段),`is_active` 默认 `false`
- [x] 1.2.2 创建数据库迁移文件:`tb_order` 新增 `payment_config_id`bigint, nullable, 带索引)
- [x] 1.2.3 创建数据库迁移文件:`tb_asset_recharge_record` 新增 `payment_config_id`bigint, nullable, 带索引)
- [x] 1.2.4 执行迁移,确认表结构正确
- [x] 1.2.5 创建 `internal/model/wechat_config.go`WechatConfig 模型GORM 标签、TableName、渠道类型常量 `ProviderTypeWechat` / `ProviderTypeFuiou`
- [x] 1.2.6 修改 `internal/model/order.go`Order 模型新增 `PaymentConfigID *uint` 字段
- [x] 1.2.7 修改 `internal/model/asset_wallet.go`AssetRechargeRecord 模型新增 `PaymentConfigID *uint` 字段
- [x] 1.2.8 创建 `internal/model/dto/wechat_config_dto.go`:请求 DTOCreate/Update/List、响应 DTO含脱敏逻辑方法详细字段定义见 spec
- [x] 1.2.9 在 `pkg/constants/redis.go` 新增 `RedisWechatConfigActiveKey()` 函数
- [x] 1.2.10 在 `pkg/errors/codes.go` 新增错误码:`CodeWechatConfigNotFound=1170``CodeWechatConfigActive=1171``CodeWechatConfigHasPendingOrders=1172``CodeFuiouPayFailed=1173``CodeFuiouCallbackInvalid=1174``CodeNoPaymentConfig=1175`
### 1.3 微信参数配置 CRUDStore + Service + Handler
- [x] 1.3.1 创建 `internal/store/postgres/wechat_config_store.go`:实现 Create、GetByID、GetByIDUnscoped含软删除、List分页+筛选、Update、SoftDelete、GetActive、ActivateInTx事务内停用所有+激活指定、Deactivate、CountPendingOrdersByConfigID、CountPendingRechargesByConfigID
- [x] 1.3.2 创建 `internal/service/wechat_config/service.go`:实现 CRUD 业务逻辑,包含按 provider_type 校验必填字段、激活/停用(含 Redis 缓存清除)、删除保护(检查激活状态 + 在途订单 + 在途充值、GetActiveConfigRedis 缓存 + DB 回源 + 空标记)、更新脱敏字段处理、审计日志记录
- [x] 1.3.3 创建 `internal/handler/admin/wechat_config.go`:实现 Create、List、Get、Update、Delete、Activate、Deactivate、GetActive 共 8 个 Handler 方法
- [x] 1.3.4 创建 `internal/routes/wechat_config.go`:注册路由到 `/api/admin/wechat-configs/*`,包含平台用户权限中间件
- [x] 1.3.5 更新 `internal/bootstrap/`types.go、stores.go、services.go、handlers.go注册 WechatConfigStore、WechatConfigService、WechatConfigHandler
- [x] 1.3.6 更新 `cmd/api/docs.go``cmd/gendocs/main.go`:注册 WechatConfigHandler 到文档生成器
### 1.4 富友支付 SDK
- [x] 1.4.1 创建 `pkg/fuiou/types.go`:定义 WxPreCreateRequest/Response、NotifyRequest 等 XML 结构体
- [x] 1.4.2 创建 `pkg/fuiou/client.go`:实现 Client 结构体(持有配置和 RSA 密钥对、NewClient从 WechatConfig 模型构造)、签名算法(字典序 → GBK → MD5 → RSA → Base64、验签算法、HTTP 请求XML + GBK + 双 URL 编码、响应解码URL 解码 → GBK→UTF-8 → XML 解析)
- [x] 1.4.3 创建 `pkg/fuiou/wxprecreate.go`:实现 WxPreCreate 方法(公众号 JSAPI + 小程序支付下单),支持 trade_typeJSAPI / LETPAY和 sub_appid / sub_openid 参数
- [x] 1.4.4 创建 `pkg/fuiou/notify.go`:实现 VerifyNotify 方法GBK→UTF-8 + XML 解析 + RSA 验签BuildNotifyResponse 成功/失败响应构建
- [x] 1.4.5 在 `go.mod` 添加 `golang.org/x/text` 依赖GBK 编解码)
### 1.5 订单支付流程改造
- [x] 1.5.1 改造 `internal/service/order/service.go``CreateH5Order``CreateAdminOrder`:注入 `wechatConfigService`(新增字段),下单时查询 active 配置 → 无配置则拒绝第三方支付 → 有配置则记录 `payment_config_id` 到订单
- [x] 1.5.2 改造 `WechatPayJSAPI` 方法(**留桩**):添加 TODO 注释 `// TODO: 从 payment_config_id 加载配置动态创建 Payment 实例`,本次保留现有 `s.wechatPayment` 单例调用不变;同时在构造函数中保留 `wechatPayment` 参数(留桩期间仍需注入)
- [x] 1.5.3 改造 `WechatPayH5` 方法(**留桩**):同 1.5.2,添加 TODO 注释,保留 `s.wechatPayment` 调用
- [x] 1.5.4 新增富友支付发起方法桩:`FuiouPayJSAPI`(返回 "富友支付发起暂未实现" 错误)和 `FuiouPayMiniApp`(同上),标记 TODO
> **留桩期间的 Bootstrap 注入**:任务 1.5.2/1.5.3 的留桩意味着 `internal/bootstrap/dependencies.go` 的 `WechatPayment` 字段、`services.go` 和 `handlers.go` 的 `deps.WechatPayment` 注入**暂时不改动**。当 WechatPayJSAPI/WechatPayH5 完成动态加载改造(留桩解除)后,再删除 `WechatPayment` 字段和所有注入点。
### 1.6 回调处理改造
- [x] 1.6.1 改造 `internal/handler/callback/payment.go``WechatPayCallback`:解析订单号 → 按前缀分发(`ORD`/`CRCH`/`ARCH`)→ 查询对应表取 `payment_config_id` → 按配置加载验签(本次留桩:验签仍用现有 `wechatPayment` 单例,添加 TODO `// TODO: 按 payment_config_id 加载配置验签`**订单分发逻辑必须完整实现**(不是留桩),三种订单类型必须全部支持
- [x] 1.6.2 修复回调中的前缀匹配:将 `constants.RechargeOrderPrefix("RCH")` 替换为分别匹配 `constants.AssetRechargeOrderPrefix("CRCH")``constants.AgentRechargeOrderPrefix("ARCH")`;同时修复 `AlipayCallback` 中同样使用 `RechargeOrderPrefix` 的问题(第 84 行)
- [x] 1.6.3 新增 `FuiouPayCallback` Handler接收富友回调 → 解析 XMLGBK→UTF-8→ 按订单号前缀分发 → 查询对应记录 → 加载配置 → 验签 → 调用对应 Service.HandlePaymentCallback → 返回 XML 响应
- [x] 1.6.4 在 `internal/routes/order.go` 注册富友回调路由 `POST /api/callback/fuiou-pay`(无需认证)
- [x] 1.6.5 更新 `internal/bootstrap/handlers.go``NewPaymentHandler` 新增 `agentRechargeService` 参数(用于 `ARCH` 前缀分发);`WechatPayment` 参数留桩期间保留
### 1.7 资产充值模块适配
- [x] 1.7.1 改造 `internal/service/recharge/service.go``Create` 方法:创建充值订单时查询 active 配置,记录 `payment_config_id`
- [x] 1.7.2 改造 `internal/service/recharge/service.go``HandlePaymentCallback` 方法:回调时按 `payment_config_id` 加载配置验签(留桩)
### 1.8 集成验证与文档
- [ ] 1.8.1 验证完整流程:创建微信支付配置 → 激活 → 确认缓存生效 → 停用 → 确认降级为钱包支付
- [ ] 1.8.2 验证配置切换:激活配置 A → 创建订单(记录 payment_config_id=A→ 切换到配置 B → 新订单使用 B
- [ ] 1.8.3 验证权限控制:代理/企业账号无法访问微信参数配置管理接口
- [ ] 1.8.4 验证审计日志CRUD 和激活/停用操作产生审计记录
- [ ] 1.8.5 创建功能文档 `docs/wechat-config-management/功能总结.md`
---
## Goal 2代理预充值系统
### 2.1 数据库与模型
- [x] 2.1.1 创建数据库迁移文件:`tb_agent_recharge_record` 新增 `payment_config_id`bigint, nullable, 带索引)
- [x] 2.1.2 修改 `internal/model/agent_wallet.go`AgentRechargeRecord 模型新增 `PaymentConfigID *uint` 字段
- [x] 2.1.3 创建 `internal/model/dto/agent_recharge_dto.go`CreateAgentRechargeRequest、AgentOfflinePayRequest、AgentRechargeResponse、AgentRechargeListRequest、AgentRechargeListResponse详细字段定义见 spec
### 2.2 代理充值 Service
- [x] 2.2.1 创建 `internal/service/agent_recharge/service.go`
- `Create`:验证权限(代理只能充自己店铺,平台可指定)→ 验证金额范围 → 查找 main 钱包 → 查询 active 配置wechat 时必须有)→ 创建充值订单 → 记录 payment_config_id
- `OfflinePay`:验证平台权限 → 验证操作密码 → 事务内更新订单状态 + 增加钱包余额(乐观锁)+ 创建交易记录 → 审计日志
- `HandlePaymentCallback`:幂等检查 → 按 payment_config_id 验签 → 事务内更新订单状态 + 增加余额 + 创建交易记录
- `GetByID``List`:查询充值订单
### 2.3 代理充值 Handler + 路由
- [x] 2.3.1 创建 `internal/handler/admin/agent_recharge.go`:实现 Create、List、Get、OfflinePay 共 4 个 Handler 方法
- [x] 2.3.2 创建 `internal/routes/agent_recharge.go`:注册路由到 `/api/admin/agent-recharges/*`
- [x] 2.3.3 更新 `internal/bootstrap/`types.go、stores.go、services.go、handlers.go注册 AgentRechargeService、AgentRechargeHandler
- [x] 2.3.4 更新 `cmd/api/docs.go``cmd/gendocs/main.go`:注册 AgentRechargeHandler 到文档生成器
### 2.4 代理充值回调集成
- [x] 2.4.1 在回调 Handler1.6.2 已完成的前缀分发逻辑)中接入代理充值回调:`"ARCH"` 前缀 → `agentRechargeService.HandlePaymentCallback()`
- [x] 2.4.2 确认富友回调 Handler 也支持 `"ARCH"` 前缀分发
### 2.5 集成验证与文档
- [ ] 2.5.1 验证微信支付充值流程创建充值订单wechat→ 确认 payment_config_id 记录 → 模拟回调 → 确认余额增加
- [ ] 2.5.2 验证线下充值流程平台创建充值订单offline→ 确认线下支付 → 验证操作密码 → 确认余额增加
- [ ] 2.5.3 验证权限控制:代理只能充自己店铺、非平台不能线下充值、操作密码错误拒绝
- [ ] 2.5.4 验证审计日志:线下充值操作产生审计记录
- [ ] 2.5.5 创建功能文档 `docs/agent-recharge/功能总结.md`