OpenSSL 生成的支付网关 SSL certificate 无效
结论
问题大概率不在 PATH,而是证书生成方式、商户号、文件格式或证书交换流程不符合要求。
支付网关所说的 certificate,通常不是网站使用的 HTTPS/TLS 证书,而是用于支付报文签名和验签的商户证书。在命令行中运行 OpenSSL 并生成自签名证书,不代表网关就能使用该证书。你需要按照 UPC 提供的 run.bat、config.dat 和商户注册信息生成密钥,再完成公钥证书的交换或上传。
目前缺少 run.bat 的具体内容和网关返回的原始错误码,因此无法确定唯一的解决命令。可以按下面的步骤逐项检查,找出问题出现在哪个环节。
先确认网关到底需要什么
重新生成证书前,先向支付网关或插件文档确认以下要求:
- 需要的是商户签名证书、TLS 客户端证书,还是服务器 SSL 证书。
- 插件需要加载哪种文件:
.pem、.crt、.cer、.p12或.pfx。 - 是否还需要私钥文件,例如
.key。 - 证书使用 PEM 还是 DER 编码。
- 私钥是否必须使用密码保护。
- 网关是否要求上传商户公钥证书。
- 网关返回的证书是否也需要安装。
- 测试环境和生产环境是否使用不同的商户号及证书。
- 支持哪些密钥类型、密钥长度、摘要算法和签名算法。
这些要求不能根据 YouTube 教程推断。不同网关即使都使用 OpenSSL,证书交换流程也可能完全不同。
正确的操作顺序
1. 安装与脚本兼容的 OpenSSL
https://www.openssl.org/source/ 主要提供 OpenSSL 源代码,并不是可以直接运行的 Windows 安装程序。请使用支付网关明确支持的 Windows OpenSSL 版本和架构。
安装后,将实际的 bin 目录加入 PATH,例如:
C:\OpenSSL\bin
重新打开命令提示符,再检查系统实际调用的是哪个程序:
where openssl
openssl version -a
如果 where openssl 显示多个路径,run.bat 可能调用了错误的版本。可以暂时使用绝对路径验证:
"C:\OpenSSL\bin\openssl.exe" version -a
一些旧的批处理脚本依赖 OpenSSL 1.x 的配置或命令行为,换用 OpenSSL 3.x 后可能执行失败。不要自行降级或更改算法,先确认 UPC 当前支持的版本。
2. 使用正确的商户资料
完成商户注册并取得 E-shop attributes 后,再生成正式密钥。至少要确认以下事项:
MERCHANT ID已经正式分配;- 没有用申请编号、终端号或其他编号代替 Merchant ID;
- 没有混用测试环境与生产环境的 Merchant ID;
- 复制商户号时没有带入引号、前后空格或换行;
config.dat的编码和格式没有被编辑器破坏。
config.dat 中的名称、组织和地区等信息,通常只用于标识证书,不参与交易签名计算。但文件结构、字段名、分隔符和编码仍然不能随意更改。应在 UPC 提供的原始文件上修改字段值,不要新建空白文件后自行编写。
3. 在脚本所在目录运行 run.bat
假设批处理文件位于:
C:\UPC\batch
可以执行:
cd /d C:\UPC\batch
run.bat MERCHANT_ID
将 MERCHANT_ID 替换成真实商户号,例如:
run.bat 123456789
除非网关文档明确要求,否则不要把示例商户号、尖括号或说明文字一并输入。
如果批处理文件来自邮件附件,执行前应先查看内容,确认它只调用预期的 OpenSSL 程序,并了解它会生成哪些文件。不要从论坛或视频中下载同名脚本,替换网关提供的版本。
执行脚本时,注意是否出现以下信息:
unable to load config info
No such file or directory
unknown option
unsupported algorithm
problems making Certificate Request
unable to load Private Key
即使窗口最后显示文件已生成,也不能证明之前的命令全部执行成功。建议保存完整输出:
run.bat 123456789 > generation.log 2>&1
然后找到 generation.log 中出现的第一个错误。后面的报错往往是由第一个错误连续引发的。
检查生成的文件
脚本不同,生成的文件名也会不同,但通常包括以下一种或多种文件:
- 私钥,例如
merchant.key; - 证书签名请求,例如
merchant.csr; - 公钥证书,例如
merchant.crt或merchant.pem; - PKCS#12 文件,例如
merchant.p12或merchant.pfx。
先通过以下命令确认文件存在且不是空文件:
dir
检查证书
对于 PEM 格式的 X.509 证书:
openssl x509 -in merchant.crt -noout -subject -issuer -serial -dates
openssl x509 -in merchant.crt -noout -text
正常的 PEM 证书应包含类似边界:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
如果文件使用 DER 编码,需要增加 -inform DER:
openssl x509 -inform DER -in merchant.cer -noout -text
如果命令提示:
Could not read certificate
常见原因有:
- 该文件不是 X.509 证书;
- PEM 和 DER 格式用反了;
- 实际上传的是 CSR;
- 文件被编辑器破坏;
- 文件路径或文件名不正确。
检查 CSR
如果脚本生成的是证书签名请求:
openssl req -in merchant.csr -noout -subject -text -verify
CSR 的典型边界是:
-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----
CSR 不是正式证书。如果插件要求 certificate,就不能直接向它提供 .csr 文件,除非 UPC 明确要求先上传 CSR,再由 UPC 签发证书。
检查私钥
openssl pkey -in merchant.key -check -noout
如果私钥设置了密码,OpenSSL 会提示输入。出现问题时,应重点检查:
- 输入的密码是否正确;
- 插件是否支持加密私钥;
- 插件配置的私钥路径是否正确;
- 插件是否支持当前私钥格式;
- 私钥文件内容是否完整。
不要把私钥发送给支付网关,也不要通过邮件、聊天工具或工单上传私钥。通常需要交给网关的是公钥证书,私钥只保存在商户自己的服务器上。
检查证书与私钥是否配对
对于 RSA 密钥,可以分别计算公钥摘要:
openssl x509 -in merchant.crt -pubkey -noout | openssl pkey -pubin -outform DER | openssl dgst -sha256
openssl pkey -in merchant.key -pubout -outform DER | openssl dgst -sha256
两条命令输出的 SHA-256 摘要必须一致。如果不一致,说明插件使用的证书和私钥并非同一对。常见情况是重新生成证书后,只替换了其中一个文件。
如果实际文件名不同,请相应替换命令中的 merchant.crt 和 merchant.key。
检查 PKCS#12/PFX 文件
如果插件要求 .p12 或 .pfx:
openssl pkcs12 -in merchant.p12 -info -noout
如果网关明确要求将现有证书和私钥打包,可以使用:
openssl pkcs12 -export ^
-inkey merchant.key ^
-in merchant.crt ^
-out merchant.p12 ^
-name "merchant"
只有插件文档明确要求 PKCS#12 时,才应执行这一步。不要因为 .p12 看起来像一个包含内容更完整的证书文件,就自行转换格式。
完成证书交换
许多支付网关使用双向证书交换流程:
- 商户生成自己的私钥和公钥证书;
- 商户向网关提交公钥证书;
- 网关将该证书登记到对应的 Merchant ID;
- 网关向商户提供网关证书;
- 商户使用自己的私钥为请求签名;
- 商户使用网关证书验证响应。
如果只在本地生成文件,却没有把正确的公钥证书上传或交给 UPC,网关便无法验证商户签名,通常会返回 certificate invalid、signature invalid 或类似错误。
提交前请确认:
- 上传的是公钥证书,不是私钥;
- 证书登记在同一个 Merchant ID 下;
- 证书上传到了正确的环境;
- 网关已经激活证书,而不只是收到了文件;
- 插件使用的是与本次登记对应的私钥;
- 没有把网关证书误当成商户证书使用。
检查插件配置
证书本身有效,但插件仍然报错时,应重点检查以下配置:
merchant_id
environment
merchant_certificate_path
merchant_private_key_path
private_key_password
gateway_certificate_path
具体字段名以插件文档为准。
开始排查时,路径最好使用绝对路径,并确认运行网站或服务的账户有权限读取文件。例如:
C:\payment\certs\merchant.crt
C:\payment\certs\merchant.key
C:\payment\certs\gateway.crt
Windows 服务、IIS、PHP、Java 或其他运行环境使用的账户,可能与当前登录账户不同。命令行可以读取文件,不代表 Web 服务也有相同权限。
修改配置后,如果插件或应用会缓存证书,还可能需要根据部署方式重新加载配置或重启相应服务。
“证书无效”还可能表示签名无效
有些插件会把所有密码学错误统一显示为 certificate invalid,实际原因可能是报文签名方式不匹配,例如:
- 字段顺序不正确;
- 字段分隔符不正确;
- 字符编码不符合网关要求;
- 对原始字符串进行了额外转义;
- 混用了 Base64 和十六进制编码;
- 使用了错误的摘要算法或签名算法;
- 完成签名后又修改了报文字段;
- 测试环境和生产环境使用了不同的密钥。
因此,需要取得网关返回的原始错误码和服务器日志,不能只根据插件页面上的一句错误提示判断证书已经损坏。
建议的定位顺序
按以下顺序排查通常更快:
- 使用
where openssl和openssl version -a确认实际调用的 OpenSSL 版本。 - 恢复 UPC 原始的
run.bat和config.dat,只修改文档要求修改的内容。 - 使用准确的 Merchant ID 重新执行脚本,并保存完整日志。
- 使用
openssl x509、openssl req或openssl pkcs12判断每个文件的真实类型。 - 验证商户证书与私钥是否配对。
- 确认提交给网关的是公钥证书,而不是 CSR 或私钥。
- 确认证书已经登记到正确的 Merchant ID 和环境。
- 检查插件中的证书路径、私钥路径、密码和文件权限。
- 获取支付网关的原始错误码,区分证书解析失败、证书未登记和签名验证失败。
如果上述检查全部通过,但证书仍被判定无效,应向 UPC 技术支持提供 Merchant ID、测试或生产环境、OpenSSL 版本、证书的 subject/issuer/serial、脚本日志以及网关原始错误码。不要提供私钥、私钥密码,也不要提交包含敏感支付数据的完整请求。
备注:内容仅供参考。
