Files
junhong_cmp_fiber/docs/wechat-config-management/功能总结.md

11 KiB
Raw Blame History

微信参数配置管理功能

功能概述

在管理后台支持多套微信支付配置的 CRUD 管理,每套配置代表一套完整的"微信身份"(公众号 OAuth + 小程序 OAuth + 支付凭证),支持全局唯一激活约束和秒级切换。同时集成富友支付 SDK作为微信直连的备选渠道。

背景与动机

原有微信相关参数(公众号 OAuth、小程序、支付凭证硬编码在环境变量中只有一套配置无法动态切换。业务上微信公众号/小程序随时可能被封禁,需要在管理后台秒级切换到备用配置恢复 OAuth 登录和支付能力。同时需要接入富友支付作为备选通道,降低对微信直连的单一依赖。

核心设计

配置切换流程

管理员激活新配置 POST /api/admin/wechat-configs/:id/activate
    │
    ├─ ① BEGIN 事务
    │   ├─ UPDATE tb_wechat_config SET is_active=false WHERE is_active=true
    │   └─ UPDATE tb_wechat_config SET is_active=true WHERE id=:id
    ├─ ② COMMIT
    ├─ ③ DEL Redis "wechat:config:active"(即时生效)
    └─ ④ 记录审计日志
         │
         ├─ 新订单 → 使用新配置(记录新的 payment_config_id
         └─ 旧订单(待支付)→ 回调时按 payment_config_id 加载旧配置验签
                              └─ 30 分钟超时自动取消

生效配置缓存策略

  • Redis Keywechat:config:active(见 pkg/constants/redis.go
  • TTL5 分钟(兜底,防 Redis 缓存与 DB 长期不一致)
  • 主动失效:激活、停用、更新生效配置、删除配置时主动 DEL 缓存
  • 空标记:无生效配置时缓存 "none"TTL 1 分钟,防止缓存穿透
  • 读取流程Redis GET → 命中返回 → MISS → 查 DB → SET 缓存

配置切换时在途订单处理

  • tb_ordertb_asset_recharge_recordtb_agent_recharge_record 均新增 payment_config_id 字段nullable
  • 下单时记录当前使用的配置 ID配置切换后旧订单仍按 payment_config_id 加载旧配置验签
  • 旧待支付订单由现有 30 分钟超时自动取消机制清理
  • 有待支付订单引用的配置不允许删除(软删除后仍可用于验签)

支付回调统一分发

回调到达
    │
    ├─ 微信回调 POST /api/callback/wechat-pay
    │   └─ PowerWeChat SDK 解析 → 取 out_trade_no
    │
    └─ 富友回调 POST /api/callback/fuiou-pay
        └─ GBK→UTF-8 → XML 解析 → 取 mchnt_order_no
    │
    └─ 按订单号前缀分发
        ├─ "ORD"  → 套餐订单   → orderService.HandlePaymentCallback()
        ├─ "CRCH" → 资产充值   → rechargeService.HandlePaymentCallback()
        └─ "ARCH" → 代理充值   → agentRechargeService.HandlePaymentCallback()

接口说明

基础路径

/api/admin/wechat-configs

权限要求:仅超级管理员(user_type=1)和平台用户(user_type=2)可访问,其他类型返回 1005

接口列表

方法 路径 说明
POST /api/admin/wechat-configs 创建配置
GET /api/admin/wechat-configs 查询配置列表(分页+筛选)
GET /api/admin/wechat-configs/active 查询当前生效配置
GET /api/admin/wechat-configs/:id 查询配置详情
PUT /api/admin/wechat-configs/:id 更新配置
DELETE /api/admin/wechat-configs/:id 软删除配置
POST /api/admin/wechat-configs/:id/activate 激活配置
POST /api/admin/wechat-configs/:id/deactivate 停用配置
POST /api/callback/fuiou-pay 富友支付回调(无需认证)

渠道类型provider_type

说明 必填支付字段
wechat 微信直连 wx_mch_idwx_api_v3_keywx_cert_contentwx_key_contentwx_serial_nowx_notify_url
fuiou 富友聚合支付 fy_ins_cdfy_mchnt_cdfy_term_idfy_private_keyfy_public_keyfy_api_urlfy_notify_url

敏感字段脱敏规则

接口响应中所有敏感字段均脱敏,数据库明文存储:

字段类型 脱敏规则 示例
Secret/Key 前4位 + *** + 后4位 abcd***7890
证书/私钥(长) 仅显示状态 [已配置] / [未配置]

更新脱敏字段:不传或传空字符串 = 保留原值;传新明文值 = 替换。

删除保护规则

条件 错误码 错误消息
配置 is_active=true 1171 不能删除当前生效的支付配置,请先停用
存在待支付订单引用 1172 该配置存在未完成的支付订单,暂时无法删除

富友支付 SDK

位置pkg/fuiou/

文件 说明
types.go WxPreCreateRequest/Response、NotifyRequest 等 XML 结构体
client.go Client 结构体、NewClient、RSA 签名/验签、HTTP 请求XML+GBK
wxprecreate.go WxPreCreate 方法(公众号 JSAPI + 小程序支付下单)
notify.go VerifyNotifyGBK→UTF-8 + XML 解析 + RSA 验签、BuildNotifyResponse

签名算法:字典序排列参数 → GBK 编码 → MD5 哈希 → RSA 签名 → Base64

新增依赖golang.org/x/textGBK 编解码)

数据库变更

新建表 tb_wechat_config(迁移 000078

字段组 字段 说明
基础信息 id, name, description, provider_type, is_active 配置基础字段
公众号 OAuth oa_app_id, oa_app_secret, oa_token, oa_aes_key, oa_oauth_redirect_url 公众号相关
小程序 OAuth miniapp_app_id, miniapp_app_secret 小程序相关
微信直连 wx_mch_id, wx_api_v3_key, wx_api_v2_key, wx_cert_content, wx_key_content, wx_serial_no, wx_notify_url provider_type=wechat 时使用
富友 fy_ins_cd, fy_mchnt_cd, fy_term_id, fy_private_key, fy_public_key, fy_api_url, fy_notify_url provider_type=fuiou 时使用
审计 creator, updater, created_at, updated_at, deleted_at 标准审计字段

新增字段

字段 类型 迁移文件
tb_order payment_config_id bigint, nullable 000079
tb_asset_recharge_record payment_config_id bigint, nullable 000080
tb_agent_recharge_record payment_config_id bigint, nullable 000081

新增错误码

错误码 常量 说明
1170 CodeWechatConfigNotFound 微信支付配置不存在
1171 CodeWechatConfigActive 不能删除/操作当前生效的支付配置
1172 CodeWechatConfigHasPendingOrders 该配置存在未完成的支付订单
1173 CodeFuiouPayFailed 富友支付失败
1174 CodeFuiouCallbackInvalid 富友回调验签失败
1175 CodeNoPaymentConfig 当前无可用的支付配置

审计日志

以下操作均记录审计日志(异步写入,失败不影响业务):

操作 operation_type 说明
创建配置 create after_data 存脱敏后配置
更新配置 update before/after_data 均脱敏
删除配置 delete before_data 存脱敏后配置
激活配置 activate before_data=旧配置after_data=新配置
停用配置 deactivate before/after_data 存状态变更

涉及文件

新增文件

层级 文件 说明
模型 internal/model/wechat_config.go WechatConfig 模型、渠道类型常量
DTO internal/model/dto/wechat_config_dto.go CRUD 请求/响应 DTO、脱敏方法
Store internal/store/postgres/wechat_config_store.go CRUD + 激活/停用 + 统计
Service internal/service/wechat_config/service.go 业务逻辑、缓存管理、删除保护
Handler internal/handler/admin/wechat_config.go 8 个 Handler 方法
路由 internal/routes/wechat_config.go 路由注册(含平台权限中间件)
SDK pkg/fuiou/types.go 富友 XML 结构体
SDK pkg/fuiou/client.go 富友 HTTP 客户端、签名/验签
SDK pkg/fuiou/wxprecreate.go 富友支付下单
SDK pkg/fuiou/notify.go 富友回调验签
迁移 migrations/000078_create_wechat_config_table.up.sql 创建 tb_wechat_config 表
迁移 migrations/000079_add_payment_config_id_to_order.up.sql tb_order 新增字段
迁移 migrations/000080_add_payment_config_id_to_asset_recharge.up.sql tb_asset_recharge_record 新增字段
迁移 migrations/000081_add_payment_config_id_to_agent_recharge.up.sql tb_agent_recharge_record 新增字段

修改文件

文件 变更说明
internal/model/order.go 新增 PaymentConfigID *uint 字段
internal/model/asset_wallet.go 新增 PaymentConfigID *uint 字段
internal/handler/callback/payment.go 支持富友回调 + 按订单前缀分发 + 按 payment_config_id 验签
internal/routes/order.go 新增 /api/callback/fuiou-pay 路由
internal/service/order/service.go 注入 wechatConfigService、下单时记录 payment_config_id
internal/bootstrap/ 系列 注册 WechatConfigStore/Service/Handler
cmd/api/docs.go / cmd/gendocs/main.go 注册 WechatConfigHandler

删除/精简文件YAML 支付方案遗留清理)

文件 变更说明
pkg/config/config.go 删除 PaymentConfig 结构体 + WechatConfig.Payment 字段
pkg/config/defaults/config.yaml 删除 wechat.payment: 整个配置节
pkg/wechat/config.go 删除 NewPaymentApp() 函数YAML/CertPath 方式已被 DB Base64 方案替代)
cmd/api/main.go 删除 validateWechatConfig 中所有 wechatCfg.Payment.* 相关校验代码

常量定义

// pkg/constants/wallet.goCard* 重命名为 Asset*,旧名保留为废弃别名)
AssetWalletResourceTypeIotCard   // 原 CardWalletResourceTypeIotCard
AssetWalletResourceTypeDevice    // 原 CardWalletResourceTypeDevice
AssetRechargeOrderPrefix         // "CRCH"(原 CardRechargeOrderPrefix
AssetRechargeMinAmount           // 最小充值金额(分)
AssetRechargeMaxAmount           // 最大充值金额(分)

// pkg/constants/redis.go
RedisWechatConfigActiveKey()     // "wechat:config:active"

// internal/model/wechat_config.go
ProviderTypeWechat = "wechat"    // 微信直连
ProviderTypeFuiou  = "fuiou"     // 富友

已知限制(留桩)

以下功能本次未实现,待后续会话补全:

  • 客户端支付发起WechatPayJSAPIWechatPayH5FuiouPayJSAPIFuiouPayMiniApp 均为留桩(返回"暂未实现"错误或 TODO 注释),当前仍保留 wechatPayment 单例注入
  • OAuth 配置动态加载OfficialAccountService 仍从环境变量读取,tb_wechat_config 中的 oa_* 字段仅存储,待 H5/小程序重构时切换

部署注意事项

  1. 执行数据库迁移000078~000081现有数据不受影响新字段均为 nullable
  2. 原环境变量 JUNHONG_WECHAT_PAYMENT_* 系列已不再读取,可清理
  3. 首次上线后,需要在管理后台手动创建并激活一个微信配置,否则第三方支付功能处于禁用状态(系统自动降级为仅支持钱包/线下支付)