## 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, 带索引) - [ ] 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`:请求 DTO(Create/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 微信参数配置 CRUD(Store + 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 缓存清除)、删除保护(检查激活状态 + 在途订单 + 在途充值)、GetActiveConfig(Redis 缓存 + 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_type(JSAPI / 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:接收富友回调 → 解析 XML(GBK→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 在回调 Handler(1.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`