微信支付 APIv3 平台证书切公钥:回调灰度微信说了算,应答灰度得自己盯满 7 天
项目信息
- 如何从平台证书切换成微信支付公钥:https://pay.wechatpay.cn/doc/v3/partner/4012925289
- 常见问题:https://pay.wechatpay.cn/doc/v3/merchant/4013038816
背景
微信支付 APIv3 支持「平台证书」和「微信支付公钥」两种模式来构造签名验签。平台证书有效期 5 年,每 5 年商户需要主动更换一次;微信支付公钥没有有效期,维护成本更低。为避免更换不及时带来的系统风险,可以把平台证书模式切换成微信支付公钥模式。
前置限制
平台证书切换微信支付公钥的流程,不能和「灰度更换新平台证书」流程同时进行。如果正在灰度更换新的平台证书,需要先停掉该灰度,才能做公钥切换。
公钥灰度和切换按「商户号」维度进行。如果同一个商户号在多个项目里使用,所有项目都要先支持公钥模式,才能点【开始更换】。
两个灰度维度
1. 回调使用公钥的比例:微信支付控制
按固定进度自动灰度,商户不可操作:
| 天数 | 比例 |
|---|---|
| 第 1 天 | 0.1% |
| 第 2 天 | 1% |
| 第 3 天 | 5% |
| 第 4 天 | 10% |
| 第 5 天 | 20% |
| 第 6 天 | 50% |
| 第 7 天 | 100% |
灰度期间,按上述比例用公钥签名,剩余比例用平台证书签名。因此商户的回调必须根据请求头 wechatpay-serial 判断本次回调用的是公钥还是平台证书,再用对应的公钥或平台证书验签。
2. 应答使用公钥的比例:商户自己控制
判断依据是 HTTP 请求头 Wechatpay-Serial 里带的是微信支付公钥 ID 还是平台证书 ID。公钥 ID 带有 PUB_KEY_ID_ 前缀。
curl -X GET https://api.mch.weixin.qq.com/v3/xxx \
-H "Authorization: WECHATPAY2-SHA256-RSA2048 mchid=\"1900000001\",..." \
-H "Accept: application/json" \
-H "Wechatpay-Serial: PUB_KEY_ID_00000000000000000000000000000000"
应答使用公钥比例 = 近 7 天用微信支付公钥调接口次数 / 近 7 天 v3 接口总调用次数。数据更新频率是 1 小时,所以全量切到公钥之后还要再等 7 天,比例才会变成 100%。
获取公钥
商户号的超级管理员或安全联系人,在【商户平台】→【账户中心】→【API安全】→【微信支付公钥】→【管理公钥】页面下载 pem 格式公钥文件,也可以在该页面查询公钥 ID。
申请公钥后默认不开启公钥切换,需要在【管理公钥】页点击「开启公钥切换」按钮后才可用。如果已经在请求头 wechatpay-serial 传了公钥 ID,但微信返回的应答还是用平台证书签名,多半就是这个开关没开。
完成切换
当所有业务场景的请求都已携带公钥 ID,且经过 7 天回调灰度后,【回调使用公钥比例】和【应答使用公钥比例】都为 100%,确认业务覆盖完全,点击【确认切换】,变更完成。
切换完成后,除敏感字段加解密场景外,回调场景和应答场景的 HTTP 请求头可以不带上 Wechatpay-Serial,默认微信支付会使用微信支付私钥签名。
常见坑
- 微信支付提供的
wechatpay-java库中,RSACombinedNotificationConfig会自动调用下载平台证书的接口。当回调比例进度条为 100% 时,应改为使用RSAPublicKeyNotificationConfig;否则会有一部分自动下载平台证书的流量,导致应答场景比例无法灰度到 100%。 - 需要计算好平台证书的过期时间和灰度时间,避免平台证书过期但公钥灰度未完成导致报错。
- 灰度中发现问题或有排期冲突,可以点「停止更换」暂停,但请谨慎操作。