PAYATHON 2026

alipay.trade.page.pay.return 的 sign 应使用哪张证书验签?

支付阿杰

结论

验证 sign 时,应使用支付宝开放平台提供的支付宝公钥证书,也就是 SDK 中通常配置为 alipay_public_cert_path 的证书。

以下证书或密钥不能用于这一步验签:

  • 应用公钥证书:用于向支付宝证明应用公钥的身份,不能验证支付宝签名。
  • 应用私钥:用于应用发起请求时生成签名。
  • 支付宝根证书:用于校验支付宝证书链,不能直接验证业务请求中的 sign。

return_url 参数中没有 alipay_cert_sn,不影响验签,也不意味着需要改用应用证书。在证书模式下,直接使用本地配置的支付宝公钥证书即可。

为什么没有 alipay_cert_sn

return_url 是支付完成后的页面跳转地址。浏览器跳转时会携带支付结果参数,但不保证其中包含 alipay_cert_sn。

alipay_cert_sn 主要用于标识支付宝使用的公钥证书序列号。当本地存在多张支付宝公钥证书时,可以根据该参数选择对应的证书。不过,它并非所有返回场景都会提供。

因此,不能仅根据 method=alipay.trade.page.pay.return 选择某张特殊证书。这个 method 也不代表另一套独立的验签接口,验签对象仍是支付宝返回的全部待验签参数。

Java 验签示例

使用支付宝 Java SDK 提供的证书验签方法:

import com.alipay.api.internal.util.AlipaySignature;

import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

public boolean verifyReturnSign(HttpServletRequest request) throws Exception {
    Map<String, String> params = new HashMap<>();

    for (Map.Entry<String, String[]> entry
            : request.getParameterMap().entrySet()) {
        String[] values = entry.getValue();
        params.put(
            entry.getKey(),
            values == null ? "" : String.join(",", values)
        );
    }

    String alipayPublicCertPath =
        "/path/to/alipayCertPublicKey_RSA2.crt";

    return AlipaySignature.rsaCertCheckV1(
        params,
        alipayPublicCertPath,
        "UTF-8",
        "RSA2"
    );
}

不同版本 SDK 的方法签名可能略有不同,具体应以项目实际依赖版本提供的 AlipaySignature API 为准。使用证书模式时,应优先调用名称中带 Cert 的验签方法。

如果项目采用普通公钥模式,则应使用支付宝开放平台配置页面提供的“支付宝公钥”,并调用对应的公钥验签方法,例如:

boolean verified = AlipaySignature.rsaCheckV1(
    params,
    alipayPublicKey,
    "UTF-8",
    "RSA2"
);

证书模式和普通公钥模式不能混用。

验签后的处理步骤

验签成功只能证明这些参数由对应的支付宝私钥签发。业务代码还需要检查:

  1. app_id 是否与当前应用的 App ID 一致。
  2. seller_id 是否为预期的支付宝卖家账号。
  3. out_trade_no 是否存在于本地系统,并且属于当前商户。
  4. 订单金额、交易状态等信息是否与本地订单一致。

return_url 是由用户浏览器发起的同步跳转,可能不会发生,也可能被中断或重复访问。因此,不能仅凭这个请求把订单更新为支付成功。

支付结果应以 notify_url 异步通知为主,必要时再调用 alipay.trade.query 查询交易状态。return_url 更适合展示“支付处理中”,或者展示查询后的支付结果。

常见注意事项

不要自行拼接验签字符串

应将原始请求参数交给支付宝 SDK 处理。SDK 会按照支付宝的规则对参数排序,并排除 sign、sign_type 等不参与签名计算的字段。自行排序、编码或拼接,很容易造成验签失败。

避免二次 URL 解码

Servlet 或 Web 框架通常已经解析并解码查询参数。如果业务代码再次执行 URL Decode,参数内容可能改变,进而导致验签失败。构建验签参数时,应尽量直接使用原始请求参数集合。

auth_app_id 不用于选择证书

auth_app_id 与应用授权或调用身份有关,不能据此判断应使用哪张支付宝公钥证书。具体使用哪种验签证书,仍取决于当前应用采用的支付宝接入模式。

证书更新期间的处理

如果本地保存了多个版本的支付宝公钥证书,而返回参数中没有 alipay_cert_sn,就无法仅凭当前请求准确判断签名对应哪张证书。此时应先确认从开放平台下载的证书是否已经更新,并按照当前 SDK 和支付宝开放平台规定的证书更新流程维护证书。

验签失败时不能跳过验签,也不能直接信任浏览器提交的 out_trade_no 或其他支付结果参数。

备注:内容仅供参考。