SSL Certification 与 Online Payment Gateway 选型问题
结论
一般来说,接入 Payment Gateway 使用基础的公开可信 SSL/TLS 证书就够了。银行使用哪个证书品牌,并不意味着商户也要购买同品牌的高价证书。
需要确认的是银行的正式技术规范,而不是工作人员的口头建议:
- 是否接受所有主流公开 CA 签发的证书;
- 要求 DV、OV 还是 EV;
- 是否指定证书品牌或根证书;
- 对 TLS 版本和加密套件有什么要求;
- 是否需要双向 TLS(mTLS)或客户端证书;
- 支付回调地址是否必须使用 HTTPS;
- 是否禁止通配符证书,或要求使用固定域名。
如果银行只要求网站提供一个受浏览器和服务器信任的 HTTPS 地址,那么 GoDaddy、DigiCert、Sectigo、GlobalSign、Let’s Encrypt 等公开可信 CA 签发的证书通常都能使用。最终应以银行 Payment Gateway 的正式接入文档和测试环境的验证结果为准。
这些证书有什么区别
题目中的 Verisign 产品名称是较早期的商业命名。后来证书市场和品牌归属发生过变化,现在选型时更应该比较证书的验证等级、兼容性和配套服务,不必纠结旧产品名称。
大致可以这样理解:
| 类型 | 主要特点 | 对支付功能的影响 |
|---|---|---|
| Secure Site | 基础服务器证书 | 可以建立 HTTPS,通常足以满足普通支付接入 |
| Secure Site Pro | 增加厂商提供的兼容性、保障额度或安全服务 | 通常不会改变 Payment Gateway API 的功能 |
| Secure Site with EV | 对企业主体进行更严格的扩展验证 | 提高身份审核等级,但不会让加密算法天然更强 |
| Secure Site Pro with EV | EV 验证加上 Pro 服务 | 主要区别仍在审核、支持和附加服务 |
“Pro”具体包含哪些内容,会随厂商和销售时期而变化,可能包括更高的赔付保障、安全扫描、技术支持或针对早期浏览器的兼容功能。购买前应查看当前的产品说明,不能只凭名称判断。
证书价格更高,不代表 HTTPS 数据会获得更高级别的基本加密。实际连接是否安全,主要取决于:
- Web 服务器启用的 TLS 版本;
- 加密套件配置;
- 私钥长度和算法;
- 证书链是否完整;
- 私钥是否得到妥善保护;
- 应用程序是否正确验证对方证书;
- 是否及时修补服务器和程序漏洞。
DV、OV 和 EV 应该怎么选
现在更常用的分类是 DV、OV 和 EV。
DV(Domain Validation)
CA 只验证申请者是否控制该域名。
DV 签发快、成本低,也方便自动续期。在使用相同算法配置的情况下,它提供的传输加密与 OV、EV 证书没有本质区别。
如果活动网站规模不大,银行不要求主体认证,而且支付页面主要由银行托管,DV 通常就够用了。
OV(Organization Validation)
除域名控制权外,CA 还会审核组织的注册信息。
如果网站代表公司、学校、协会或正式活动组织,OV 可以提供更明确的组织身份信息。有些银行或企业采购制度会要求使用 OV,但这属于合规和身份审核要求,并非 Payment Gateway 在技术上的必然要求。
EV(Extended Validation)
EV 的组织身份审核更严格,签发时间通常更长,成本也更高。
现代浏览器通常不会再像早期那样,用醒目的绿色地址栏展示 EV 证书。除非银行、保险、审计制度或内部安全政策明确要求,否则活动报名网站通常没必要只为了”看起来更安全”而购买 EV。
是否可以使用其他 CA
原则上可以,但要同时满足以下条件:
- 证书由银行系统和用户浏览器信任的公开 CA 签发。
- 证书中的域名与实际访问域名一致。
- 服务器正确发送完整的中间证书链。
- 证书没有过期或被吊销。
- TLS 配置符合银行的最低安全要求。
- 银行没有在合同中指定某个 CA 或证书等级。
银行网站使用某个证书品牌,不代表接入该银行网关的商户也必须使用相同品牌。TLS 通信依赖证书信任链和协议兼容性,并不要求通信双方向同一家 CA 购买证书。
但如果银行使用的是旧系统,只预装了少量根证书,或者采用了证书指纹、颁发者白名单等非通用限制,其他 CA 签发的证书确实可能无法通过。遇到这种情况,应让银行技术团队书面确认,或直接在测试环境中验证。
可以向银行提出以下问题:
商户 HTTPS 回调地址是否可以使用任意公开可信 CA 签发的 DV/OV 证书?是否存在指定 CA、根证书、证书算法、TLS 版本、通配符证书或 mTLS 客户端证书要求?
先确认支付接入模式
证书怎么选,也取决于支付流程。
跳转到银行支付页面
用户在活动网站填写报名信息,然后跳转到银行页面输入卡号并付款。付款完成后,银行将用户跳回活动网站,或者调用网站的服务器端回调地址。
在这种模式下,活动网站仍应全站启用 HTTPS,但卡片数据通常不会经过活动网站。基础的公开可信证书一般就能满足要求。
网站直接收集银行卡信息
如果卡号、有效期、验证码等信息直接提交到活动网站服务器,需要考虑的就不只是证书了。网站还可能进入更严格的 PCI DSS 合规范围,需要处理:
- 卡片数据的存储和传输;
- 日志脱敏;
- 访问控制;
- 漏洞扫描;
- 密钥管理;
- 网络隔离;
- 安全审计。
不要把银行卡号、CVV 或完整支付报文写入 MySQL、应用日志、错误日志或分析系统。如果可以使用银行托管支付页或令牌化组件,应优先选择这些方案。
推荐的实施步骤
1. 确定正式域名
例如:
https://event.example.com/
https://event.example.com/payment/callback
证书必须覆盖实际使用的域名。example.com、www.example.com 和 event.example.com 是三个不同的名称,除非证书的 SAN 字段明确包含它们。
2. 选择证书
如果银行没有额外要求,可以按以下顺序选择:
- 先考虑公开可信的 DV 证书;
- 组织制度要求展示主体身份时,选择 OV;
- 只有银行或合规规则明确要求时,才选择 EV。
即使活动只持续几个月,也要考虑活动结束后是否还要处理支付回调、退款、对账和用户查询,不能在活动结束当天就停止续期。
3. 安装完整证书链
以 Nginx 为例:
server {
listen 443 ssl http2;
server_name event.example.com;
ssl_certificate /etc/ssl/event/fullchain.pem;
ssl_certificate_key /etc/ssl/event/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/event/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
}
证书路径和 PHP-FPM socket 名称要根据实际服务器环境调整。私钥文件必须限制访问权限,也不能提交到 Git 仓库。
还要把 HTTP 请求重定向到 HTTPS:
server {
listen 80;
server_name event.example.com;
return 301 https://$host$request_uri;
}
4. 正确调用银行 HTTPS API
使用 PHP cURL 调用银行接口时,必须保持证书验证开启:
<?php
$payload = [
'order_id' => 'EVT-2026-000123',
'amount' => '199.00',
'currency' => 'CNY',
];
$ch = curl_init('https://gateway.bank.example/api/payment');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException('Payment gateway request failed: ' . curl_error($ch));
}
$statusCode = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($statusCode < 200 || $statusCode >= 300) {
throw new RuntimeException('Payment gateway returned HTTP ' . $statusCode);
}
不要用下面的配置绕过证书错误:
CURLOPT_SSL_VERIFYPEER => false
关闭验证会让连接更容易受到中间人攻击,还可能掩盖服务器证书链的配置错误。
5. 安全处理支付回调
HTTPS 只能保护数据传输,不能证明某条回调一定来自银行的业务系统。处理回调时,还必须验证银行提供的签名、MAC、证书签名或其他认证字段。
示意代码如下:
<?php
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_PAYMENT_SIGNATURE'] ?? '';
if (!verifyBankSignature($rawBody, $signature)) {
http_response_code(400);
exit('invalid signature');
}
$data = json_decode($rawBody, true, flags: JSON_THROW_ON_ERROR);
$orderId = $data['order_id'] ?? '';
$transactionId = $data['transaction_id'] ?? '';
$status = $data['status'] ?? '';
if ($status === 'PAID') {
// 使用 transaction_id 或银行流水号实施幂等处理。
// 再核对订单号、金额、币种和商户号,然后更新订单状态。
}
http_response_code(200);
echo 'success';
verifyBankSignature()使用的算法、字段排序、字符编码和公钥来源,都必须严格按照银行文档实现,不能自行设计。
容易忽略的事项
- 不要只保护支付页面,登录、报名、订单查询和回调接口也要使用 HTTPS。
- 不要根据浏览器跳转参数直接把订单标记为已付款,应以通过验签的服务器端通知或主动查询结果为准。
- 回调处理必须支持重复通知,避免重复登记、重复开具发票或重复发放权益。
- 核对回调中的商户号、订单号、金额、币种和支付状态。
- 不要把私钥、API 密钥和支付签名密钥存入源码仓库。
- 测试环境和生产环境可能使用不同的域名、证书及银行公钥。
- 为证书设置到期监控和自动续期,并确认续期后中间证书链仍然完整。
- 不要只依赖页面上的安全标识图片。用户依赖的是能够通过浏览器验证的 HTTPS 连接。
- 如果银行要求上传”SSL certificate”,先确认对方需要的是公开证书文件,还是 mTLS 客户端证书。服务器证书的私钥绝不能交给银行。
如果银行文档没有指定证书品牌、OV/EV 或 mTLS,选择受广泛信任的基础 DV 证书通常就够了。相比购买昂贵的品牌证书,更应该把预算用于完善 TLS 配置、支付报文验签、回调幂等、密钥保护和 PCI DSS 范围控制。
备注:内容仅供参考。
