PAYATHON 2026

H5支付宝手机网站支付如何更换商户号及生成.pem文件

支付老李

结论

只替换 APPID 通常无法完成商户切换。还要更换新应用对应的商户私钥、支付宝公钥或应用证书,并确认新商户下的应用已经开通”手机网站支付”能力。

ali_private_key.pem 不是从支付宝下载的,而是由商户在本地生成并妥善保管。由该私钥导出的应用公钥需要配置到支付宝开放平台。如果项目采用证书模式,还要为新应用重新申请应用公钥证书,同时替换支付宝公钥证书和支付宝根证书。

.pem 文件名并非支付宝的统一规范,不能只凭文件名判断用途。应先检查支付配置和 SDK 初始化代码,确认项目使用的是”普通公钥模式”还是”证书模式”。

先确认当前使用的密钥模式

先找到支付宝客户端的初始化位置。

如果配置中包含以下字段,通常使用的是普通公钥模式:

app_id
merchant_private_key
alipay_public_key
sign_type
gateway_url

如果包含以下字段,通常使用的是证书模式:

app_id
merchant_private_key
app_cert_path
alipay_cert_path
alipay_root_cert_path

部分旧项目的字段或文件名称可能不同,例如:

ali_private_key.pem
ali_public_key.pem
alipay_public_key.pem
cacert.pem

文件可以自行命名。判断其用途,要看代码将文件内容传给了哪个配置项,不要看到四个 .pem 文件就直接逐一覆盖。

普通公钥模式如何更换

普通公钥模式涉及以下密钥:

  • 商户应用私钥:保存在服务器上,用于为支付请求签名。
  • 商户应用公钥:由私钥导出,配置到支付宝开放平台。
  • 支付宝公钥:从支付宝开放平台获取,保存在服务器上,用于验证支付宝响应和异步通知的签名。

切换步骤如下:

  1. 登录新商户对应的支付宝开放平台账号。
  2. 确认目标应用的 APPID,并检查该应用是否已开通手机网站支付能力。
  3. 在安全的本地环境中生成新的 RSA2 密钥对。
  4. 将生成的应用公钥配置到新应用的接口加签方式中。
  5. 从开放平台取得与该应用匹配的支付宝公钥。
  6. 替换服务器上的商户私钥和支付宝公钥。
  7. 修改 APPID,以及项目中可能存在的 seller_id、PID 等商户标识。
  8. 使用新商户测试下单、同步跳转和异步通知验签。

生成 ali_private_key.pem

建议使用支付宝开放平台提供的密钥工具生成 RSA2 密钥。工具会生成应用私钥和应用公钥,其中应用私钥用于服务器签名,可以保存为 ali_private_key.pem,但文件名并非强制要求。

也可以使用 OpenSSL。以下命令会生成一把 2048 位 RSA 私钥:

openssl genrsa -out ali_private_key.pem 2048

导出对应的公钥:

openssl rsa \
  -in ali_private_key.pem \
  -pubout \
  -out ali_public_key.pem

三个文件或密钥的用途如下:

ali_private_key.pem  -> 服务器保存,用于请求签名
ali_public_key.pem   -> 配置到支付宝开放平台
支付宝公钥            -> 从开放平台获取,用于验签

上传到支付宝开放平台的是应用公钥,不是私钥。ali_private_key.pem 不得上传,也不能提交到公开代码仓库或发送给无关人员。

PKCS#1 与 PKCS#8 格式

不同语言、不同版本的支付宝 SDK 对私钥格式的要求可能不同。除了 .pem 后缀,还要检查文件头和 SDK 的配置说明。

PKCS#1 私钥通常以以下内容开头:

-----BEGIN RSA PRIVATE KEY-----

PKCS#8 私钥通常以以下内容开头:

-----BEGIN PRIVATE KEY-----

如果 SDK 要求使用 PKCS#8,可以执行以下转换:

openssl pkcs8 \
  -topk8 \
  -inform PEM \
  -in ali_private_key.pem \
  -outform PEM \
  -nocrypt \
  -out ali_private_key_pkcs8.pem

不要通过手工删除文件头、文件尾或换行来”转换格式”。有些 SDK 配置项要求填写不含 PEM 头尾的纯 Base64 内容,有些则支持完整的 PEM 文件,具体应以项目所用 SDK 的参数要求为准。

证书模式如何处理

如果代码中配置了应用证书、支付宝公钥证书和支付宝根证书,项目很可能使用的是证书模式。这种情况下,只生成普通 RSA 密钥对还不够。

证书模式一般需要:

  • 商户应用私钥。
  • 应用公钥证书。
  • 支付宝公钥证书。
  • 支付宝根证书。

典型配置如下:

<?php

$aop = new AopCertClient();

$aop->appId = '新应用APPID';
$aop->rsaPrivateKey = file_get_contents(
    __DIR__ . '/cert/ali_private_key.pem'
);

