PAYATHON 2026

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 EVEV 验证加上 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

原则上可以,但要同时满足以下条件:

  1. 证书由银行系统和用户浏览器信任的公开 CA 签发。
  2. 证书中的域名与实际访问域名一致。
  3. 服务器正确发送完整的中间证书链。
  4. 证书没有过期或被吊销。
  5. TLS 配置符合银行的最低安全要求。
  6. 银行没有在合同中指定某个 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 范围控制。

备注:内容仅供参考。