前言
最近在接微信支付的时候,遇到了一个 无可用平台证书
的报错,记录下解决过程。
经过一番查找,发现这个问题是由于平台证书存在过期时间,需要开发这由于没有及时更换,会导致支付失败。
因为在 v3 接口中,微信强制只允许使用公钥进行验签。而相关的报错信息模糊,没有明显的公告,加上官方
给出的示例也没有更新到使用公钥的版本,导致接入的时候在这个问题上浪费了不少时间。
名词解释
商户id、商户号(mcnId)
微信支付平台 - 账户中心 - 商户信息 - 基本账户信息 - 微信支付商户号
证书序列号(SerialNumber,SerialNo)
微信支付平台 - 账户中心 - API安全 - API 证书管理 - 证书序列号
也可以使用命令行查看
1
|
openssl x509 -in apiclient_cert.pem -noout -serial
|
私钥需要下载工具生成。具体位置为
微信支付平台 - 账户中心 - API 安全 - API 证书管理
APIv3 Key
APIv2 已经停止支持,使用 v3 即可
微信支付平台 - 账户中心 - API安全 - 解密回调 - APIv3 密钥(自己设置的32位字符)
公钥、公钥ID
微信支付平台 - 账户中心 - API安全 - 微信支付公钥
SDK调整
官方提供的 SDK
github.com/wechatpay-apiv3/wechatpay-go v0.2.20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package main
import (
"context"
"github.com/rs/zerolog/log"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
)
func main() {
ctx := context.Background()
mchId := "xxx" // 商户号
mchCertSerialNo := "xxx" // 商户证书序列号
publicKeyId := "xxx" // 公钥ID
// 载入私钥
mchPrivateKey, err := utils.LoadPrivateKeyWithPath("xxx_key.pem")
if err != nil {
log.Fatal().Err(err).Msg("load private key failed")
}
// 载入公钥
mchPublicKey, err := utils.LoadPublicKeyWithPath("xxx.pem")
if err != nil {
log.Fatal().Err(err).Msg("load public key failed")
}
// 初始化客户端
opts := []core.ClientOption{
option.WithWechatPayPublicKeyAuthCipher(mchId, mchCertSerialNo, mchPrivateKey, publicKeyId, mchPublicKey),
}
client, err := core.NewClient(ctx, opts...)
if err != nil {
log.Error().Err(err).Msg("init client failed")
}
_ = client
}
|
第三方 SDK (go-pay)
github.com/go-pay/gopay v1.5.109
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import (
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/wechat/v3"
"github.com/rs/zerolog/log"
)
func main(){
client, err := wechat.NewClientV3(mchId, mchCertificateSerialNumber, mchAPIv3Key, mchPrivateKeyStr)
if err != nil {
log.Fatal().Err(err).Msg("init client failed")
}
// 需要使用公钥解密
err = client.AutoVerifySignByCert(mchPublicKey, publicKeyId)
if err != nil {
log.Fatal().Err(err).Msg("init client failed")
}
client.DebugSwitch = gopay.DebugOn
}
|
参考