$appCertPath = __DIR__ . '/cert/appCertPublicKey_新APPID.crt';
$alipayCertPath = __DIR__ . '/cert/alipayCertPublicKey_RSA2.crt';
$rootCertPath = __DIR__ . '/cert/alipayRootCert.crt';

$aop->appCertSN = $aop->getCertSN($appCertPath);
$aop->alipayrsaPublicKey = $aop->getPublicKey($alipayCertPath);
$aop->alipayRootCertSN = $aop->getRootCertSN($rootCertPath);

$aop->signType = 'RSA2';

具体的类名和属性取决于项目使用的 SDK 版本,并非所有 PHP SDK 都采用完全相同的接口。

证书模式通常按以下步骤处理:

  1. 为新应用生成新的应用密钥。
  2. 按照支付宝开放平台的证书申请流程提交应用公钥或 CSR。
  3. 下载新应用的应用公钥证书。
  4. 下载对应的支付宝公钥证书和支付宝根证书。
  5. 替换项目中的证书文件。
  6. 重新计算证书序列号,或交由 SDK 自动计算。
  7. 使用新应用进行联调。

证书文件通常使用 .crt 后缀,但旧项目也可能把证书内容保存为 .pem 文件,所以仍要根据文件内容和代码用途判断。

普通公钥模式配置示例

以下只是结构示例,字段名称要与当前项目使用的 SDK 对应:

<?php

$config = [
    'app_id' => '新应用APPID',
    'sign_type' => 'RSA2',
    'charset' => 'UTF-8',
    'gateway_url' => 'https://openapi.alipay.com/gateway.do',

    // 新商户应用私钥
    'merchant_private_key' => file_get_contents(
        __DIR__ . '/cert/ali_private_key.pem'
    ),

    // 新应用安全配置页面显示的支付宝公钥
    'alipay_public_key' => file_get_contents(
        __DIR__ . '/cert/alipay_public_key.pem'
    ),

    'return_url' => 'https://example.com/alipay/return',
    'notify_url' => 'https://example.com/alipay/notify',
];

发起手机网站支付时,通常仍使用以下接口:

alipay.trade.wap.pay

如果旧代码中硬编码了商户标识,也要一并检查:

seller_id
pid
partner
app_id

较新的开放平台接口主要通过 APPID 标识应用,但旧接口或旧业务代码中可能仍保留 partner、PID 或 seller_id。这些值不能继续指向原商户。

异步通知验签也必须更换

商户切换后,支付通知验签很容易被遗漏。发起支付时已经使用新私钥,并不表示回调验签配置也已更新。

普通公钥模式应使用新应用对应的支付宝公钥验签:

<?php

$verified = $aop->rsaCheckV1(
    $_POST,
    $newAlipayPublicKey,
    'RSA2'
);

if (!$verified) {
    http_response_code(400);
    exit('failure');
}

验签通过后,仍要核对以下字段:

app_id
out_trade_no
trade_no
total_amount
seller_id
trade_status

尤其要确认通知中的 app_id、金额和订单号与本地订单一致,不能只根据 trade_status 更新订单。

还需要检查的配置

除密钥外,至少还要检查以下事项:

  • 新商户应用是否已经签约并开通手机网站支付。
  • 应用是否处于可用状态,正式环境不能误用沙箱 APPID。
  • gateway_url 是否与正式环境或沙箱环境匹配。
  • sign_type 是否统一为 RSA2。
  • notify_url 和 return_url 是否仍然有效。
  • 域名、应用授权及相关产品配置是否需要在新应用下重新设置。
  • 旧代码是否缓存了 APPID、私钥、支付宝公钥或证书序列号。
  • Web 服务器或 PHP-FPM 等运行账户是否有权读取新密钥文件。
  • 新私钥文件是否设置了严格的访问权限。
  • 数据库或环境变量中是否仍保留旧商户的 PID、seller_id、授权令牌等信息。
  • 如果存在服务商代商户调用,还要检查 app_auth_token,不要混淆普通商户直连与第三方应用授权。

不建议直接沿用旧 .pem 文件

旧支付宝公钥通常对应旧应用的安全配置,继续使用往往会导致验签失败。旧商户私钥即使仍能读取,只要它与新应用中配置的应用公钥不匹配,请求签名就会失败。

只有明确掌握旧密钥的来源,确认新应用已经配置同一把应用公钥,并完成安全评估后,才可能复用原密钥。实际迁移时,为新应用生成独立密钥通常更稳妥。切换完成后,再安全归档或撤销旧密钥。

如果暂时无法确定四个 .pem 文件的用途,应从 SDK 初始化代码反向查找每个文件对应的配置项。只凭文件名替换风险较大。配置完成后,至少要验证支付下单、支付页面跳转、同步返回、异步通知验签、订单状态更新和退款等完整链路。

备注:内容仅供参考。