wechatpay-apiv3 / wechatpay-go

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

搞了一天了,没找到原因,证书代码什么的都没问题,支付回调时验证报错 #67

Closed WeinanHu closed 3 years ago

WeinanHu commented 3 years ago

报错:stdout: not valid wechatpay notify request: validate verify fail serial=[33AC6BABEBEE5B9F83D36C06BECBF24B20CE99CC] request-id=[] err=verifty signature with public key err:crypto/rsa: verification error

每次都要支付一下,调试很麻烦,试了很多

EmmetZC commented 3 years ago

你好,方便发一下你是如何初始化 notify.Handler 的吗?(贴代码的时候注意不要把商户私钥和 APIv3key的贴出来)

aassaadd commented 3 years ago

我也碰到同样的问题,网上看需要自己去实现这块业务,持续观望,希望官方跟进

aassaadd commented 3 years ago

certVisitor, err := payutils.LoadCertificateWithPath(config.GetConfig().WxPayCertificatePath) if err != nil { logger.Error(err.Error()) return nil, err } handler := notify.NewNotifyHandler(config.GetConfig().WxPayMchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(core.NewCertificateMapWithList([]*x509.Certificate{certVisitor})))

xy-peng commented 3 years ago
certVisitor, err := payutils.LoadCertificateWithPath(config.GetConfig().WxPayCertificatePath)

WxPayCertificatePath是通过 API 下载得到的微信支付平台证书,还是商户的证书?

商户平台证书是指由微信支付 负责申请的,包含微信支付平台标识、公钥信息的证书。商户可以使用平台证书中的公钥进行验签。微信支付平台证书请调用“获取平台证书接口” 获取。

EmmetZC commented 3 years ago

certVisitor, err := payutils.LoadCertificateWithPath(config.GetConfig().WxPayCertificatePath) if err != nil { logger.Error(err.Error()) return nil, err } handler := notify.NewNotifyHandler(config.GetConfig().WxPayMchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(core.NewCertificateMapWithList([]*x509.Certificate{certVisitor})))

这个初始化过程看起来没有问题,我再问个问题:接收到的回调通知http.Request在传入 ParseNotifyRequest 方法之前,有做过其他操作吗?比如读取 req.Body

aassaadd commented 3 years ago

我找到问题 了,使用证书下载 这个函数 就可以了 certVisitor := downloader.MgrInstance().GetCertificateVisitor(config.GetConfig().WxPayMchID) handler := notify.NewNotifyHandler(config.GetConfig().WxPayMchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certVisitor)) 我这没问题了,

WeinanHu commented 3 years ago

certVisitor, err := payutils.LoadCertificateWithPath(config.GetConfig().WxPayCertificatePath) if err != nil { logger.Error(err.Error()) return nil, err } handler := notify.NewNotifyHandler(config.GetConfig().WxPayMchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(core.NewCertificateMapWithList([]*x509.Certificate{certVisitor})))

这个初始化过程看起来没有问题,我再问个问题:接收到的回调通知http.Request在传入 ParseNotifyRequest 方法之前,有做过其他操作吗?比如读取 req.Body

我有将body转成map打印过

WeinanHu commented 3 years ago

我将所有验签和解密代码提取出来,使用本地证书,自己重新组合实现了一下就没问题,用该go库自动下载证书的功能就报错

WeinanHu commented 3 years ago

用该go库的本地证书验签解密也报错,反正搞不通。只能自己重写一下

EmmetZC commented 3 years ago

certVisitor, err := payutils.LoadCertificateWithPath(config.GetConfig().WxPayCertificatePath) if err != nil { logger.Error(err.Error()) return nil, err } handler := notify.NewNotifyHandler(config.GetConfig().WxPayMchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(core.NewCertificateMapWithList([]*x509.Certificate{certVisitor})))

这个初始化过程看起来没有问题,我再问个问题:接收到的回调通知http.Request在传入 ParseNotifyRequest 方法之前,有做过其他操作吗?比如读取 req.Body

