看我如何接入騰訊API,以及生成sig簽名~\(≧▽≦)/~


以騰訊上傳用戶在應用中的等級相關信息為例。接口詳情在此【"http://wiki.open.qq.com/wiki/v3/user/get_info"】

在set_achievement這個接口中,接口參數包括openid, openkey, appid, pf, sig, user_attr, format

此接口最后的請求示例為

http://openapi.tencentyun.com/v3/user/set_achievement?
openid=B624064BA065E01CB73F835017FE96FA&
openkey=5F154D7D2751AEDC8527269006F290F70297B7E54667536C&
appid=2&
pf=qzone&
format=json&
user_attr=%7B%22level%22%3A10%7D&
sig=9999b41ad0b688530bb1b21c5957391c

這里除了sig其他參數都只是經過了URL編碼而已,所以本文的重點也在如何生成sig。

點我查看詳細簽名規則

在寫代碼的過程中我們也可以思考下為什么需要生成簽名~

Step 1. 構造源串

第1步:將請求的URI路徑進行URL編碼(URI不含host,URI示例:/v3/user/get_info)。請開發者關注:URL編碼注意事項,否則容易導致后面簽名不能通過驗證。

第2步:將除“sig”外的所有參數按key進行字典升序排列。 注:除非OpenAPI文檔中特別標注了某參數不參與簽名,否則除sig外的所有參數都要參與簽名。

第3步:將第2步中排序后的參數(key=value)用&拼接起來,並進行URL編碼。請開發者關注:URL編碼注意事項,否則容易導致后面簽名不能通過驗證。 第4步:將HTTP請求方式(GET或者POST)以及第1步和第3步中的字符串用&拼接起來。

Step 2. 構造密鑰

得到密鑰的方式:在應用的appkey末尾加上一個字節的“&”,即appkey&

Step 3. 生成簽名值

1. 使用HMAC-SHA1加密算法,使用Step2中得到的密鑰對Step1中得到的源串加密。 (注:一般程序語言中會內置HMAC-SHA1加密算法的函數,例如PHP5.1.2之后的版本可直接調用hash_hmac函數。)

2. 然后將加密后的字符串經過Base64編碼。 (注:一般程序語言中會內置Base64編碼函數,例如PHP中可直接調用 base64_encode() 函數。)

3. 得到的簽名值結果如下:

FdJkiDYwMj5Aj1UG2RUPc83iokk=

以下是生成sig的解決方案:

 

def getSig(cfg):
    strFilter = ".-_"
    codeUrlAddr = urllib2.quote(cfg['urlAddr'],strFilter)  
    urlData2 = sorted(cfg['urlData'].iteritems(), key=lambda d:d[0])
    codeStr0 = ""
    for (value01,value02) in urlData2:
        if codeStr0:
            codeStr0 += "&" + str(value01) + '=' + str(value02)
        else:
            codeStr0 += str(value01) + '=' + str(value02)
    codeStr1 = urllib2.quote(codeStr0)     
    codeConn = cfg['urlMethod'] + '&' + codeUrlAddr + '&' + codeStr1
    sig = hmac.new(cfg['appkey'] + '&', codeConn, hashlib.sha1).digest().encode('base64').rstrip()
    return sig

def test(): 
    urlData = {
        'openid' : '12345',
        'openkey' : '12345',
        'pf' : 'wanba_ts',
        'appid' : 12345,
        'format' : 'json',
        'user_attr' : '{"level":%d}' % 1234
    }
    urlcfg = {
        'urlAddr' : '/v3/user/set_achievement',
        'urlMethod' : 'GET',
        'appkey' : 'ABCDWFSFFG',
        'urlData' : urlData
    } 
    urlData['sig'] = getSig(urlcfg)
 

 

第一步:將請求的URI路徑進行URL編碼(URI不含host,URI示例:/v3/user/get_info)。

urlCfg中urlAddr是第一步中的請求的URI路徑。

URL編碼規則:
簽名驗證時,要求對字符串中除了“-”、“_”、“.”之外的所有非字母數字字符都替換成百分號(%)后跟兩位十六進制數。
十六進制數中字母必須為大寫。

strFilter = ".-_" #不需要替換的字符
codeUrlAddr = urllib2.quote(cfg['urlAddr'],strFilter)# url編碼

第二步:將除“sig”外的所有參數按key進行字典升序排列。 

urlData中就是第二步要求的sig參數外的所有參數,采用sorted方式進行排序。

urlData2 = sorted(cfg['urlData'].iteritems(), key=lambda d:d[0])

 

第三步:將第2步中排序后的參數(key=value)用&拼接起來,並進行URL編碼。

    codeStr0 = ""
    for (value01,value02) in urlData2:
        if codeStr0:
            codeStr0 += "&" + str(value01) + '=' + str(value02)
        else:
            codeStr0 += str(value01) + '=' + str(value02)
    codeStr1 = urllib2.quote(codeStr0)

當我看到urllib.urlencode可以用來直接生成&進行拼接的時候非常開心,但是后來發現它會對value進行url編碼。這與我們的要求是不符合的。所以采用了上面這種詭異的方式。

第四步:將HTTP請求方式(GET或者POST)以及第1步和第3步中的字符串用&拼接起來。

codeConn = cfg['urlMethod'] + '&' + codeUrlAddr + '&' + codeStr1

Step2和Step3

sig = hmac.new(cfg['appkey'] + '&', codeConn, hashlib.sha1).digest().encode('base64').rstrip()

這樣就得到了sig的值,文檔看起來有些復雜,但是一步步做下來其實難度也不大。

接下來就是按照文檔要求進行數據請求啦~

 urlStr1 = urllib.urlencode(urlData)
 url = urlHost + qqUserInfos['getPlayzoneUserInfoUrl'] + '?' + urlStr1
    
 request = urllib2.Request(url)
 result = json.loads(urllib2.urlopen(request).read())

在這個過程中不知道有沒有小伙伴好奇為什么我的urlData里面的user_attr要像下面這樣寫

'user_attr' : '{"level":%d}' % 1234

其實剛開始我是直接把{"level:1234}這個字典賦值給user_attr的。但是在操作的過程中發現由於python會把雙引號自動變成單引號,導致生成的簽名一直有問題。所以采用json格式來解決這個問題。

你以為本文這就完了?當!然!不!是!還有剛開始提出的問題沒回答捏~

sooooo...為什么要生成簽名?

The answer is "為了確定數據來源正確合法"

雙方如何根據簽名確定數據來源正確,以騰訊為例:
1.騰訊給我們一個appkey用作密鑰,我們按照騰訊約定的簽名方式對sig以外的參數進行簽名。
2.生成簽名后,將用作簽名的參數和簽名一起傳給騰訊服務器。
3.服務器將簽名與我們的appid對應的appkey進行解密。
4.將傳遞過去的參數排序,然后與生成的參數進行對比。若數據一致則能保證數據真實。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM