--- name: 虚拟支付沙箱环境自动选择 overview: 为虚拟支付增加环境自动选择:保持 EnvAppKey/SandboxAppKey 双槽位配置,按「只填沙箱 key → env=1 沙箱;只填现网 key 或两把都填 → env=0 现网」的规则在客户端初始化时决定激活环境,并把 env 贯穿到道具同步、下单签名、订单记录与回调校验全链路。 todos: - id: wechat-env-select content: 改造 pkg/wechat/virtualpay.go:新增 resolveEnvKey 与 client.env,调整初始化校验,道具 API 带 env,QueryOrder/RefundOrder/BuildPaymentSign 去 env 入参并新增 GetVirtualPayEnv status: completed - id: service-env-wire content: 接入 internal/service/virtualpay.go:VirtualOrderCreate 改用 GetVirtualPayEnv 记录订单环境并适配签名调用 status: completed dependencies: - wechat-env-select - id: test-adapt content: 适配 virtualpay_test.go 现有测试并新增 TestResolveEnvKey 四分支单测 status: completed dependencies: - wechat-env-select - id: sync-config-docs content: 更新 config.yaml、config.example.yaml 与 README 中 WechatVirtualPay 的环境选择规则说明 status: completed dependencies: - wechat-env-select - id: verify-build content: 执行 go build、go vet、go test 与 read_lints 全量验证 status: completed dependencies: - service-env-wire - test-adapt - sync-config-docs --- ## 产品概述 为微信小程序虚拟支付(XPay)增加环境自动选择能力:配置保留双槽位(EnvAppKey 现网 / SandboxAppKey 沙箱),服务启动初始化时按规则自动判定激活环境,并把 env 贯穿到道具同步、下单签名、查单退款全链路。测试与上线切换只需修改配置文件,无需改代码。 ## 核心功能 - 环境自动选择:只填沙箱 AppKey 时激活沙箱环境(env=1,测试不真实扣款);只填现网 AppKey 或两把都填时激活现网环境(env=0);两把都空时初始化报错、虚拟支付禁用 - 全链路 env 贯穿:道具上传/发布、订单查询/退款、前端调起签名(signData 的 env 字段与 paySig)均使用激活环境的 key 与 env 值 - 订单记录环境:虚拟支付订单的 xpay_env 字段记录下单时的激活环境,发货推送按此校验(沙箱推送不会误发现网订单) - 环境切换零代码:切换测试/现网只需改配置后重启,启动时的全量道具同步会自动把商品发布到新激活的环境 ## 技术栈 - 语言与框架:Go 1.27(复用现有项目栈,不改架构) - 涉及模块:pkg/wechat/virtualpay.go(XPay 客户端)、internal/service/virtualpay.go(虚拟支付业务)、pkg/wechat/virtualpay_test.go(单元测试) - 配置:configs/config.yaml、configs/config.example.yaml(仅更新注释) ## 实现方案 ### 环境选择规则(初始化时一次决定) 抽成纯函数便于单测: ``` // resolveEnvKey 按配置决定激活环境: // EnvAppKey 非空 -> 现网(env=0,两把都填时现网优先); // EnvAppKey 空且 SandboxAppKey 非空 -> 沙箱(env=1); // 两把都空 -> 返回错误。 func resolveEnvKey(envAppKey, sandboxAppKey string) (appKey string, env int, err error) ``` `InitVirtualPayClient` 调用该函数得到激活 key 与 env:校验 OfferID 非空 + resolveEnvKey 成功;激活 key 存入 client 的 envAppKey 字段(保持 callXPay 签名逻辑不动),新增 `env int` 字段记录激活环境。日志输出当前激活环境,便于运维确认。 ### env 贯穿链路 ```mermaid flowchart LR A[config.yaml
EnvAppKey / SandboxAppKey] --> B[InitVirtualPayClient
resolveEnvKey] B --> C[client.envAppKey = 激活key
client.env = 0/1] C --> D[道具同步 API
body 带 env + 沙箱key签名] C --> E[BuildPaymentSign
signData.env = client.env
paySig 用激活key] C --> F[QueryOrder / RefundOrder
内部用 client.env] E --> G[VirtualOrderCreate
订单 xpay_env = GetVirtualPayEnv] G --> H[发货推送校验
推送 Env == 订单 xpay_env] ``` ### 关键改动点 **pkg/wechat/virtualpay.go** - 新增 `resolveEnvKey` 纯函数(规则见上) - `virtualPayClient` 增加 `env int` 字段;`InitVirtualPayClient` 改用 resolveEnvKey(原校验改为 OfferID 非空 + 至少一把 key) - 道具 API(StartUploadGoods/QueryUploadGoods/StartPublishGoods/QueryPublishGoods)body 增加 `"env": c.env`(微信按 env+key 双校验,注释标注字段联调以官方文档为准) - `QueryOrder`/`RefundOrder` 删除 env 入参(当前无 service 调用点,改动安全),内部使用 `c.env` - `BuildPaymentSign` 删除 env 入参,signData 的 env 字段与 paySig 使用 `c.env` 与 `c.envAppKey`(即激活环境) - 新增导出函数 `GetVirtualPayEnv() (int, error)` 供 service 层记录订单环境 **internal/service/virtualpay.go** - `VirtualOrderCreate`:`XPayEnv` 由写死的 `wechat.XPayEnvProd` 改为 `wechat.GetVirtualPayEnv()` 返回值;`BuildPaymentSign` 调用去掉 env 实参 - `SyncVirtualGoods` 道具同步调用不变(env 已在 wechat 层内部带入) - `handleGoodsDeliver` 的 Env 校验逻辑保持不动(订单 xpay_env 与推送 Env 匹配) **pkg/wechat/virtualpay_test.go** - 适配 `TestBuildPaymentSign`:client 构造改为含 env 字段、调用去掉 env 实参 - 新增 `TestResolveEnvKey`:覆盖四个分支(只填现网、只填沙箱、两把都填、两把都空) **配置与文档** - `configs/config.yaml` 与 `configs/config.example.yaml`:WechatVirtualPay 段注释更新为环境选择规则(只填沙箱 key 走沙箱测试;只填现网 key 或两把都填走现网) - `README.md` 配置表 WechatVirtualPay 行同步该规则 ## 目录结构 ``` pkg/wechat/ ├── virtualpay.go # [MODIFY] resolveEnvKey 纯函数、client.env 字段、初始化调整、道具 API 带 env、QueryOrder/RefundOrder 去 env 入参、BuildPaymentSign 去 env 入参、GetVirtualPayEnv └── virtualpay_test.go # [MODIFY] 适配现有签名测试 + 新增 TestResolveEnvKey 四分支单测 internal/service/ └── virtualpay.go # [MODIFY] VirtualOrderCreate 改用 GetVirtualPayEnv 记录订单环境 configs/ ├── config.yaml # [MODIFY] WechatVirtualPay 段注释更新(不改已填值) └── config.example.yaml # [MODIFY] WechatVirtualPay 段注释更新环境选择规则 README.md # [MODIFY] 配置表 WechatVirtualPay 行说明同步 ``` ## 实现注意事项 - 只改虚拟支付环境选择与 env 贯穿,不动支付架构、权益发放/回退、订单状态机、普通 JSAPI 支付 - 环境切换后重启即可:P0-2 修复后的全量道具同步会自动把商品发布到新激活环境,无需额外迁移 - 沙箱与现网的道具/订单/推送隔离由微信侧保证(按签名 key 与 env 双校验) - 验证:go build ./...、go vet ./...、go test ./pkg/wechat/ 通过;read_lints 无新增错误