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"
);
证书模式和普通公钥模式不能混用。
验签后的处理步骤
验签成功只能证明这些参数由对应的支付宝私钥签发。业务代码还需要检查:
app_id是否与当前应用的 App ID 一致。seller_id是否为预期的支付宝卖家账号。out_trade_no是否存在于本地系统,并且属于当前商户。- 订单金额、交易状态等信息是否与本地订单一致。
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 或其他支付结果参数。
备注:内容仅供参考。
