現在很多這種快速支付的通道,易寶支援的通道算是很全面的,正好最近需要整合易寶的支付通道到平台中,所以寫一貼來記錄一下,順便鄙視一下國內的支付平台,api的支援做得很是差勁,易寶的例子代碼居然是錯的,這麼囧的事情都能出現,可見國內的競爭還是不夠激烈啊。
進入主題,今天的任務是要打通支付和支付通知介面,根據一般性規則,通過http協議的支付介面的一般設計都是,通過N個field或者查詢參數傳遞資料,其中一個是驗證串,防止篡改資料,每個申請了支付介面的使用者都給了一個編號,相當於使用者名稱,一個key,相當於密碼,用於加密防篡改欄位的鹽值。
易寶的欄位定義在文檔中有,這個文檔到處能下到,對發起請求的url這裡文檔倒沒有什麼錯,但是文檔裡的例子是POST,把資料放到隱藏表單裡,我這裡通過構造Get的querystring的方式來發送資料。
根據文檔,首先定義資料如下:#用的測試平台的資料
data=[
"",
("p0_Cmd","Buy"),
("p1_MerId","10000432521"),
("p2_Order",transid),
("p3_Amt",str(fee)),
("p4_Cur","CNY"),
("p5_Pid","測試一下嘛"),
("p6_Pcat","test"),
("p7_Pdesc","test"),
("p8_Url","http://"),
("p9_SAF","1"),
("pa_MP","None"),
("pd_FrpId","ICBC-NET"),
("pr_NeedResponse","1"),
]
第一個“”不是打醬油的,在下面的運算是有用處的,不要當我寫錯了忽略掉。
首先我們要根據資料來構建待加密的驗證源串,根據文檔描述也就是把每個field的值串連起來,注意,不加任何間隔符,看看讓人吐血的文檔
看這段描述,你能猜出是如何構造這個字串的嗎?寫這個文檔的人多半語文重修不下十次
根據這段文檔唯一有用的一句話參看了源碼,於是把源碼裡囉哩吧嗦的一大篇八股文改為一行代碼,搞定
origin_str=reduce(lambda x,y:"%s%s"%(x,y[1]),data)
這裡用了reduce函數,就是挨個取出list裡的資料和下一資料累計運算,運算的方法就是把前一次運算的結果和下一個item作為參數傳給reduce的第一個參數,這裡是一個lambda運算式,x就是前一次運算的結果,y就是下一個item,因為運算式裡預設第一次運算的結果是字串,所以這就是在data這個列表頭上的第一個打醬油的””的來曆
接下來需要用hmac來加密字串,拜偉大的python大嬸的神威,我在shell裡輸入import hmac
斷行符號後居然還真有這個庫,省去麻煩一大堆,於是
mac=hmac.new("8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t")
mac.update(origin_str)
hash_key=mac.hexdigest()
得到key後,需要構建查詢的字串,這種遍曆的操作用python的函數變成支援很是爽,又是一行搞定
query= "".join(["http://tech.yeepay.com:8080/robot/debug.action?",reduce(lambda x,y:"%s&%s=%s"%(x,y[0],y[1]),data).lstrip("&"),"&hmac=",hmac_key])
這裡我們再次祭出了reduce大嬸
接下來有一個很重要的步驟,就是對中文的編碼處理,易寶支援GBK,所以我們需要把這個字串轉換成GBK的編碼:
query=unicode(query,"utf8").encode("GBK")
這裡我們預設你的檔案頭部是
#-*- coding:utf-8 –*- 而你的源檔案也是utf8編碼儲存的
剩下的事情很簡單了,redirect到這個地址就可以看到測試成功的頁面了。
這要注意的是我用的ID,Key,和介面的地址都是測試專用的,要用上正式環境需要用正式環境下的key,id,和介面地址來代替
接下來需要搞定的就是回調地址的程式,這裡最重要的就是解析參數和hash參數的防篡改串,也就是參數名為hmac的那個值,這裡易寶在文檔裡和樣本程式裡都犯了不可饒恕地罪過,在文檔和代碼裡都只說要檢測r0~r9開頭的參數,但是其實裡面有個p1_MerId的參數也要算進去,不然你是永遠不可能得出正確的結果的。
驗證部分同前面,這裡我們假設所有querystring都是架構解析好了,放在一個dict裡面
keys=['p1_MerId', 'r0_Cmd', 'r1_Code', 'r2_TrxId', 'r3_Amt', 'r4_Cur', 'r5_Pid', 'r6_Order', 'r7_Uid', 'r8_MP', 'r9_BType']
origin=reduce(lambda x,y:"%s%s"%(x,y),[dic[k] for k in keys])
mac=hmac.new("8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t")
mac.update(origin)
hmac_key=mac.hexdigest()
其實功能這些都是很簡單的,不過用上了python,頭不痛了,腰不酸了,上樓也有勁了。