PAYATHON 2026

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 看起来像一个包含内容更完整的证书文件,就自行转换格式。

完成证书交换

许多支付网关使用双向证书交换流程:

  1. 商户生成自己的私钥和公钥证书;
  2. 商户向网关提交公钥证书;
  3. 网关将该证书登记到对应的 Merchant ID;
  4. 网关向商户提供网关证书;
  5. 商户使用自己的私钥为请求签名;
  6. 商户使用网关证书验证响应。

如果只在本地生成文件,却没有把正确的公钥证书上传或交给 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 和十六进制编码;
  • 使用了错误的摘要算法或签名算法;
  • 完成签名后又修改了报文字段;
  • 测试环境和生产环境使用了不同的密钥。

因此,需要取得网关返回的原始错误码和服务器日志,不能只根据插件页面上的一句错误提示判断证书已经损坏。

建议的定位顺序

按以下顺序排查通常更快:

  1. 使用 where openssl 和 openssl version -a 确认实际调用的 OpenSSL 版本。
  2. 恢复 UPC 原始的 run.bat 和 config.dat,只修改文档要求修改的内容。
  3. 使用准确的 Merchant ID 重新执行脚本,并保存完整日志。
  4. 使用 openssl x509、openssl req 或 openssl pkcs12 判断每个文件的真实类型。
  5. 验证商户证书与私钥是否配对。
  6. 确认提交给网关的是公钥证书,而不是 CSR 或私钥。
  7. 确认证书已经登记到正确的 Merchant ID 和环境。
  8. 检查插件中的证书路径、私钥路径、密码和文件权限。
  9. 获取支付网关的原始错误码,区分证书解析失败、证书未登记和签名验证失败。

如果上述检查全部通过,但证书仍被判定无效,应向 UPC 技术支持提供 Merchant ID、测试或生产环境、OpenSSL 版本、证书的 subject/issuer/serial、脚本日志以及网关原始错误码。不要提供私钥、私钥密码,也不要提交包含敏感支付数据的完整请求。

备注:内容仅供参考。