wechatpay-apiv3 / wechatpay-go

微信支付 APIv3 的官方 Go Library
https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml
Apache License 2.0
983 stars 140 forks source link

Init NewClient Error #135

Closed lucky0604 closed 1 year ago

lucky0604 commented 1 year ago

bug 按照示例代码进行测试,商户号,秘钥等都是按照文档操作通过服务商后台进行配置,证书为下载好通过本地读取文件方式进行加载压缩包中提供好的apiclient_key.pem文件

opts := []core.ClientOption{
        option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
    }

报错:decrypt downloaded certificate failed: cipher: message authentication failed.

xy-peng commented 1 year ago

看提示是下载微信支付平台证书时失败了。

mchAPIv3Key 是对的吗?用这个密钥能成功下载证书吗?

你试试用 证书下载工具 下载证书。

lucky0604 commented 1 year ago

使用这个工具通过jar包下载,返回ERROR com.wechat.pay.contrib.apache.httpclient.auth.CertificatesVerifier - 找不到证书序列号对应的证书,序列号:41*********D08184497**************** 目前我的证书文件夹是通过https://kf.qq.com/faq/161222NneAJf161222U7fARv.html 这个文档按步骤生成,生成后下载下来的文件夹中有一个apiclient_key.pem,apiclient_cert.pem,apiclient_cert.p12和一个使用说明,按照说明文档中的描述这个key.pem应该是生成好可直接使用的,序列号是通过openssl x509 -in apiclient_cert.pem -noout -serial得到,但这个序列号和上面报错的序列号不同 在文档中提供的postman pre-request script文件中使用我现在的商户号和mchAPIv3Key以及apiclient_key.pem中的密钥发起请求可以得到返回,内容包含ciphertext和一个serial_no,并且这个serial_no和上面通过Java下载找不到序列号对应证书的序列号是一样的

xy-peng commented 1 year ago

商户 API 证书,是用来证实商户身份的。证书中包含商户号、证书序列号、证书有效期等信息,由证书授权机构(Certificate Authority ,简称 CA)签发,以防证书被伪造或篡改。如何获取请见 商户 API 证书 。 商户 API 私钥。商户申请商户 API 证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中。

微信支付平台证书。微信支付平台证书是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。商户使用微信支付平台证书中的公钥验证应答签名。获取微信支付平台证书需通过 获取平台证书列表 接口下载。

有两个证书,看看是不是弄混了。

lucky0604 commented 1 year ago

今天重新试了一下 步骤是这样

补充一下: https://developers.weixin.qq.com/community/develop/article/doc/000ce8d3ee8b70d868ed6185b5b013

根据这个文档里的验签说明,使用postman pre-request script进行微信支付平台证书的下载请求是正确的,那么应该说明我的证书,商户ID,证书序列号是正确的

代码片段

var (
        mchID                      string = "11111111"                               // 商户号
        mchCertificateSerialNumber string = "11111111111111" // 商户证书序列号
        mchAPIv3Key                string = "okadfdsfsdfsf**********"         // 商户APIv3密钥
    )

    // 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
    mchPrivateKey, err := utils.LoadPrivateKeyWithPath("/path/to/apiclient_key.pem")

    if err != nil {
        log.Print("load merchant private key error")
    }
    fmt.Println(mchPrivateKey)
    fmt.Println(mchID)
    fmt.Println(mchCertificateSerialNumber)
    fmt.Println(mchAPIv3Key)
    ctx := context.Background()
    // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
    opts := []core.ClientOption{
        option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
    }
    fmt.Println(opts)
    client, err := core.NewClient(ctx, opts...)
    if err != nil {
        log.Printf("new wechat pay client err:%s", err)
    }

    svc := jsapi.JsapiApiService{Client: client}

报错是在opts := []core.ClientOption{} 也就是说WithWechatPayAutoAuthCipher()方法应该有问题

xy-peng commented 1 year ago

根据这个文档里的验签说明,使用postman pre-request script进行微信支付平台证书的下载请求是正确的,那么应该说明我的证书,商户ID,证书序列号是正确的

你检查下你的 APIv3Key 是否正确?

从微信支付平台证书下载接口获取到的证书使用了 APIv3Key 做了 AES_GCM 加密。如果 APIv3Key 不正确,会导致 WithWechatPayAutoAuthCipher 失败。

lucky0604 commented 1 year ago

APIV3Key是正确的,在证书下,有v2和v3,这个检查了一下,就是v3key,应该不会出错 现在应该不是通过微信支付证书下载接口获取到的证书解密问题 看上面代码的逻辑,是初始化之前的core.ClientOption初始化问题,还没到调用jsapi去发起请求

xy-peng commented 1 year ago

初始化的过程,会使用 APIv3Key 解密微信支付平台证书。

在文档中提供的postman pre-request script文件中使用我现在的商户号和mchAPIv3Key以及apiclient_key.pem中的密钥发起请求可以得到返回,内容包含ciphertext和一个serial_no,并且这个serial_no和上面通过Java下载找不到序列号对应证书的序列号是一样的

你可以试试能否解密微信支付平台证书下载得到的 ciphertext。可以找一些 AES-GCM 在线解密的服务,也可以用 utils/aes 试试。

lucky0604 commented 1 year ago

使用utils/aes里的方法解密返回空,错误信息cipher: message authentication failed 这样应该说明是Apiv3Key错误吧? 但是我是在 image 这里配置的,应该不会出错啊

xy-peng commented 1 year ago

是这里配置。如果不影响现网业务,可以试着重置一次试试。

lucky0604 commented 1 year ago

可以了,重置一下ApiV3Key即可。 这里贴下总结,方便以后有相同情况的朋友进行错误排查: 若确定mchID, serialNumber, mchPrivateKey都正确的情况下,返回解密失败,同时有之前就存在的apiV3Key,可以尝试重置apiV3Key,虽然不知道具体是什么原理。

meloncut commented 1 month ago

可以了,重置一下ApiV3Key即可。 这里贴下总结,方便以后有相同情况的朋友进行错误排查: 若确定mchID, serialNumber, mchPrivateKey都正确的情况下,返回解密失败,同时有之前就存在的apiV3Key,可以尝试重置apiV3Key,虽然不知道具体是什么原理。

重置APIV3秘钥后解决+1