python接口自動化-實現sign簽名(MD5加密)


本文內容皆為作者原創,碼字不易,如需轉載,請注明出處:https://www.cnblogs.com/temari/p/13513636.html

一,前序

今天在學習sign簽名的的時候,了解了下常用的sign加密算法,突然心血來潮,想用python試着將簽名生成的通用步驟用代碼實現出來,雖然中間經歷了一點小波折,請教了開發同事后,按照他給的思路建議,搞定了。我實現的是微信支付的簽名算法規則。

二,加密業務規則

簽名生成的通用步驟如下:

第一步,設所有發送或者接收到的數據為集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特別注意以下重要規則:

1.參數名ASCII碼從小到大排序(字典序);
2.如果參數的值為空不參與簽名;
3.參數名區分大小寫;
4.驗證調用返回或微信主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值作校驗。
5.微信接口可能增加字段,驗證簽名時必須支持增加的擴展字段。

第二步,在stringA最后拼接上key得到stringSignTemp字符串,並對stringSignTemp進行MD5運算,再將得到的字符串所有字符轉換為大寫,得到sign值signValue。

參考網址:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3

三,代碼設計

3.1 參數類型確定
由微信支付簽名生成規則描述可知,需要加密的參數數據是按照鍵值對的形式拼接,且參數名區分大小寫,將參數數據定義為字典Dict類型特別合適,由於python本身區分大小寫,字典鍵值也區分大小寫。
#如代碼所示:
>>> data={'q':'apple','Q':'orange'}
>>> data['q']
'apple'
>>> data['Q']
'orange'
3.2 參數設計

為了滿足"參數的值為空不參與簽名,傳送的sign參數不參與簽名,接口參數支持擴展”的簽名算法規則,參數字典data在設計的時候除了要包含微信支付接口提供的必傳參數外,另外我補充了參數值為空和參數名為sign的參數,如下:

#string1,string2用戶擴展,增加參數名sign的參數
data={
     'appid':'wxd930ea5d5a258f4f',
     'mch_id':'10000100',
     'device_info':'1000',
     'body':'test',
     'nonce_str':'ibuaiVcKdpRxkhJA',
     'string1':'',
     'string2':'',
     'sign':'fdsfdhgjghjf'
}
3.3 自定義函數設計

參數data確定下來后,由於存在參數名為sign或者參數值為空的參數,這兩種參數是不參與簽名的。需要寫一個函數,用於排除參數名為sign或者參數值為空的參數。另外參與簽名的參數生成后,參數名要按照ASCII進行從小到大排序,然后跟參數值進行拼接,這里需要設計一個拼接函數。拼接函數需要實現參數名排序,python數據類型中,字典沒有排序功能,但是列表有一個sort()函數可實現對象排序,因此要把字典的鍵值單獨取出來存放到列表中進行排序,排序完成后再根據鍵名取字典對應的鍵值。

3.4 加密函數

需要加密的字符串生成后,可以利用python的hashlib模塊對字符串進行加密。Python的hashlib提供了常見的摘要算法,如MD5,SHA1等等,這里我用md5加密。加密后把字符串轉換成大寫,生成sign簽名。

3.5 簽名實現邏輯

1.將傳的參數定義成字典類型數據A。
2.排除參數名為sign或者參數值為空的參數,另存為新的字典類型數據B。
3.將參數名用ASCII進行從小到大排序,參數名保存成列表對象。
4.用排序完成的參數名循環遍歷字典數據B,跟參數值拼接。參數名1=參數值&參數名2=參數值&...
5.參數拼接完成,每個商戶的key值也需要拼接,生成拼接API秘鑰。
6.拼接完成的字符串,MD5加密,使用hashlib模塊。
7.將加密得到的字符串所有字符轉換為大寫,得到sign值signValue。

四,代碼實現

完整代碼如下:
"""
接口名稱:微信支付
實現目標:微信支付sign簽名MD5加密
簽名算法規則:
1.參數名ASCII碼從小到大排序(字典序)
2.如果參數的值為空不參與簽名
3.參數名區分大小寫
4.驗證調用返回或微信主動通知簽名時,傳送的sign參數不參與簽名,將生成的簽名與該sign值作校驗
5.微信接口可能增加字段,驗證簽名時必須支持增加的擴展字段
"""

#導入數據處理加密的包
import hashlib
keyString="192006250b4c09247ec02edce69f6a2d"
#所有發送或者接收到的數據定義為字典類型數據
data={
     'appid':'wxd930ea5d5a258f4f',
     'mch_id':'10000100',
     'device_info':'1000',
     'body':'test',
     'nonce_str':'ibuaiVcKdpRxkhJA',
     'string1':'',
     'string2':'',
     'sign':'fdsfdhgjghjf'
}

#定義函數作用:去除參數的值為空或者參數名為sign的數據,返回參與簽名的字典類型數據
def GetSignData(data):
    signData={}
    for key, value in data.items():
        if value != "" and key != "sign":
            signData[key] = value
    return  signData

#對參數按照key=value的格式,並按照參數名ASCII字典序排序拼接成字符串stringA,最后拼接上key,返回拼接API密鑰。
def SignString(signData,key):
   #定義空列表
   list=[]
   # 定義空字符串
   stringA=""
   #循環遍歷字典數據的鍵值,取出存放到列表中
   for key in signData.keys():
       list.append(key)
   #對列表的對象進行排序,默認升序,即按照ASCII碼從小到大排序
   list.sort()
   #循環遍歷排序后的列表,根據鍵值取出字典鍵對應的值
   for i in list:
       stringA += i+"="+signData[i]+"&"
    #參數拼接成需要加密的字符串
   stringA += "key"+"="+keyString
   return   stringA

#調用GetSignData函數,獲取參與簽名的參數,返回新的字典數據
signData=GetSignData(data)
#調用函數,返回需要加密的字符串
signBody=SignString(signData,keyString)
print(signBody)

#創建對象md
md=hashlib.md5()
#對stringA字符串進行編碼
md.update(signBody.encode('utf-8'))
#數據加密
signValue=md.hexdigest()
#把加密的結果,小寫轉換成大寫,upper函數
signValue=signValue.upper()
print(signValue)
代碼演示:

用python代碼編寫生成的sign簽名與微信支付網頁的簽名一樣,說明代碼正確,如圖:


免責聲明!

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



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