[後端開發]支付寶支付介面除錯 (Python v3.6)
阿新 • • 發佈:2018-11-22
寫在前面:
講真,一開始接到這個任務我是拒絕的。因為支付寶官方沒有提供Python的SDK環境,只有JAVA/PHP/.NET三種語言的SDK,這意味著簽名&驗籤、HTTP介面請求等操作全都要自己手動實現,就算支付寶提供了簽名、驗籤的演算法說明,但僅靠它的文字描述就寫出一個符合支付寶想法的演算法很明顯“任重道遠”,我當然不會去嘗試這條路。
幸運的是,github總能給我驚喜,搜尋“alipay python sdk”結果第一個就是,兩百多顆星,這意味著接下來的路平坦許多。
正文:
- Github上的
我接到的需求是做二維碼支付(不同於支付寶官方的當面付/APP支付/手機網站支付/電腦網站/支付/等),流程如下:
接收商品名稱資訊、訂單金額、訂單號 》》》請求“支付寶預付訂單建立介面”根據返回的URL生成二維碼》》》 使用者掃碼支付》》》一定時間內輪詢訂單狀態,若超時未支付則關閉訂單。
操作(二維碼支付):
pip install python-alipay-sdk --upgrade
from alipay import AliPay import time,qrcode alipay_public_key_string = '''-----BEGIN PUBLIC KEY----- YOUR_ALIPAY_PUBLIC_KEY -----END PUBLIC KEY-----''' app_private_key_string = '''-----BEGIN RSA PRIVATE KEY----- YOUR_APP_PRIVATE_KEY -----END RSA PRIVATE KEY-----''' #注意:一個是支付寶公鑰,一個是應用私鑰 APP_ID = '2018052160210122' NOTIFY_URL = "https://your_domain/alipay_callback" def init_alipay_cfg(): ''' 初始化alipay配置 :return: alipay 物件 ''' alipay = AliPay( appid=APP_ID, app_notify_url=NOTIFY_URL, # 預設回撥url app_private_key_string=app_private_key_string, alipay_public_key_string=alipay_public_key_string, # 支付寶的公鑰,驗證支付寶回傳訊息使用,不是你自己的公鑰, sign_type="RSA2", # RSA 或者 RSA2 debug = False # 預設False ,若開啟則使用沙盒環境的支付寶公鑰 ) return alipay def get_qr_code(code_url): ''' 生成二維碼 :return None ''' #print(code_url) qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=10, border=1 ) qr.add_data(code_url) # 二維碼所含資訊 img = qr.make_image() # 生成二維碼圖片 img.save(r'C:\Users\SEEMORE\Desktop\qr_test_ali.png') print('二維碼儲存成功!') def preCreateOrder(subject:'order_desc' , out_trade_no:int, total_amount:(float,'eg:0.01')): ''' 建立預付訂單 :return None:表示預付訂單建立失敗 [或] code_url:二維碼url ''' result = init_alipay_cfg().api_alipay_trade_precreate( subject=subject, out_trade_no=out_trade_no, total_amount=total_amount) print('返回值:',result) code_url = result.get('qr_code') if not code_url: print(result.get('預付訂單建立失敗:','msg')) return else: get_qr_code(code_url) #return code_url def query_order(out_trade_no:int, cancel_time:int and 'secs'): ''' :param out_trade_no: 商戶訂單號 :return: None ''' print('預付訂單已建立,請在%s秒內掃碼支付,過期訂單將被取消!'% cancel_time) # check order status _time = 0 for i in range(10): # check every 3s, and 10 times in all print("now sleep 2s") time.sleep(2) result = init_alipay_cfg().api_alipay_trade_query(out_trade_no=out_trade_no) if result.get("trade_status", "") == "TRADE_SUCCESS": print('訂單已支付!') print('訂單查詢返回值:',result) break _time += 2 if _time >= cancel_time: cancel_order(out_trade_no,cancel_time) return def cancel_order(out_trade_no:int, cancel_time=None): ''' 撤銷訂單 :param out_trade_no: :param cancel_time: 撤銷前的等待時間(若未支付),撤銷後在商家中心-交易下的交易狀態顯示為"關閉" :return: ''' result = init_alipay_cfg().api_alipay_trade_cancel(out_trade_no=out_trade_no) #print('取消訂單返回值:', result) resp_state = result.get('msg') action = result.get('action') if resp_state=='Success': if action=='close': if cancel_time: print("%s秒內未支付訂單,訂單已被取消!" % cancel_time) elif action=='refund': print('該筆交易目前狀態為:',action) return action else: print('請求失敗:',resp_state) return def need_refund(out_trade_no:str or int, refund_amount:int or float, out_request_no:str): ''' 退款操作 :param out_trade_no: 商戶訂單號 :param refund_amount: 退款金額,小於等於訂單金額 :param out_request_no: 商戶自定義引數,用來標識該次退款請求的唯一性,可使用 out_trade_no_退款金額*100 的構造方式 :return: ''' result = init_alipay_cfg().api_alipay_trade_refund(out_trade_no=out_trade_no, refund_amount=refund_amount, out_request_no=out_request_no) if result["code"] == "10000": return result #介面呼叫成功則返回result else: return result["msg"] #介面呼叫失敗則返回原因 def refund_query(out_request_no:str, out_trade_no:str or int): ''' 退款查詢:同一筆交易可能有多次退款操作(每次退一部分) :param out_request_no: 商戶自定義的單次退款請求識別符號 :param out_trade_no: 商戶訂單號 :return: ''' result = init_alipay_cfg().api_alipay_trade_fastpay_refund_query(out_request_no, out_trade_no=out_trade_no) if result["code"] == "10000": return result #介面呼叫成功則返回result else: return result["msg"] #介面呼叫失敗則返回原因 if __name__ == '__main__': cancel_order(1527212120) subject = "話費餘額充值" out_trade_no =int(time.time()) total_amount = 0.01 preCreateOrder(subject,out_trade_no,total_amount) query_order(out_trade_no,40) print('5s後訂單自動退款') time.sleep(5) print(need_refund(out_trade_no,0.01,111)) print('5s後查詢退款') time.sleep(5) print(refund_query(out_request_no=111, out_trade_no=out_trade_no)) #操作完登入 https://authsu18.alipay.com/login/index.htm中的對賬中心檢視是否有一筆交易生成並退款
下面是支付寶介面呼叫成功的response示例:
官文:https://docs.open.alipay.com/api_1/ 建立預付訂單返回值: {'code': '10000', 'msg': 'Success', 'out_trade_no': '1527214200', 'qr_code': 'https://qr.alipay.com/bax09560qqw1epttm5i8006e'} 取消訂單返回值示例: {'code': '10000', 'msg': 'Success', 'action': 'close'(交易已取消), 'out_trade_no': '1527212120', 'retry_flag': 'N', 'trade_no': '2018052521001004480221282310'} 訂單查詢返回值: {'code': '10000', 'msg': 'Success', 'buyer_logon_id': 'cha***@icloud.com', 'buyer_pay_amount': '0.01', 'buyer_user_id': '2088012915825485', 'fund_bill_list': [{'amount': '0.01', 'fund_channel': 'ALIPAYACCOUNT'}], 'invoice_amount': '0.01', 'out_trade_no': '1527217434', 'point_amount': '0.00', 'receipt_amount': '0.01', 'send_pay_date': '2018-05-25 11:04:08', 'total_amount': '0.01', 'trade_no': '2018052521001004480221487538', 'trade_status': 'TRADE_SUCCESS'} 退款返回值示例: {'code': '10000', 'msg': 'Success', 'buyer_logon_id': 'cha***@icloud.com', 'buyer_user_id': '2088012915825485', 'fund_change': 'Y', 'gmt_refund_pay': '2018-05-25 10:08:05', 'out_trade_no': '1527211312', 'refund_detail_item_list': [{'amount': '0.01', 'fund_channel': 'ALIPAYACCOUNT'}], 'refund_fee': '0.01', 'send_back_fee': '0.01', 'trade_no': '2018052521001004480221209563'} 退款查詢返回值示例: {'code': '10000', 'msg': 'Success', 'out_request_no': '111', 'out_trade_no': '1527216203', 'refund_amount': '0.01', 'total_amount': '0.01', 'trade_no': '2018052521001004480221450113'} '''
-有用可以點個贊-