我有将body转成map打印过

有没有可能是你的前置逻辑把 http.Request 的 body 耗尽了,导致 notify.Handler 读到的 body 是空的,所以才验签失败了?

WeinanHu commented 3 years ago

certVisitor, err := payutils.LoadCertificateWithPath(config.GetConfig().WxPayCertificatePath) if err != nil { logger.Error(err.Error()) return nil, err } handler := notify.NewNotifyHandler(config.GetConfig().WxPayMchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(core.NewCertificateMapWithList([]*x509.Certificate{certVisitor})))

这个初始化过程看起来没有问题,我再问个问题:接收到的回调通知http.Request在传入 ParseNotifyRequest 方法之前,有做过其他操作吗?比如读取 req.Body

我有将body转成map打印过

有没有可能是你的前置逻辑把 http.Request 的 body 耗尽了,导致 notify.Handler 读到的 body 是空的,所以才验签失败了?

应该是证书问题,我换了gopay另一个库里的验签算法,也一样报错,这里验签证书能问一下要用哪里的证书吗?从商户网站下载证书有3个apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem我应该用哪个,我都试了都不行,如果不是这3个,那我要从哪里弄证书

EmmetZC commented 3 years ago

certVisitor, err := payutils.LoadCertificateWithPath(config.GetConfig().WxPayCertificatePath) if err != nil { logger.Error(err.Error()) return nil, err } handler := notify.NewNotifyHandler(config.GetConfig().WxPayMchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(core.NewCertificateMapWithList([]*x509.Certificate{certVisitor})))

这个初始化过程看起来没有问题,我再问个问题:接收到的回调通知http.Request在传入 ParseNotifyRequest 方法之前,有做过其他操作吗?比如读取 req.Body

我有将body转成map打印过

有没有可能是你的前置逻辑把 http.Request 的 body 耗尽了,导致 notify.Handler 读到的 body 是空的,所以才验签失败了?

应该是证书问题,我换了gopay另一个库里的验签算法,也一样报错,这里验签证书能问一下要用哪里的证书吗?从商户网站下载证书有3个apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem我应该用哪个,我都试了都不行,如果不是这3个,那我要从哪里弄证书

验签需要使用微信支付平台证书,平台证书需要通过通过平台证书下载接口进行下载。 本SDK中提供了平台证书下载工具将平台证书下载到本地。 你也可以参考使用平台证书下载管理器初始化 notify.Handler,这样可以在运行时自动下载平台证书,无需手动下载。

EmmetZC commented 3 years ago

报错:stdout: not valid wechatpay notify request: validate verify fail serial=[33AC6BABEBEE5B9F83D36C06BECBF24B20CE99CC] request-id=[] err=verifty signature with public key err:crypto/rsa: verification error

每次都要支付一下,调试很麻烦,试了很多

但是一般情况下如果证书不正确,错误提示会直接提示证书找不到才对。但是你的提示时验签失败,这里就比较奇怪了。 方便把你的代码(脱敏后)发给我看看怎么回事吗?

WeinanHu commented 3 years ago

报错:stdout: not valid wechatpay notify request: validate verify fail serial=[33AC6BABEBEE5B9F83D36C06BECBF24B20CE99CC] request-id=[] err=verifty signature with public key err:crypto/rsa: verification error 每次都要支付一下,调试很麻烦,试了很多

但是一般情况下如果证书不正确,错误提示会直接提示证书找不到才对。但是你的提示时验签失败,这里就比较奇怪了。 方便把你的代码(脱敏后)发给我看看怎么回事吗?

有没有可能是你的前置逻辑把 http.Request 的 body 耗尽了,导致 notify.Handler 读到的 body 是空的,所以才验签失败了? 确实是这个原因,我去掉了对body的打印就可以了

WeinanHu commented 3 years ago

可以了,已解决

WeinanHu commented 3 years ago

建议做个错误提示,提示一下body为空,免得后面有人又来踩坑

EmmetZC commented 3 years ago

好的,谢谢提议。