免密支付

签名和验签

1. 请求返回码

SUC0000表示成功,其他表示错误,具体错误码见详细API定义。

2. 使用支付秘钥做签名或验签

签名:

商户需要使用支付密钥对请求报文进行签名。

验签:

银行同步响应报文如果包含了签名数据,商户需要使用支付密钥进行验签。
验签的过程与签名过程基本相同,只是验签过程需要商户将计算出的签名数据和银行响应报文中的签名数据进行对比,以确认验签成功。

签名算法说明:

首先组成待签名字符串。待签名字符串组成规则为:对待验签的所有请求参数按从az的字典顺序排列,如果首字母相同,按第二个字母排列,以此类推。排序完成后按将所有键值对以&符号拼接:

param1=value1&m2=value2&……

将商户签名密钥增加“&”附加到待签名字符串后,按指定签名算法进行运算。假设待签名字符串为strToSign,商户密钥为merkey,算法为sha256,对strToSign&merkey进行sha256签名运算获得签名结果byte数组,将byte数组转换为16进制即为最终的签名结果。

注意:
1、所有reqData(或rspData)中参数,即便其值为空,也加入签名字符串
2、注意排序时按字典顺序排序,字母顺序与大小写无关。例如:sDatesdateTime的顺序是
sDate=XXX&sdateTime=XXXsdatesDateTime的顺序是sdate=XXX&sDateTime=XXX
3、出现特殊字符时,按照ASCII表中特殊字符和小写字母的顺序,进行排序判断。例如:bankSerialNobank_msg的顺序是bank_msg=XXX&bankSerialNo=XXX
4、签名时,按指定的字符集将字符串转换为字节流
5、根据HTTP协议要求,如果请求参数值中有特殊字符和汉字,如&、@等,需进行URLEncoding处理。待签名数据为原生值而非encoding后的值。如:参数值为email=test@msn.com,则签名值是email=test@msn.com,而非email=test%40msn.com

样例报文:

{    
     "version":"1.0",    
     "charset":"UTF-8",    
     "sign":"ABCDAEEDDDFA",    
     "signType":"SHA-256",    
     "reqData":{        
         "param1":"value1",        
         "param2":"value2",        
         "dateTime":"20160622182921"        
         }
}

待签名字符串(不包含支付密钥)为:

dateTime=20160622182921&param1=value1&param2=value2

注意:为了支持参数扩展,商户必须使用算法对待签名参数进行排序,不能使用程序写死的方法硬拼接参数顺序。

3. 使用招行公钥验签

银行主动发送的通知报文,会使用招行私钥进行签名,商户接受到通知报文后,需要使用招行公钥验签。(如“成功签约结果通知”,“成功支付结果通知”等)

验签说明:

首先组成待签名字符串。待签名字符串组成规则为:对noticeData所有参数名转换为小写后按从az的字典顺序排列,如果首字母相同,按第二个字母排列,以此类推。排序完成后按将所有键值对以&符号拼接:

param1=value1&m2=value2&……

假设待签名字符串为strToSign,招行通知公钥为publicKey, 签名内容为strSign,算法为标准的RSA算法,加密算法为SHA1WithRSA,对strToSign进行签名校验。
招行通知公钥可以通过调用“查询招行公钥”接口获取,详见查询招行公钥API介绍。

注意:

  1. 所有noticeData中请求参数,即便其值为空,也加入签名字符串

  2. 验签字符串不需要拼接招行公钥。

  3. 注意排序时按字典顺序排序,字母顺序与大小写无关。例如:sDatesdateTime的顺序是sDate=XXX&sdateTime=XXXsdatesDateTime的顺序是sdate=XXX&sDateTime=XXX

  4. 出现特殊字符时,按照ASCII表中特殊字符和小写字母的顺序,进行排序判断。例如:bankSerialNobank_msg的顺序是bank_msg=XXX&bankSerialNo=XXX

  5. 签名时,按指定的字符集将字符串转换为字节流。

  6. 根据HTTP协议要求,如果请求参数值中有特殊字符,如&@等,需进行URLEncoding处理。待签名数据为原生值而非encoding后的值。如:参数值为email=test@msn.com,则签名值是email=test@msn.com,而非email=test%40msn.com

样例报文:

{    
    "version":"1.0",    
    "charset":"UTF-8",    
    "sign":"签名结果(strSign)",    
    "signType":"RSA",        
        "noticeData":{        
        "dateTime":"20160622182921",        
        "noticeUrl":"https://... ",        
        "httpMethod":"POST",        
        "branchNo":"0755",        
        "merchantNo":"002346",        
        "noticeType":"BKPAY",        
        "noticeSerialNo":"201606238888888",        
        "param1":"aaa",        
        "param2":"bbb"        
        }
}

待验证签名字符串strToSign为:

branchNo=0755&dateTime=20160622182921&httpMethod=POST&merchantNo=002346&noticeSerialNo=201606238888888&noticeType=BKPAY&noticeUrl=https://...&param1=aaa&param2=bbb

4. FAQ

Q1、为什么我在做测试时,招行系统显示 “签名验证失败”?
验签失败,sign内容不正确。

可能原因:
1、 签名时使用的商户密钥与设置的不一样,请确认配置的密钥与环境是否匹配。
2、 生成签名数据时填写的参数与支付接口中填写的相应参数值不一样。
3、 生成签名数据的参数排序顺序不正确,请仔细核对文档中的排序顺序
4、 特殊字符是否加密正确,例如服务器端&字符是否被转换为&,导致签名错误
5、 参数前后是否包含空格,请不要包括空格。
6、 参数首字母相同时,请注意包含特殊字符参数的排序是否正确