YSDK支付接口签名说明

目录

1.签名生成总体说明

本文档仅适用于YSDK 支付相关接口的签名生成,由于是通用说明,本文中仅以/mpay/get_balance_m的签名生成作为示例。
签名值sig是将请求源串以及密钥根据一定签名方法生成的签名值,用来提高传输过程参数的防篡改性。
签名值的生成共有3个步骤:构造源串,构造密钥,生成签名值。详见下面的描述。

Step 1. 构造源串

源串是由3部分内容用“&”拼接起来的: HTTP请求方式 & urlencode(uri) & urlencode(a=x&b=y&...)
特别注意构造签名里URI需要在实际的URI前加入/v3/r/,比如请求/mpay/get_balance_m,则签名时的uri路径为/v3/r/mpay/get_balance_m

源串构造步骤

第1步:将请求的URI路径进行URL编码(URI不含host,URI示例:/v3/r/mpay/get_balance_m,)。
请开发者关注:URL编码注意事项,否则容易导致后面签名不能通过验证

第2步: 将除“sig”外的所有参数按key进行字典升序排列。
注:除非OpenAPI文档中特别标注了某参数不参与签名,否则除sig外的所有参数都要参与签名。

第3步:将第2步中排序后的参数(key=value)用&拼接起来,并进行URL编码。
请开发者关注:URL编码注意事项,否则容易导致后面签名不能通过验证

第4步:将HTTP请求方式(GET或者POST)以及第1步和第3步中的字符串用&拼接起来。
注:Java_SDK_V3.0.6仅支持POST方式,如果用GET可能导致一直计算sig不正确。

源串构造示例如下

(由于是通用说明,这里以/mpay/get_balance_m作为示例,且示例中的请求串不可直接复制访问)

1. 原始请求信息:
appkey:56abfbcd12fe46f5ad85ad9f12345678
HTTP请求方式:GET
请求的URI路径(不含HOST,注意加入/v3/r/):/v3/r/mpay/get_balance_m
请求参数:appid=15499&format=json&openid=00000000000000000000000014BDF6E4&openkey=AB43B
F3DC5C3C79D358CC5318E41CF59&pf=myapp_m_qq-00000000-android-00000000-ysdk&pfkey=CA641BC173479
B8C0B35BC84873B3DB9&ts=1340880299&userip=112.90.139.30&zoneid=1

2. 下面开始构造源串: 
第1步:将请求的URI路径进行URL编码,得到: %2Fv3%2Fr%2Fmpay%2Fget_balance_m 

第2步:将除“sig”外的所有参数按key进行字典升序排列,排列结果为:appid,format,openid,openkey,pf,pfkey,ts,userip,zoneid 

第3步:将第2步中排序后的参数(key=value)用&拼接起来:
appid=15499&format=json&openid=00000000000000000000000014BDF6E4&openkey=AB43BF3DC5C3C79D358CC5318E41
CF59&pf=myapp_m_qq-00000000-android-00000000-ysdk&pfkey=CA641BC173479B8C0B35BC84873B3DB9&ts=1340880299&
userip=112.90.139.30&zoneid=1

