All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m2s
- 新增 UpdateWechatConfigParams/AgentOfflinePayParams 聚合结构体,嵌入 IDReq 提供 path:id 标签 - 修复 PUT /:id 和 POST /:id/offline-pay 路由的 Input 引用 - 修复 Makefile 构建路径从单文件改为包路径,解决多文件编译问题 - 标记 tasks.md 中 1.2.4 迁移任务为已完成
12 KiB
12 KiB
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/KeyPath的os.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_id列(bigint, nullable, 带索引) - 1.2.3 创建数据库迁移文件:
tb_asset_recharge_record新增payment_config_id列(bigint, nullable, 带索引) - 1.2.4 执行迁移,确认表结构正确
- 1.2.5 创建
internal/model/wechat_config.go:WechatConfig 模型(GORM 标签、TableName、渠道类型常量ProviderTypeWechat/ProviderTypeFuiou) - 1.2.6 修改
internal/model/order.go:Order 模型新增PaymentConfigID *uint字段 - 1.2.7 修改
internal/model/asset_wallet.go:AssetRechargeRecord 模型新增PaymentConfigID *uint字段 - 1.2.8 创建
internal/model/dto/wechat_config_dto.go:请求 DTO(Create/Update/List)、响应 DTO(含脱敏逻辑方法),详细字段定义见 spec - 1.2.9 在
pkg/constants/redis.go新增RedisWechatConfigActiveKey()函数 - 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)
- 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 缓存清除)、删除保护(检查激活状态 + 在途订单 + 在途充值)、GetActiveConfig(Redis 缓存 + 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.go和cmd/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_type(JSAPI / 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.go的CreateH5Order和CreateAdminOrder:注入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.go的WechatPayment字段、services.go和handlers.go的deps.WechatPayment注入暂时不改动。当 WechatPayJSAPI/WechatPayH5 完成动态加载改造(留桩解除)后,再删除WechatPayment字段和所有注入点。
1.6 回调处理改造
- 1.6.1 改造
internal/handler/callback/payment.go的WechatPayCallback:解析订单号 → 按前缀分发(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 新增
FuiouPayCallbackHandler:接收富友回调 → 解析 XML(GBK→UTF-8)→ 按订单号前缀分发 → 查询对应记录 → 加载配置 → 验签 → 调用对应 Service.HandlePaymentCallback → 返回 XML 响应 - 1.6.4 在
internal/routes/order.go注册富友回调路由POST /api/callback/fuiou-pay(无需认证) - 1.6.5 更新
internal/bootstrap/handlers.go:NewPaymentHandler新增agentRechargeService参数(用于ARCH前缀分发);WechatPayment参数留桩期间保留
1.7 资产充值模块适配
- 1.7.1 改造
internal/service/recharge/service.go的Create方法:创建充值订单时查询 active 配置,记录payment_config_id - 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 数据库与模型
- 2.1.1 创建数据库迁移文件:
tb_agent_recharge_record新增payment_config_id列(bigint, nullable, 带索引) - 2.1.2 修改
internal/model/agent_wallet.go:AgentRechargeRecord 模型新增PaymentConfigID *uint字段 - 2.1.3 创建
internal/model/dto/agent_recharge_dto.go:CreateAgentRechargeRequest、AgentOfflinePayRequest、AgentRechargeResponse、AgentRechargeListRequest、AgentRechargeListResponse,详细字段定义见 spec
2.2 代理充值 Service
- 2.2.1 创建
internal/service/agent_recharge/service.go:Create:验证权限(代理只能充自己店铺,平台可指定)→ 验证金额范围 → 查找 main 钱包 → 查询 active 配置(wechat 时必须有)→ 创建充值订单 → 记录 payment_config_idOfflinePay:验证平台权限 → 验证操作密码 → 事务内更新订单状态 + 增加钱包余额(乐观锁)+ 创建交易记录 → 审计日志HandlePaymentCallback:幂等检查 → 按 payment_config_id 验签 → 事务内更新订单状态 + 增加余额 + 创建交易记录GetByID、List:查询充值订单
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.go和cmd/gendocs/main.go:注册 AgentRechargeHandler 到文档生成器
2.4 代理充值回调集成
- 2.4.1 在回调 Handler(1.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