签名验证

1、待签名参数集合

不论支付宝是POST传输还是GET传输,绝大多数接口除sign及sign_type以外,获得的参数集合皆是要参与签名的参数。具体返回参数请以接口技术文档说明及实际返回的信息为准。以即时到账的异步通知内容为例:

http://商户自定义地址/notify_url.php?trade_no=2014040311001004370000361525&out_trade_no=3618810634349901&subject=测试&body=Hello&price=10.00&quantity=1&total_fee=10.00&trade_status=TRADE_FINISHED&seller_email=test@test.com&seller_id=2088002007018916&buyer_id=2088002007013600&buyer_email=13788888888&gmt_create=2014-04-03 20:49:31&is_total_fee_adjust=N&gmt_payment=2014-04-03 20:49:50&use_coupon=N&notify_time=2014-04-03 20:49:52&notify_type=trade_status_sync&notify_id=70fec0c2730b27528665af4517c27b95&sign_type=DSA&sign=_p_w_l_h_j0b_gd_aejia7n_ko4_m%2Fu_w_jd3_nx_s_k_mxus9_hoxg_y_r_lunli_pmma29_t_q%3D%3D&extra_common_param=你好,这是测试商户的广告。

一般情况下,支付宝通知返回的参数都是有带值的,空值的参数是不会存在和出现的。

2、组装

支付宝大部分接口的通知返回部分对“待签名参数集合”也需要排序、去除sign及sign_type、拼接等,逻辑处理与请求阶段一样,最后得到一串待签名字符串。建议以接口技术文档说明为准。以即时到账的异步通知内容为例:

去除sign、sign_type:

Map<String, String> sParaTemp = new HashMap<String, String>(); 
sParaTemp.put("trade_no", "2014040311001004370000361525"); 
sParaTemp.put("out_trade_no", "3618810634349901"); 
sParaTemp.put("subject", "测试"); 
sParaTemp.put("body", "Hello"); 
sParaTemp.put("price", "10.00"); 
sParaTemp.put("quantity", "1"); 
sParaTemp.put("total_fee", "10.00"); 
sParaTemp.put("trade_status", "TRADE_FINISHED");
sParaTemp.put("seller_email", "test@test.com");
sParaTemp.put("seller_id", "2088002007018916"); 
sParaTemp.put("buyer_id", "2088002007013600");
sParaTemp.put("buyer_email", "13700000000");
sParaTemp.put("gmt_create", "2014-04-03 20:49:31");
sParaTemp.put("is_total_fee_adjust", "N");
sParaTemp.put("gmt_payment", "2014-04-03 20:49:50");
sParaTemp.put("use_coupon", "N"); 
sParaTemp.put("notify_time", "2014-04-03 20:49:52"); 
sParaTemp.put("notify_type", "trade_status_sync"); 
sParaTemp.put("notify_id", "70fec0c2730b27528665af4517c27b95"); 
sParaTemp.put("extra_common_param", "你好,这是测试商户的广告。");

排序:

Map<String, String> sParaTemp = new HashMap<String, String>(); 
sParaTemp.put("body", "Hello"); 
sParaTemp.put("buyer_email", "13700000000");
sParaTemp.put("buyer_id", "2088002007013600");
sParaTemp.put("extra_common_param", "你好,这是测试商户的广告。"); 
sParaTemp.put("gmt_create", "2014-04-03 20:49:31");
sParaTemp.put("gmt_payment", "2014-04-03 20:49:50");
sParaTemp.put("is_total_fee_adjust", "N");
sParaTemp.put("notify_id", "70fec0c2730b27528665af4517c27b95");
sParaTemp.put("notify_time", "2014-04-03 20:49:52"); 
sParaTemp.put("notify_type", "trade_status_sync"); 
sParaTemp.put("out_trade_no", "3618810634349901"); 
sParaTemp.put("price", "10.00"); 
sParaTemp.put("quantity", "1"); 
sParaTemp.put("seller_email", "test@test.com");
sParaTemp.put("seller_id", "2088002007018916");
sParaTemp.put("subject", "测试"); 
sParaTemp.put("total_fee", "10.00");
sParaTemp.put("trade_no", "2014040311001004370000361525"); 
sParaTemp.put("trade_status", "TRADE_FINISHED");
sParaTemp.put("use_coupon", "N");

拼接:

body=Hello&buyer_email=13788888888&buyer_id=2088002007013600&extra_common_param=你好,这是测试商户的广告。&gmt_create=2014-04-03 20:49:31&gmt_payment=2014-04-03 20:49:50&is_total_fee_adjust=N&notify_id=70fec0c2730b27528665af4517c27b95&notify_time=2014-04-03 20:49:52&notify_type=trade_status_sync&out_trade_no=3618810634349901&price=10.00&quantity=1&seller_email=test@test.com&seller_id=2088002007018916&subject=测试&total_fee=10.00&trade_no=2014040311001004370000361525&trade_status=TRADE_FINISHED&use_coupon=N

3、调用签名验证函数

1)MD5签名验证

  • 密钥查看:
    查看MD5(Key)
  • 密钥用法:
    把MD5密钥(Key)拼接在待验证签名的字符串尾部、从支付宝返回时得到的参数sign的值。
  • 签名验证函数
    调用md5加密函数,对已经与MD5密钥拼接好的新字符串做加密运算得到加密结果mysign,与从支付宝返回时得到的参数sign做”相等“判断,如果这两个数据是一致的,则验证通过。

2)RSA或DSA签名

  • 密钥生成:
    请查看PID和密钥管理中相应的内容
  • 密钥用法:
    准备好支付宝公钥、待验证签名的字符串、从支付宝返回时得到的参数sign的值。
  • 签名验证函数
    使用各自语言对应的SHA1WithRSA签名验证函数,传入待验签字段、支付宝公钥、参数sign对应的值(该参数为支付宝返回)进行验签,根据返回结果判定是否验签通过。
onlineServer