然后进行URL编码(<font color=red> (编码时请关注URL编码注意事项,否则容易导致后面签名不能通过验证),编码结果为:
appid%3D15499%26format%3Djson%26openid%3D00000000000000000000000014BDF6E4%26openkey%3DAB43BF3DC
5C3C79D358CC5318E41CF59%26pf%3Dmyapp_m_qq-00000000-android-00000000-ysdk%26pfkey%3DCA641BC173479B8
C0B35BC84873B3DB9%26ts%3D1340880299%26userip%3D112.90.139.30%26zoneid%3D1

第4步:将HTTP请求方式,第1步以及第3步中的到的字符串用&拼接起来,得到源串:
GET&%2Fv3%2Fr%2Fmpay%2Fget_balance_m&appid%3D15499%26format%3Djson%26openid%3D0000
0000000000000000000014BDF6E4%26openkey%3DAB43BF3DC5C3C79D358CC5318E41CF59%26pf%3Dmyapp_m_qq-
00000000-android-00000000-ysdk%26pfkey%3DCA641BC173479B8C0B35BC84873B3DB9%26ts%3D1340880299%26
userip%3D112.90.139.30%26zoneid%3D1

Step 2. 构造密钥

得到密钥的方式:在应用的appkey末尾加上一个字节的“&”,即appkey&, 注意这里的appkey指的是米大师的appkey, 测试环境用沙箱appkey, 正式环境用正式环境的appkey,例如:

56abfbcd12fe46f5ad85ad9f12345678&

Step 3. 生成签名值

(1)使用HMAC-SHA1加密算法,使用Step2中得到的密钥对Step1中得到的源串加密。
(注:一般程序语言中会内置HMAC-SHA1加密算法的函数,例如PHP5.1.2之后的版本可直接调用hash_hmac函数。)
(2)然后将加密后的字符串经过Base64编码。
(注:一般程序语言中会内置Base64编码函数,例如PHP中可直接调用 base64_encode() 函数。)
(3)得到的签名值结果如下:

SqI7fyvtnWBYMfERV8hZc9YQXp0=

(4)发送请求时所有参数都要进行URL编码。对签名Sig进行编码,会得到如下结果:

SqI7fyvtnWBYMfERV8hZc9YQXp0%3D

最后发送的请求串
http://域名/mpay/get_balance_m?appid=15499&format=json&openid=0000000000000 0000000000014BDF6E4&openkey=AB43BF3DC5C3C79D358CC5318E41CF59&pf=myapp_m_qq-00000000-andr oid-00000000-ysdk&pfkey=CA641BC173479B8C0B35BC84873B3DB9&ts=1340880299&userip=112.90.139.30 &zoneid=1&sig=SqI7fyvtnWBYMfERV8hZc9YQXp0%3D

2. 常见错误排障

为什么总是返回“-5:signature verification failed”?
签名校验失败分为以下两种情况:
(1) sig参数生成错误
有可能由下列原因引起:
• 构造源串时注意URI不含host,并且要加上/v3/r,如访问https:// ysdk.qq.com/mpay/get_balance_m,则对应签名的URI是/v3/r/mpay/get_balance_m,而不是/mpay/get_balance_m;
• 构造源串时,没有将key排序后,再将(key=value)用&拼接起来。
• 构造密钥时,没有将appkey后加“&”。
• 生成签名时用了GET方式,但实际请求时用POST方式。
• 某些语言的URLEncode系统方法在进行URL编码时,并没有按照现行的URL编码规则进行。详见下文的:URL编码注意事项。


对于支付和营销类接口,除了以上问题外,还有一些特别容易出错的地方:
• 支付和营销相关回调协议中规定参数值都为string型,开发商出于本地记账等目的,对接收到的某些参数值先转为数值型再转为string型,导致字符串部分被截断(例如:字符串“13.14”转为整形再转为string 就会变成13),从而导致签名出错。
   如果要进行本地记账等逻辑,建议用另外的变量来保存数值,传参时必须用原始接收到的string型值。
• 支付和营销相关回调协议中,在进行签名生成时多加了一个步骤:
   在构造源串的第3步“将排序后的参数(key=value)用&拼接起来,并进行URL编码”之前,需对value先进行一次编码 (编码规则为:除了 0~9 a~z A~Z !*() 之外其他字符按其ASCII码的十六进制加%进行表示,例如“-”编码为“%2D”)。
• 支付和营销接口中的goodmeta参数,必须是UTF8格式,参与签名前要进行Base64编码。
• 支付和营销接口中的payitem参数,含有*号字符,在进行URL编码时要注意观察是否进行了编码。
(2) sig参数生成正确,但是参数传输前没有进行URL编码。
所有参数传输时都要进行URL编码,包括sig。如果没有进行URL编码,则即使sig是正确的,但是校验sig时不能匹配。

建议的解决方案
(1)开发者可以使用平台提供的签名验证工具来计算签名:http://open.qq.com/tools , 通过工具吐出的签名生成过程,来排查具体是哪一步出了问题。
(2)如果您是PHP开发者,可以使用PHP SDK中的签名生成函数来生成签名,避免自己去进行复杂的签名生成逻辑的开发。

3. URL编码注意事项

URL编码规则:
签名验证时,要求对字符串中除了“-”、“_”、“.”之外的所有非字母数字字符都替换成百分号(%)后跟两位十六进制数。
十六进制数中字母必须为大写。

注意事项
(1)某些系统方法,例如.NET系统方法HttpUtility.UrlEncode会将‘=’编码成‘%3d’,而不是%3D,导致加密签名通不过验证,请开发者注意检查。
(2)Java 1.3和早期版本中,调用java.net.URLEncoder下的方法进行URL编码时,某些特殊字符并不会被编码,例如星号(*)。
由于URL编码规则中规定了星号(*)必须编码,因此在请求字符串中含星号(*)的情况下如果使用了上述方法,会导致生成的签名不能通过验证
例如调用v3/pay/buy_goods接口时, payitem参数值中一定会含有* ,在使用类java.net.URLEncoder下的方法进行编码后,需开发人员手动将星号字符“*”替换为“%2A”,否则将导致加密签名一直通不过验证,请开发者注意检查。
(3)某些语言的urlencode方法会把“空格”编码为“+”,实际上应该编码为“%2B”。这也将生成错误的签名,导致签名通不过验证。
请开发者注意检查,手动将“+”替换为“%2B”

在PHP中,推荐用rawurlencode方法进行URL编码。

以上信息是否解决您的问题?

Copyright © 1998 - 2017 Tencent. All Rights Reserved.

腾讯公司 版权所有

有问必答 返回顶部