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

12 KiB
Raw Blame History

Goal 1微信参数配置管理 + 支付流程改造

1.1 前置准备:常量重命名

  • 1.1.1 pkg/constants/wallet.go:将 Card* 前缀常量重命名为 Asset*CardWalletResourceType* → AssetWalletResourceType*、CardWalletStatus* → AssetWalletStatus*、CardTransactionType* → AssetTransactionType*、CardRechargeOrderPrefix → AssetRechargeOrderPrefix、CardRechargeMinAmount → AssetRechargeMinAmount、CardRechargeMaxAmount → AssetRechargeMaxAmount段落标题 卡钱包常量资产钱包常量
  • 1.1.2 旧 Card* 常量保留为废弃别名(const CardRechargeOrderPrefix = AssetRechargeOrderPrefix),更新废弃注释中的引用
  • 1.1.3 全局替换引用:将所有使用 Card* 常量的代码替换为 Asset*

1.1b 删除 YAML 支付配置遗留代码

必须在 1.3 之前完成:这些是原有方案的残留,新方案部署后若不删除,配置和行为会产生歧义。

  • 1.1b.1 修改 pkg/config/config.go:删除 PaymentConfig 结构体(整体删除,含 AppID/MchID/APIV3Key/APIV2Key/CertPath/KeyPath/SerialNo/NotifyURL/HttpDebug/Timeout 所有字段);删除 WechatConfig.Payment PaymentConfig 字段;删除对应注释
  • 1.1b.2 修改 pkg/config/defaults/config.yaml:删除 wechat.payment: 整个配置节(约 10 行),保留 wechat.official_account: 节不变OAuth 仍使用 YAML 配置)
  • 1.1b.3 修改 pkg/wechat/config.go:删除 NewPaymentApp(cfg *config.Config, ...) 函数(从 YAML CertPath/KeyPath 文件路径创建 Payment 实例的方式已被 DB Base64 方案完全取代)
  • 1.1b.4 修改 cmd/api/main.go:从 validateWechatConfig 中删除所有 wechatCfg.Payment.* 相关校验代码(包括对 CertPath/KeyPathos.Stat 检查、缺失字段的 appLogger.Fatal保留wechatCfg.OfficialAccount 的校验不变
  • 1.1b.5 确认编译通过:删除后运行 go build ./... 确保无编译错误(此时 wechatPayment 相关代码仍保留,因为留桩期间仍在用单例)

1.2 数据库与基础模型

  • 1.2.1 创建数据库迁移文件:新建 tb_wechat_config基础字段、OAuth 公众号字段、OAuth 小程序字段、微信直连支付字段、富友支付字段),is_active 默认 false
  • 1.2.2 创建数据库迁移文件:tb_order 新增 payment_config_idbigint, nullable, 带索引)
  • 1.2.3 创建数据库迁移文件:tb_asset_recharge_record 新增 payment_config_idbigint, nullable, 带索引)
  • 1.2.4 执行迁移,确认表结构正确
  • 1.2.5 创建 internal/model/wechat_config.goWechatConfig 模型GORM 标签、TableName、渠道类型常量 ProviderTypeWechat / ProviderTypeFuiou
  • 1.2.6 修改 internal/model/order.goOrder 模型新增 PaymentConfigID *uint 字段
  • 1.2.7 修改 internal/model/asset_wallet.goAssetRechargeRecord 模型新增 PaymentConfigID *uint 字段
  • 1.2.8 创建 internal/model/dto/wechat_config_dto.go:请求 DTOCreate/Update/List、响应 DTO含脱敏逻辑方法详细字段定义见 spec
  • 1.2.9 在 pkg/constants/redis.go 新增 RedisWechatConfigActiveKey() 函数
  • 1.2.10 在 pkg/errors/codes.go 新增错误码:CodeWechatConfigNotFound=1170CodeWechatConfigActive=1171CodeWechatConfigHasPendingOrders=1172CodeFuiouPayFailed=1173CodeFuiouCallbackInvalid=1174CodeNoPaymentConfig=1175

