加密規則:
1.固定加密字符串+字符串組合(key/value的形式,並通過aissc碼排序),
2.通過sha1算法對排序后的字符串進行加密,
3.最終輸出需要的參數sign
4.完成請求參數數據的格式輸出(因為瀏覽器復制出來的格式直接用python是不能請求的所以我用了之前寫的一個方法來完成請求數據格式的轉換)
例如:
輸入:
'''course_finance_id[0]:252638
total_price:0
state:1
finan_rmk:343
timestamp:122
sign:11'''xxx
輸出:
'course_finance_id[0]=252638&total_price=0&state=1&finan_rmk=343×tamp=1572505825134&sign=feab1228e93329b4e4adcebc7bcx'x'x2c4225a1eccba'
不廢話,上代碼:
def fwh_sign_sha1(self,str_in):#服務號請求簽名處理封裝 '''主要過程: 1.替換輸入字符串中的時間戳為最新的時間戳 2.將字符串中的sign字段過濾掉並通過ascii對其進行排序,因為加密時不需要此字段 3.將排序且處理后的字符串通過sha1算法,得到加密字符串 4.將得到的加密字符串替換至原字符串''' search_time_str='timestamp:' search_sign_str='sign:' str_inSource=re.search('(%s.+)'%(search_time_str),str_in)#匹配字段時間戳(timestamp) if str_inSource is not None: time_str=self.get_timestamp()#最終需要的時間戳,13位 str_inSource=str_inSource.group() search_str_inSource=re.search('\s',str_inSource) #匹配時間戳,key與value是否包含空格 #如果包含空格,替換時加上空格,如果不處理會有問題(字符串格式與其他地方不一致) if search_str_inSource is not None: str_equalSource=re.sub(str_inSource,'%s%s%s'%(search_time_str,search_str_inSource.group(),time_str), str_in)#將輸入的時間戳替換為需要的時間戳,並加上匹配出來得空格 else: str_equalSource=re.sub(str_inSource,'%s%s'%(search_time_str,time_str), str_in)#將輸入的時間戳替換為需要的時間戳 input_list_source=str_equalSource.split('\n')#以換行符分隔字符串並轉換位列表 input_list=[a for a in input_list_source if (search_sign_str or '%s\s'%(search_sign_str) ) not in a]#列表過濾字段sign out_list=sorted(input_list)#對list進行排序 out_str='\n'.join(out_list)#將排序后的list拼接為字符串 input_sign_str=self.requestDataToStr_firefoxAndChrome(out_str,'','').decode()#獲取拼接完成后的請求參數字符串(sign) '''這個方法默認對請求參數進行了編碼處理,所以這里需手動解碼''' out_sign_str=self.sha1_Encry(input_sign_str)#得到加密后的加密字符串 str_inSource_sign=re.search('(%s.+)'%(search_sign_str),str_in)#匹配字段簽名驗證(sign) if str_inSource_sign is not None: str_inSource_sign=str_inSource_sign.group() search_inSource_sign=re.search('\s',str_inSource) #匹配sign,key與value是否包含空格 #如果包含空格,替換時加上空格,如果不處理會有問題(字符串格式與其他地方不一致) if search_inSource_sign is not None: str_last_sign=re.sub(str_inSource_sign,'%s%s%s'%(search_sign_str,search_inSource_sign.group(), out_sign_str),str_equalSource)#將輸入的時間戳替換為需要的時間戳 else: str_last_sign=re.sub(str_inSource_sign,'%s%s'%(search_sign_str,out_sign_str), str_equalSource)#將輸入的時間戳替換為需要的時間戳 # print(str_last_sign) str_give=self.requestDataToStr_firefoxAndChrome(str_last_sign) # print(str_give) return str_give else: print('輸入字符串沒有sign對象:sign,無法完成數據轉換') return None else: print('輸入字符串沒有時間戳對象:timestamp,無法完成數據轉換') return None
#字符串進行sha1算法加密方法
def sha1_Encry(self,str_in,Encay_strOne=Encay_str):#對字符串進行加密 str_out=hashlib.sha1() #采用sha1加密 str_out.update(str('%s%s'%(str_in,Encay_str)).encode(encoding='utf-8')) return str_out.hexdigest()
#輸出13位時間戳方法
def get_timestamp(self):#輸出當前時間的13位時間戳 current_milli_time = lambda: int(round(time.time() * 1000))#輸出13位時間戳,round:對浮點數進行四舍五入 return str(current_milli_time())
#字符串格式處理方法
def requestDataToStr_firefoxAndChrome(self,str_in,space_one='=',space_two='&'): try: str_colon=re.search(':\W?|\s*:\W?',str_in) #匹配出字符串中所有的冒號 if not str_colon==None: str_colon=str_colon.group() str_equal=re.sub(str_colon,space_one,str_in) #將字符串中的冒號替換為等於號(: >>> =) str_lin=re.search("(\s\n*){2,}|(\s\n*)",str_equal) #匹配出字符串中所有的換行符與空格,不寫表示不限定匹配次數 if not str_lin==None: str_lin=str_lin.group() str_give=re.sub(str_lin,space_two,str_equal) #將字符串中的換行符替換為& (\n >>> &) str_lin2=re.search('\s.*',str_give) if str_lin2 is not None: str_lin2=str_lin2.group() str_lin3=re.search('=',str_lin2) if str_lin3 is not None and 'time' in str_give: #對請求參數含有時間字段進行特殊處理 try: str_lin3=str_lin3.group() str_give2=re.sub(str_lin3,':',str_lin2) str_give3=re.sub(str_lin2,str_give2,str_give) # print(str_give3) return str_give3.encode() #返回字符串,並對數據進行編碼處理 except Exception as error: print(error) else: # print(str_give) return str_give.encode() else: # print(str_give) return str_give.encode() else: return str_equal.encode() else: print("字符串格式匹配錯誤") return None except Exception as error: print("數據處理失敗,原因為:\n%s"%(error))
寫這個方法的時候遇到了一些問題,所以各位再實踐的過程中一定要細心,字符串處理時一定要注意對空格的處理,最好保持格式的統一(參數替換時如果其他參數帶有空格,替換時不要全給替換掉了,因為正則匹配時匹配不到就會使轉換后的字符串達不到預期效果,看后續能不能想到更好的解決方法把),這樣能避免一些問題