1. 背景介绍
微信支付使用HTTPS来保证通信安全,商户与微信支付服务器通信前,要在客户端的操作系统或者执行环境(如JRE等)中部署权威机构的根证书。 商户调用微信支付API的过程中,会用根证书来校验微信支付服务器及域名的真实性。
受Mozilla信任库的根证书最新信任策略(全球所有 CA 的可信根证书生成后最少 15 年更换一次,超过时间的可信根会逐渐被 Mozilla 停止信任)影响,DigiCert 将逐步停用旧根体系(G1)颁发 TLS/SSL 证书,并开始使用新根体系(G2)颁发 TLS/SSL 证书。
当前微信支付服务器证书的颁发根CA是Digicert Global Root CA (G1),微信支付计划于2024年8月5日0:00开始,逐步启用采用DigiCert Global Root G2根CA颁发的新服务器证书,商户的技术开发人员应仔细阅读本指引,并完成相关验证和修正,以免影响正常交易。
注意:
- 与微信支付系统直接对接(自行开发、外包开发)通信的商户可能受影响,商户需在2024年8月5日0:00之前参考指引完成相关验证和修正。服务商下属特约商户等间接对接微信支付的商户不受影响;
- 大多数操作系统和执行环境都默认内置了DigiCert Global Root G2根证书,因此大多数系统无需改动即可兼容新服务器证书。但如果商户的服务器/终端设备未内置G2根证书,或程序代码指定使用旧的G1根证书,则会受到影响,将出现服务中断的问题。请及时移除指定旧根证书操作,改用系统自带的信任库进行验证,并确保有DigiCert Global Root G2根证书;
- 新的 G2 根体系采用更高安全性的 SHA256 签名算法,且依然兼容当前主流的操作系统和移动设备,主流环境兼容情况如下:
对应的根证书文件请参考:
Baltimore CyberTrust Root:Download PEM、Download DER/CRT
Digicert Global Root CA:Download PEM 、Download DER/CRT
Digicert Global Root G2:Download PEM、Download DER/CRT
2. 商户须知
商户需确认与微信支付对接的系统或终端设备可兼容新的服务器证书,并参考“验证指引”章节的方法,在2024年8月5日0:00日之前完成验证:
-
如果验证结果正常,商户不需要做其他任何事情
-
如果验证结果异常,商户需要修改相关的系统实现或配置,且需最晚于2024年8月5日0:00之前完成修正,否则商户的业务系统与微信支付系统之间将不能正常进行HTTPS通讯,将影响业务正常运行。
商户在验证和修正过程中遇到问题,可在证书与密钥专区发帖咨询,我们会有专人进行解答回复。
3. 验证指引
验证方式:绑定host,请求已部署新证书的微信支付服务器
商户可通过修改操作系统的hosts文件来绑定IP,例如,可在hosts文件中新增一行如下内容,实现将域名"api.mch.weixin.qq.com"绑定到新证书环境:
43.142.224.50 api.mch.weixin.qq.com
在linux系统下,hosts文件的完整路径为"/etc/hosts",在Windows系统下,hosts文件的完整路径为"C:\Windows\System32\drivers\etc\hosts"。
商户应根据当前实际对接使用的域名来修改hosts文件配置,已部署新服务器证书的验证环境host和IP对应关系如下:
注意:
1. host环境可以访问的接口与正式环境完全一致,且真实生效,被视为生产正式业务。在验证之前,请充分评估对贵司业务系统以及业务的影响;
2. 验证完成后,请及时恢复服务器上的host配置,微信支付服务器证书更新完成后,此处使用的IP会被关停;
3. 需要用跟生产环境相同的操作系统、执行环境、开发语言及程序逻辑进行验证。使用curl等命令行工具验证成功,并不代表你的系统支持了新的服务器证书;
4. 逐一验证所有正在使用的微信支付接口,如果均能正常使用,说明你的系统支持微信支付新的服务器证书。反之,则需要根据修正指引排查问题并修正。
4. 修正指引
大部分情况下,验证失败是以下两种情况导致的:
情况一:程序中指定了根证书,但是指定的根证书中仅包含了旧的G1根证书;
情况二:服务器上没有部署新的G2根证书。
可通过以下两个方案修正:
方案一:删除指定根证书的代码。当程序中不指定根证书时,会使用系统自带的根证书。绝大部分系统中已内置了新的G2根证书,所以删除指定根证书的代码,不会影响到你的现有业务
方案二:更新根证书。往truststore或者根证书信任文件中追加新的G2根证书(注意:追加新的根证书时,需要保留老的G1根证书)
推荐使用“方案一”来修正,该方案的兼容性更好。原因是:新的G2根证书将于 2029年4月15日不再被Mozilla信任,到时候同样要更换新的根证书。使用方案一修复的话,你的系统中很可能已内置了后续需更换使用的根证书,从而不受影响。如果使用方案二进行修复的话,在 2029年4月15日仍可能需安装新的根证书。
下面介绍各种开发语言可能碰到的问题及解决方法:
JAVA常见错误:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
可能原因:代码中设置了javax.net.ssl.trustStore
, 可以在代码中搜索关键字trustStore
或者TrustManager
来确认。
解决方法:
方法一:删除掉指定javax.net.ssl.trustStore
的代码
方法二:安装新的根证书, 往指定的trustStore
中添加新的根证书。操作命令:keytool -importcert -keystore cacerts -storepass changeit -noprompt -file ./DigiCertGlobalRootG2.crt -alias digicertglobalrootg2
C++常见错误:
cURL error 60: SSL certificate: unable to get local issuer certificate.
CURLE_SSL_CACERT (60) peer certificate cannot be authenticated with known CA certificates.
可能原因:代码中设置了CURLOPT_CAINFO
, 可以在代码中搜索关键字CURLOPT_CAINFO
来确认。
解决方法:
方法一:删除掉curl_easy_setopt(pCurl,CURLOPT_CAINFO,"./rootca.pem");
相关的代码
方法二:更新rootca.pem,用libcurl官网最新的替换即可
PHP常见错误:
cURL error 60: SSL certificate: unable to get local issuer certificate.
CURLE_SSL_CACERT (60) peer certificate cannot be authenticated with known CA certificates.
可能原因:使用libcurl时设置了CURLOPT_CAINFO
,可以在代码中搜索关键字CURLOPT_CAINFO
来确认。
解决方法:
方法一:删除掉类似curl_setopt(pCurl,CURLOPT_CAINFO,"./rootca.pem");
的代码
方法二:更新rootca.pem,用libcurl官网最新的替换即可
C#常见错误:
RemoteCertificateValidationCallback
设置的回调函数返回false
可能原因:操作系统中没有新的根CA
解决方法:安装新的根证书
Python常见错误:
SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)
可能原因:代码中用verify
指定了根证书文件,可以在代码中搜索关键字“verify”来确认。类似的代码如:
response = requests.post(
"https://api.mch.weixin.qq.com/secapi/pay/refund",
verify="./rootca.pem",
……
);
解决方法:
方法一:删除verify
参数
方法二:更新rootca.pem,用libcurl官网最新的替换即可
go常见错误:
x509: certificate signed by unknown authority .
可能原因:发起https时, 用RootCAs
指定了根证书文件,可以在代码中搜索关键字RootCAs
来确认。类似的代码如:
roots := x509.NewCertPool()
roots.AppendCertsFromPEM([]byte(rootPEM))
tr := &http.Transport{
TLSClientConfig: &tls.Config{RootCAs: roots},
}
client := &http.Client{Transport: tr}
解决方法:
方法一:删除配置项RootCAs
方法二:更新rootca.pem,用libcurl官网最新的替换即可
Ruby常见错误:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
可能原因:发起https时, 用ssl_ca_file
或者cert_store
指定了根证书文件,可以在代码中搜索关键字ssl_ca_file
或者cert_store
来确认。类似的代码如:
response = RestClient::Resource.new(
"https://api.mch.weixin.qq.com/secapi/pay/refund",
:ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("./apiclient_cert.pem ")),
:ssl_client_key => OpenSSL::PKey::RSA.new(File.read("./apiclient_key.pem ")),
:ssl_ca_file => "./rootca.pem",
:verify_ssl=>OpenSSL::SSL::VERIFY_PEER).post(data);
或者
sock.cert_store.add_path('/usr/lib/ssl/certs/weixin')
sock.cert_store.add_file('/usr/lib/ssl/certs/weixin/rootca.pem')
解决方法:
方法一:删除ssl_ca_file
及cert_store
指定的参数
方法二:更新rootca.pem,用libcurl官网最新的替换即可
NodeJs常见错误:
Caught exception: Error: CERT_UNTRUSTED
可能原因:代码中用ca
指定了根证书文件。 可以在代码中搜索关键字ca
或者rootca
来确认。类似的代码如:
const options = {
hostname: api.mch.weixin.qq.com ',
pfx: await readFile('./apiclient_cert.p12'),
ca: await readFile('./rootca.pem'),
};
const req = https.request(options, (res) => {
……
解决方法:
方法一:删除ca
指定的参数
方法二:更新rootca.pem,用libcurl官网最新的替换即可
其它语言请参考对应的TLS/SSL库相关手册。
5. 常见问题
Q1:什么是服务器证书?
A:服务器证书通常又叫“SSL证书”、“HTTPS证书”,它由权威CA机构颁发,用于对网站进行身份鉴定,并使客户端与网站之间通过TLS/SSL协议建立起安全传输通道。微信支付的服务器证书是由权威机构DigiCert颁发,商户调用微信支付API时,能通过该证书来认证微信支付的身份。
Q2:什么是根证书?
A:根证书是权威CA机构给自己颁发的证书,是信任链的起始点,是证书颁发机构(CA)与用户建立信任关系的基础。操作系统、浏览器、TLS/SSL开发库通常随软件发行包预置其信任的权威机构的根证书。
Q3:根证书和API证书是同一个吗?
A:不是,两者没有关系。“根证书”是用来校验微信支付的域名及服务器的真实性, 通常内置在操作系统或者执行环境(如JRE等)中;“API证书”是用来证实商户身份的,通常在调用微信支付v2的出资金类接口(如:退款、企业红包、企业付款等)或v3接口时,才会使用到API证书。
Q4:微信支付为什么要更换服务器证书?
A:根证书存在有效期,根证书到期后无法继续被用来校验服务器证书。
因此,微信支付跟权威机构(CA)申请了新的服务器证书。避免在老的根证书过期后,商户调用微信支付API时出现问题。
Q5:微信支付更换服务器证书,需要商户配合做哪些事情?
A:需要商户的开发技术人员做以下事情:
- 验证你的系统是否兼容微信支付新的服务器证书。
- 若支持的话,不需要做任何操作。若不支持,需要参考修正指引排查原因并修正。
注意:
- 商户按指引进行验证或安装新的根证书, 不会产生任何费用;
- 商户平台的API证书也不需要更换;
- 商户正在使用的其它https证书不需要更换或者升级。
Q6:商户如何核实服务器上是否已内置了G2根证书?
A:以Linux系统为例。Linux系统信任根证书库的保存位置因发行版本不同而有所差异:Debian/Ubuntu:/etc/ssl/certs/ca-certificates.crt
CentOS/RHEL/Fedora/TencentOS:/etc/pki/tls/certs/ca-bundle.crt
商户可以使用以下命令来核实系统是否已内置了G2根证书:
grep "DigiCert Global Root" /etc/pki/tls/certs/ca-bundle.crt
# DigiCert Global Root CA
# DigiCert Global Root G2
备注:示例显示系统已内置了G1和G2根证书
Q7:微信支付更换证书前,可以提前安装根CA证书吗?
A:必须提前安装,且建议在2024年8月5日0:00之前提前安装。因为从2024年8月5日0:00开始,微信支付会在生产环境逐步灰度启用新服务器证书,以校验商户的系统是否兼容新证书。微信支付在更换新证书的过程中,会同时使用新老两个服务器证书,商户要能正常处理这种情况。因此,商户的服务器上需要包含新老两个根证书。
Q8:商户需在什么时候完成验证和修正?不验证会有什么影响?
A:商户应在2024年8月5日0:00之前完成验证和修正。如果商户侧系统的实现方式已能兼容新的服务器证书,那么不会影响业务;如果商户侧系统的实现方式不能兼容新的服务器证书,那么会导致商户的系统与微信支付的系统不能正常交互,影响业务。
Q9:如果商户无法按时完成兼容性修正,在微信支付灰度新证书时遇到异常应如何处理?
A:如果商户的系统经验证是不能兼容新证书的,商户应在2024年8月5日0:00之前完成修正。如果无法按时完成修正,我们可提供仍使用旧证书的临时环境,商户可通过host绑定IP的方式使用,以临时规避证书更换产生的影响。请务必在2024年11月30日0:00之前完成系统修正,并取消绑定临时环境IP,恢复以正常的方式对接微信支付的生产正式环境。 临时环境host和IP对应关系如下:
6. 特别提醒
- 为提前发现商户“是否会受到证书更换的影响?”“有没有升级完根证书?”,微信支付将于2024年8月5日0:00开始,把商户的部分请求转发到部署了新证书的服务器上,并逐步提升灰度比例。当商户不支持新的服务器证书时,会出现SSL相关的错误,通常情况下重试即可恢复;
- 根证书升级仅跟服务器和应用程序相关,与商户号没关系。只要在同一台服务器升级完成后,该服务器上使用的所有商户号都可以正常使用的;
- 如果你是通过代理服务器向微信支付发起请求的话,那么需要修改代理服务器的配置。
7. 联系我们
如果商户在验证或者修正问题的过程中遇到困难,可在证书与密钥专区发帖咨询,我们会有专人进行解答回复。
8. 附录
DigiCert 原文公告:DIGICERT ROOT AND INTERMEDIATE CA CERTIFICATE UPDATES 2023
嫌麻烦的可以把下面这一堆域名解析设置都添加到 host 文件里面,验证完再删除就行了:
我是 Windows Server 服务器,修改完 hosts 文件并保存之后,上面的 IP 解析设置立刻就生效了。
可以在命令行执行 ping api.mch.weixin.qq.com -4 命令来确认一下,如果返回的是 Pinging api.mch.weixin.qq.com [43.142.224.50] with 32 bytes of data 这样的内容,说明域名的 IP 解析设置有效。
如果没生效,就执行一下 ipconfig /flushdns ,清空 DNS 缓存再 ping 一下试试。
如果你是Debian/Ubuntu,可以使用下面的命令查看是否包含G2证书
1.0 商户可以使用以下命令来核实系统是否已内置了G2根证书:
grep "DigiCert Global Root" /etc/pki/tls/certs/ca-bundle.crt # DigiCert Global Root CA # DigiCert Global Root G2 但是命令执行后没有# DigiCert Global Root CA和# DigiCert Global Root G2 2.0 商户可通过修改操作系统的hosts文件来绑定IP, 例如,可在hosts文件中新增一行如下内容,实现将域名"api.mch.weixin.qq.com"绑定到新证书环境: 43.142.224.50 api.mch.weixin.qq.com 执行systemctl restart network 执行业务代码是可以访问api.mch.weixin.qq.com的 请问这种情况是不是就验证过了?但是命令执行服务器系统没有G2证书这样算可以了吗
俩个问题咨询:
1.
我这个里面还有G3,是不是也是ok的呢?
2."方案一:删除指定根证书的代码。当程序中不指定根证书时,会使用系统自带的根证书。绝大部分系统中已内置了新的G2根证书,所以删除指定根证书的代码,不会影响到你的现有业务"
这个“当程序中不指定根证书时,会使用系统自带的根证书”,这个是操作系统实现的吗,以php为例,是否需要改php.ini相关配置。
记录一下处理根证书的做法, 也许对其他人会有帮助
我这边有三台 centos 服务器, 版本分别是 7.0、7.2 和 7.7, 这里重点说 7.0 那一台, 后面两台有 G2 和 G3 证书, 不需要有下面的处理
7.0 那一台运行下面命令的结果是空的
$ grep "DigiCert Global Root" /etc/pki/tls/certs/ca-bundle.crt
之后尝试下载证书时提示: To connect to cacerts.digicert.com insecurely, use --no-check-certificate
$ wget https://cacerts.digicert.com/DigiCertGlobalRootG2.crt
直接对 dc 官网都不支持, 可以预见, 这一台机器上肯定是需要处理的, 之后用下面命令安装根证书
# yum install ca-certificates
安装后再次运载上面的 wget 就没有要加 --no-check-certificate 这个提示了, 也没有必要将证书下载下来再运行这个命令: keytool -importcert -keystore cacerts -storepass changeit -noprompt -file ./DigiCertGlobalRootG2.crt -alias digicertglobalrootg2
用以下命令查看有没有 DC 的证书以及对应的过期时间
# awk -v cmd='openssl x509 -noout -subject -enddate' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-bundle.crt | grep -A1 'DigiCert Global Root' subject= /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA notAfter=Nov 10 00:00:00 2031 GMT subject= /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root G2 notAfter=Jan 15 12:00:00 2038 GMT subject= /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root G3 notAfter=Jan 15 12:00:00 2038 GMT
可以看到 CA 证书的过期时间是 2031-11-10, G2 和 G3 的过期时间是 2038-01-15, 上面 wget 以及 keytool 的部分就没必要再运行了
后续跑验证如果还有问题, 可以尝试更新一下证书
# update-ca-trust force-enable # update-ca-trust extract
总的来说, 在低版本的 centos 上安装一下证书, 有问题就刷一下让证书生效就可以了
我服务器是windows server 微信支付接口V2 调用官方自代的代码,验证不通过,不知道在哪里删除,删除掉指定
javax.net.ssl.trustStore
的代码,知道的朋友麻烦指导一下,感谢
服务器执行这个结果怎么处理,安装了也没有效果
如果执行grep "DigiCert Global Root" /etc/pki/tls/certs/ca-bundle.crt后有如下结果, 是否就说明自己的项目不需要做任何其他调整?
# DigiCert Global Root CA
# DigiCert Global Root G2
# DigiCert Global Root G3
Centos6.5返回 如下内容:也是支持的吧?
# grep "DigiCert Global Root" /etc/pki/tls/certs/ca-bundle.crt
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3
Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3
麻烦问下,我之前的程序中写死了 微信支付平台证书, 然后用这次验证方式增加了hosts:
43.142.224.50 api.mch.weixin.qq.com
验证成功,请问我写死的 微信支付平台证书 用改吗? 或者需要改的话 如何获取?谢谢。