代码 对接支付接口报 SSL certificate problem:别急着关 VERIFYPEER,先查 CA 路径、SNI 与老 ca-bundle

2026-10-02 09:01:23

对接支付接口报 SSL certificate problem:别急着关 VERIFYPEER,先查 CA 路径、SNI 与老 ca-bundle

对接微信支付、支付宝、Stripe 这类 HTTPS 接口,第一次跑通前最常见的拦路虎不是签名,是 TLS 握手阶段就断了:SSL certificate problem: unable to get local issuer certificate、Go 里的 x509: certificate signed by unknown authority、Java 的 PKIX path building failed。这类报错和签名无关——请求根本没走到对方业务层。最省事的「修复」是在代码里加一行 CURLOPT_SSL_VERIFYPEER => false,它能跑通,但把证书校验整个关掉,等于 HTTPS 退回明文加密,中间人可随手换证书。下面按「先定位 → 再对症修」记一遍。

一、先确认坏在哪一段

浏览器打得开的域名,程序却报证书错,第一步是看客户端实际拿到了什么链、有没有带 SNI。

curl -v https://api.example.com/ 2>&1 | grep -Ei 'SSL|TLS|subject|issuer|verify'
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts -status = 7.71 用 `CURLOPT_SSL_OPTIONS=CURLSSLOPT_NATIVE_CA`(Windows 尤其需要);
- libcurl >= 7.77 用 `CURLOPT_CAINFO_BLOB`;
- `CURLOPT_SSL_VERIFYHOST` 别设 0。

Linux:

- Debian/Ubuntu 放 `/usr/local/share/ca-certificates/` 后 `update-ca-certificates`;
- RHEL/CentOS 放 `/etc/pki/ca-trust/source/anchors/` 后 `update-ca-trust`;
- 不要手改合并文件。

Docker/scratch:

- Alpine:`apk --no-cache add ca-certificates && update-ca-certificates`;
- scratch:

```dockerfile
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
  • Go 可 import _ "golang.org/x/crypto/x509roots/fallback"(未实测)。

Node 用 NODE_EXTRA_CA_CERTS,Java 用 keytool -importcert -cacerts,Python 用 verify=。

四、SNI 与 IP 直连

同机多域名靠 SNI 选证书;用 openssl s_client -connect 10.0.0.5:443 -servername api.example.com 判断是否中间层丢 SNI。

五、老 ca-bundle 与服务端链不全

服务端只配站点证书没配中间证书,浏览器缓存过所以你看不出,程序客户端挂;链顺序 site → intermediate。

客户端 CA 库过旧:Let's Encrypt DST Root CA X3 于 2021-09-30 过期后,Android

  • PHP cURL CA 配置:
复制全文 生成海报 接口对接 HTTPS TLS 证书 排障

推荐文章

程序员茄子在线接单