微信支付新服务器证书兼容性验证指引
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