first commit
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
---
|
||||
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<br/>EnvAppKey / SandboxAppKey] --> B[InitVirtualPayClient<br/>resolveEnvKey]
|
||||
B --> C[client.envAppKey = 激活key<br/>client.env = 0/1]
|
||||
C --> D[道具同步 API<br/>body 带 env + 沙箱key签名]
|
||||
C --> E[BuildPaymentSign<br/>signData.env = client.env<br/>paySig 用激活key]
|
||||
C --> F[QueryOrder / RefundOrder<br/>内部用 client.env]
|
||||
E --> G[VirtualOrderCreate<br/>订单 xpay_env = GetVirtualPayEnv]
|
||||
G --> H[发货推送校验<br/>推送 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 无新增错误
|
||||
Reference in New Issue
Block a user