简介:本文详细解析支付宝 v3 接口验签机制的实现原理,涵盖 RSA2 签名算法、验签步骤、代码示例及常见问题处理,帮助开发者高效完成接口安全验证。
在开放平台场景中,验签是确保请求来源合法性、数据完整性的核心机制。支付宝 v3 接口采用非对称加密(RSA2)签名方案,通过私钥签名、公钥验签的方式,防止请求被篡改或伪造。其重要性体现在:
典型业务场景包括支付回调通知、退款请求等高敏感操作。以支付结果通知为例,若未验签直接处理,可能导致资金风险。
支付宝 v3 采用 SHA256WithRSA 签名算法,流程如下:
签名生成:
参数1=值1&参数2=值2...)验签过程:
关键点:
bouncycastle 库处理加密cryptography 库待签名字符串构造规则:
sign)和空值参数key1=value1&key2=value2... 格式%20)示例:
原始参数:
{"app_id": "2021001123","method": "alipay.trade.query","charset": "utf-8","sign_type": "RSA2","timestamp": "2023-01-01 12:00:00","biz_content": "{\"out_trade_no\":\"123456\"}"}
处理后待签名字符串:
app_id=2021001123&biz_content={"out_trade_no":"123456"}&charset=utf-8&method=alipay.trade.query×tamp=2023-01-01 12:00:00
import java.security.*;import java.security.spec.X509EncodedKeySpec;import java.util.*;import org.apache.commons.codec.binary.Base64;public class AlipayVerifier {// 支付宝公钥(PEM格式需处理)private static final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...";/*** 验证签名* @param params 请求参数Map(包含sign)* @return 验证结果*/public static boolean verify(Map<String, String> params) {try {// 1. 获取签名String sign = params.get("sign");if (sign == null) return false;// 2. 构造待签名字符串String content = buildSignContent(params);// 3. 加载支付宝公钥PublicKey publicKey = loadPublicKey(ALIPAY_PUBLIC_KEY);// 4. 验证签名Signature signature = Signature.getInstance("SHA256withRSA");signature.initVerify(publicKey);signature.update(content.getBytes("UTF-8"));byte[] signBytes = Base64.decodeBase64(sign);return signature.verify(signBytes);} catch (Exception e) {e.printStackTrace();return false;}}private static String buildSignContent(Map<String, String> params) {// 排除sign和空值参数params.remove("sign");List<String> keys = new ArrayList<>(params.keySet());Collections.sort(keys);StringBuilder content = new StringBuilder();for (String key : keys) {String value = params.get(key);if (value != null && !value.isEmpty()) {content.append(key).append("=").append(value).append("&");}}return content.length() > 0 ? content.substring(0, content.length() - 1) : "";}private static PublicKey loadPublicKey(String pubKey) throws Exception {// 处理PEM格式公钥(去除头尾和换行)String formattedKey = pubKey.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replaceAll("\\s", "");byte[] keyBytes = Base64.decodeBase64(formattedKey);X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePublic(spec);}}
问题1:验签失败排查清单
sign 参数问题2:公钥格式转换
支付宝提供两种公钥形式:
问题3:异步通知验签
对于支付结果通知,需特别注意:
success 前需确保验签通过通过系统化的验签实现,可有效保障支付宝 v3 接口的安全性。实际开发中,建议参考支付宝官方文档的《签名验签教程》,并定期关注接口规范更新。对于复杂业务场景,可考虑使用支付宝提供的 SDK(如 Java SDK 已内置验签功能),但需注意 SDK 版本与接口版本的兼容性。