支付寶介面呼叫總結(1)
阿新 • • 發佈:2018-12-17
支付寶沙漏測試使用
首先建立一個開發者賬號
略
呼叫alipay介面
# 4 呼叫alipay介面 import time alipay = self.get_alipay() # 生成支付的url query_params = alipay.direct_pay( subject="路飛學城", # 商品簡單描述 out_trade_no="x345" + str(time.time()), #商戶訂單號 total_amount=pay_money, # 交易金額(單位: 元 保留倆位小數) ) pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params) res.data={ "url":pay_url }
self.get_alipay.py
def get_alipay(self):# 沙箱環境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info app_id = "2016091100486897" # POST請求,用於最後的檢測 notify_url = "http://47.94.172.250:8804/page2/" # notify_url = "http://www.wupeiqi.com:8804/page2/" # GET請求,用於頁面的跳轉展示 return_url = "http://47.94.172.250:8804/page2/" # return_url = "http://www.wupeiqi.com:8804/page2/" merchant_private_key_path = "keys/app_private_2048.txt" alipay_public_key_path = "keys/alipay_public_2048.txt" alipay = AliPay( appid=app_id, app_notify_url=notify_url, return_url=return_url, app_private_key_path=merchant_private_key_path, alipay_public_key_path=alipay_public_key_path, # 支付寶的公鑰,驗證支付寶回傳訊息使用,不是你自己的公鑰 debug=True, # 預設False, ) return alipay
引用的from api.utils.pay import AliPay
1 from datetime import datetime 2 from Crypto.PublicKey import RSA 3 from Crypto.Signature import PKCS1_v1_5 4 from Crypto.Hash import SHA256 5 from urllib.parse import quote_plus 6 from urllib.parse import urlparse, parse_qs 7 from base64 import decodebytes, encodebytes 8 import json 9 10 11 class AliPay(object): 12 """ 13 支付寶支付介面(PC端支付介面) 14 """ 15 16 def __init__(self, appid, app_notify_url, app_private_key_path, 17 alipay_public_key_path, return_url, debug=False): 18 self.appid = appid 19 self.app_notify_url = app_notify_url 20 self.app_private_key_path = app_private_key_path 21 self.app_private_key = None 22 self.return_url = return_url 23 with open(self.app_private_key_path) as fp: 24 self.app_private_key = RSA.importKey(fp.read()) 25 self.alipay_public_key_path = alipay_public_key_path 26 with open(self.alipay_public_key_path) as fp: 27 self.alipay_public_key = RSA.importKey(fp.read()) 28 29 if debug is True: 30 self.__gateway = "https://openapi.alipaydev.com/gateway.do" 31 else: 32 self.__gateway = "https://openapi.alipay.com/gateway.do" 33 34 def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs): 35 biz_content = { 36 "subject": subject, 37 "out_trade_no": out_trade_no, 38 "total_amount": total_amount, 39 "product_code": "FAST_INSTANT_TRADE_PAY", 40 # "qr_pay_mode":4 41 } 42 43 biz_content.update(kwargs) 44 data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url) 45 return self.sign_data(data) 46 47 def build_body(self, method, biz_content, return_url=None): 48 data = { 49 "app_id": self.appid, 50 "method": method, 51 "charset": "utf-8", 52 "sign_type": "RSA2", 53 "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 54 "version": "1.0", 55 "biz_content": biz_content 56 } 57 58 if return_url is not None: 59 data["notify_url"] = self.app_notify_url 60 data["return_url"] = self.return_url 61 62 return data 63 64 def sign_data(self, data): 65 data.pop("sign", None) 66 # 排序後的字串 67 unsigned_items = self.ordered_data(data) 68 unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items) 69 sign = self.sign(unsigned_string.encode("utf-8")) 70 # ordered_items = self.ordered_data(data) 71 quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items) 72 73 # 獲得最終的訂單資訊字串 74 signed_string = quoted_string + "&sign=" + quote_plus(sign) 75 return signed_string 76 77 def ordered_data(self, data): 78 complex_keys = [] 79 for key, value in data.items(): 80 if isinstance(value, dict): 81 complex_keys.append(key) 82 83 # 將字典型別的資料dump出來 84 for key in complex_keys: 85 data[key] = json.dumps(data[key], separators=(',', ':')) 86 87 return sorted([(k, v) for k, v in data.items()]) 88 89 def sign(self, unsigned_string): 90 # 開始計算簽名 91 key = self.app_private_key 92 signer = PKCS1_v1_5.new(key) 93 signature = signer.sign(SHA256.new(unsigned_string)) 94 # base64 編碼,轉換為unicode表示並移除回車 95 sign = encodebytes(signature).decode("utf8").replace("\n", "") 96 return sign 97 98 def _verify(self, raw_content, signature): 99 # 開始計算簽名 100 key = self.alipay_public_key 101 signer = PKCS1_v1_5.new(key) 102 digest = SHA256.new() 103 digest.update(raw_content.encode("utf8")) 104 if signer.verify(digest, decodebytes(signature.encode("utf8"))): 105 return True 106 return False 107 108 def verify(self, data, signature): 109 if "sign_type" in data: 110 sign_type = data.pop("sign_type") 111 # 排序後的字串 112 unsigned_items = self.ordered_data(data) 113 message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items) 114 return self._verify(message, signature)pay.py
1 from datetime import datetime 2 from Crypto.PublicKey import RSA 3 from Crypto.Signature import PKCS1_v1_5 4 from Crypto.Hash import SHA256 5 from urllib.parse import quote_plus 6 from urllib.parse import urlparse, parse_qs 7 from base64 import decodebytes, encodebytes 8 import json 9 10 11 class AliPay(object): 12 """ 13 支付寶支付介面(PC端支付介面) 14 """ 15 16 def __init__(self, appid, app_notify_url, app_private_key_path, 17 alipay_public_key_path, return_url, debug=False): 18 self.appid = appid 19 self.app_notify_url = app_notify_url 20 self.app_private_key_path = app_private_key_path 21 self.app_private_key = None 22 self.return_url = return_url 23 with open(self.app_private_key_path) as fp: 24 self.app_private_key = RSA.importKey(fp.read()) 25 self.alipay_public_key_path = alipay_public_key_path 26 with open(self.alipay_public_key_path) as fp: 27 self.alipay_public_key = RSA.importKey(fp.read()) 28 29 if debug is True: 30 self.__gateway = "https://openapi.alipaydev.com/gateway.do" 31 else: 32 self.__gateway = "https://openapi.alipay.com/gateway.do" 33 34 def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs): 35 biz_content = { 36 "subject": subject, 37 "out_trade_no": out_trade_no, 38 "total_amount": total_amount, 39 "product_code": "FAST_INSTANT_TRADE_PAY", 40 # "qr_pay_mode":4 41 } 42 43 biz_content.update(kwargs) 44 data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url) 45 return self.sign_data(data) 46 47 def build_body(self, method, biz_content, return_url=None): 48 data = { 49 "app_id": self.appid, 50 "method": method, 51 "charset": "utf-8", 52 "sign_type": "RSA2", 53 "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 54 "version": "1.0", 55 "biz_content": biz_content 56 } 57 58 if return_url is not None: 59 data["notify_url"] = self.app_notify_url 60 data["return_url"] = self.return_url 61 62 return data 63 64 def sign_data(self, data): 65 data.pop("sign", None) 66 # 排序後的字串 67 unsigned_items = self.ordered_data(data) 68 unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items) 69 sign = self.sign(unsigned_string.encode("utf-8")) 70 # ordered_items = self.ordered_data(data) 71 quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items) 72 73 # 獲得最終的訂單資訊字串 74 signed_string = quoted_string + "&sign=" + quote_plus(sign) 75 return signed_string 76 77 def ordered_data(self, data): 78 complex_keys = [] 79 for key, value in data.items(): 80 if isinstance(value, dict): 81 complex_keys.append(key) 82 83 # 將字典型別的資料dump出來 84 for key in complex_keys: 85 data[key] = json.dumps(data[key], separators=(',', ':')) 86 87 return sorted([(k, v) for k, v in data.items()]) 88 89 def sign(self, unsigned_string): 90 # 開始計算簽名 91 key = self.app_private_key 92 signer = PKCS1_v1_5.new(key) 93 signature = signer.sign(SHA256.new(unsigned_string)) 94 # base64 編碼,轉換為unicode表示並移除回車 95 sign = encodebytes(signature).decode("utf8").replace("\n", "") 96 return sign 97 98 def _verify(self, raw_content, signature): 99 # 開始計算簽名 100 key = self.alipay_public_key 101 signer = PKCS1_v1_5.new(key) 102 digest = SHA256.new() 103 digest.update(raw_content.encode("utf8")) 104 if signer.verify(digest, decodebytes(signature.encode("utf8"))): 105 return True 106 return False 107 108 def verify(self, data, signature): 109 if "sign_type" in data: 110 sign_type = data.pop("sign_type") 111 # 排序後的字串 112 unsigned_items = self.ordered_data(data) 113 message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items) 114 return self._verify(message, signature)pay
最後下載模組
pip3 install pycryptodome
存放的公鑰替換檔案位置放在根目錄