1.3 微信参数配置 CRUDStore + Service + Handler

  • 1.3.1 创建 internal/store/postgres/wechat_config_store.go:实现 Create、GetByID、GetByIDUnscoped含软删除、List分页+筛选、Update、SoftDelete、GetActive、ActivateInTx事务内停用所有+激活指定、Deactivate、CountPendingOrdersByConfigID、CountPendingRechargesByConfigID
  • 1.3.2 创建 internal/service/wechat_config/service.go:实现 CRUD 业务逻辑,包含按 provider_type 校验必填字段、激活/停用(含 Redis 缓存清除)、删除保护(检查激活状态 + 在途订单 + 在途充值、GetActiveConfigRedis 缓存 + DB 回源 + 空标记)、更新脱敏字段处理、审计日志记录
  • 1.3.3 创建 internal/handler/admin/wechat_config.go:实现 Create、List、Get、Update、Delete、Activate、Deactivate、GetActive 共 8 个 Handler 方法
  • 1.3.4 创建 internal/routes/wechat_config.go:注册路由到 /api/admin/wechat-configs/*,包含平台用户权限中间件
  • 1.3.5 更新 internal/bootstrap/types.go、stores.go、services.go、handlers.go注册 WechatConfigStore、WechatConfigService、WechatConfigHandler
  • 1.3.6 更新 cmd/api/docs.gocmd/gendocs/main.go:注册 WechatConfigHandler 到文档生成器

1.4 富友支付 SDK

  • 1.4.1 创建 pkg/fuiou/types.go:定义 WxPreCreateRequest/Response、NotifyRequest 等 XML 结构体
  • 1.4.2 创建 pkg/fuiou/client.go:实现 Client 结构体(持有配置和 RSA 密钥对、NewClient从 WechatConfig 模型构造)、签名算法(字典序 → GBK → MD5 → RSA → Base64、验签算法、HTTP 请求XML + GBK + 双 URL 编码、响应解码URL 解码 → GBK→UTF-8 → XML 解析)
  • 1.4.3 创建 pkg/fuiou/wxprecreate.go:实现 WxPreCreate 方法(公众号 JSAPI + 小程序支付下单),支持 trade_typeJSAPI / LETPAY和 sub_appid / sub_openid 参数
  • 1.4.4 创建 pkg/fuiou/notify.go:实现 VerifyNotify 方法GBK→UTF-8 + XML 解析 + RSA 验签BuildNotifyResponse 成功/失败响应构建
  • 1.4.5 在 go.mod 添加 golang.org/x/text 依赖GBK 编解码)

1.5 订单支付流程改造

  • 1.5.1 改造 internal/service/order/service.goCreateH5OrderCreateAdminOrder:注入 wechatConfigService(新增字段),下单时查询 active 配置 → 无配置则拒绝第三方支付 → 有配置则记录 payment_config_id 到订单
  • 1.5.2 改造 WechatPayJSAPI 方法(留桩):添加 TODO 注释 // TODO: 从 payment_config_id 加载配置动态创建 Payment 实例,本次保留现有 s.wechatPayment 单例调用不变;同时在构造函数中保留 wechatPayment 参数(留桩期间仍需注入)
  • 1.5.3 改造 WechatPayH5 方法(留桩):同 1.5.2,添加 TODO 注释,保留 s.wechatPayment 调用
  • 1.5.4 新增富友支付发起方法桩:FuiouPayJSAPI(返回 "富友支付发起暂未实现" 错误)和 FuiouPayMiniApp(同上),标记 TODO

留桩期间的 Bootstrap 注入:任务 1.5.2/1.5.3 的留桩意味着 internal/bootstrap/dependencies.goWechatPayment 字段、services.gohandlers.godeps.WechatPayment 注入暂时不改动。当 WechatPayJSAPI/WechatPayH5 完成动态加载改造(留桩解除)后,再删除 WechatPayment 字段和所有注入点。

1.6 回调处理改造

  • 1.6.1 改造 internal/handler/callback/payment.goWechatPayCallback:解析订单号 → 按前缀分发(ORD/CRCH/ARCH)→ 查询对应表取 payment_config_id → 按配置加载验签(本次留桩:验签仍用现有 wechatPayment 单例,添加 TODO // TODO: 按 payment_config_id 加载配置验签订单分发逻辑必须完整实现(不是留桩),三种订单类型必须全部支持
  • 1.6.2 修复回调中的前缀匹配:将 constants.RechargeOrderPrefix("RCH") 替换为分别匹配 constants.AssetRechargeOrderPrefix("CRCH")constants.AgentRechargeOrderPrefix("ARCH");同时修复 AlipayCallback 中同样使用 RechargeOrderPrefix 的问题(第 84 行)
  • 1.6.3 新增 FuiouPayCallback Handler接收富友回调 → 解析 XMLGBK→UTF-8→ 按订单号前缀分发 → 查询对应记录 → 加载配置 → 验签 → 调用对应 Service.HandlePaymentCallback → 返回 XML 响应
  • 1.6.4 在 internal/routes/order.go 注册富友回调路由 POST /api/callback/fuiou-pay(无需认证)
  • 1.6.5 更新 internal/bootstrap/handlers.goNewPaymentHandler 新增 agentRechargeService 参数(用于 ARCH 前缀分发);WechatPayment 参数留桩期间保留

1.7 资产充值模块适配

  • 1.7.1 改造 internal/service/recharge/service.goCreate 方法:创建充值订单时查询 active 配置,记录 payment_config_id
  • 1.7.2 改造 internal/service/recharge/service.goHandlePaymentCallback 方法:回调时按 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 数据库与模型

  • 2.1.1 创建数据库迁移文件:tb_agent_recharge_record 新增 payment_config_idbigint, nullable, 带索引)
  • 2.1.2 修改 internal/model/agent_wallet.goAgentRechargeRecord 模型新增 PaymentConfigID *uint 字段
  • 2.1.3 创建 internal/model/dto/agent_recharge_dto.goCreateAgentRechargeRequest、AgentOfflinePayRequest、AgentRechargeResponse、AgentRechargeListRequest、AgentRechargeListResponse详细字段定义见 spec

2.2 代理充值 Service

  • 2.2.1 创建 internal/service/agent_recharge/service.go
    • Create:验证权限(代理只能充自己店铺,平台可指定)→ 验证金额范围 → 查找 main 钱包 → 查询 active 配置wechat 时必须有)→ 创建充值订单 → 记录 payment_config_id
    • OfflinePay:验证平台权限 → 验证操作密码 → 事务内更新订单状态 + 增加钱包余额(乐观锁)+ 创建交易记录 → 审计日志
    • HandlePaymentCallback:幂等检查 → 按 payment_config_id 验签 → 事务内更新订单状态 + 增加余额 + 创建交易记录
    • GetByIDList:查询充值订单

2.3 代理充值 Handler + 路由

  • 2.3.1 创建 internal/handler/admin/agent_recharge.go:实现 Create、List、Get、OfflinePay 共 4 个 Handler 方法
  • 2.3.2 创建 internal/routes/agent_recharge.go:注册路由到 /api/admin/agent-recharges/*
  • 2.3.3 更新 internal/bootstrap/types.go、stores.go、services.go、handlers.go注册 AgentRechargeService、AgentRechargeHandler
  • 2.3.4 更新 cmd/api/docs.gocmd/gendocs/main.go:注册 AgentRechargeHandler 到文档生成器

2.4 代理充值回调集成

  • 2.4.1 在回调 Handler1.6.2 已完成的前缀分发逻辑)中接入代理充值回调:"ARCH" 前缀 → agentRechargeService.HandlePaymentCallback()
  • 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