1.字段概念
APPID:收款賬號既是您的APPID對應支付寶賬號 商戶私鑰 merchant_private_key,您的PKCS8格式RSA2私鑰 支付寶公鑰 alipay_public_key,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應 APPID下的支付寶公鑰 服務器異步通知頁面路徑 notify_url post 頁面跳轉同步通知頁面路徑 return_url get 簽名方式 sign_type = "RSA2" 沙箱網關 gatewayUrl ="https://openapi.alipaydev.com/gateway.do"
2.同步回調與異步回調
同步回調:把函數b傳遞給函數a。執行a的時候,回調了b,a要一直等到b執行完才能繼續執行;
異步回調:把函數b傳遞給函數a。執行a的時候,回調了b,然后a就繼續往后執行,b獨自執行。
異步回調指的是:在發起一個異步任務的同時指定一個函數,在異步任務完成時會自動的調用這個函數。
通常情況下,異步都會和回調函數一起使用,使用方法即是add_done_callback(),給Future對象綁定一個回調函數。
3.概述
當一個支付請求被發送到支付渠道方,支付渠道(支付寶同步回調向系統發送一個get請求)會很快返回一個結果。但是這個結果,只是告訴你調用成功了,不是扣款成功,這叫同步調用。
很多新手會拿這個結果 當作支付成功了,那就會被坑死,結果就是支付成功率特別高,伴隨着一堆無法解釋的壞賬率,
測試人員尤其要注意測試數據的篡改:金額,同步返回結果,訂單號等。
同步請求參數里面會有一個回調地址,這個地址是支付渠道在扣款成功后調用的,這叫異步調用。
一般同步接口僅檢查參數是否正確,簽名是否無誤等。異步接口才告訴你扣款結果。
一般異步接口有5秒以內的延遲。調用不成功會重試。有時候是這邊成功了,但支付渠道側沒收到返回,於是會繼續調。
當天的支付到第二天還在 被異步調用也都是正常的。這也是開發人員需要特別注意的地方,不要當做重復支付。
測試人員也要對重復回調進行測試,應只有一次有效。這還不是最坑的,一般 支付渠道側,只有支付成功了才通知你。
要是支付失敗了,壓根兒都不告訴你。
另一方面,如何老收不到異步結果呢?那就得查查了。同步結果不可靠,異步調用不可靠,那怎么確定支付結果?最終的殺招就是查單了,
反查,一般支付渠道側都 會提供反查接口,定時獲取DB中待支付的訂單調用支付渠道側的反查接口,最終把支付渠道側扣款成功的訂單完成掉。
4.第三方支付過程分析
1)支付接口(需要登錄認證:是誰):前台提交商品等信息,得到支付鏈接(或二維碼) post方法 分析:支付寶回調 同步:支付寶get給前台 => 前台可以在收到支付寶同步get回調時,前台ajax異步在給消息同步給后台,也采用get,后台處理前台的get請求 異步:post給后台 => 后台直接處理支付寶的post請求 2)支付回調接口(不需要登錄認證:哪個訂單(訂單信息中有非對稱加密)、支付寶壓根不可能有你的token): get方法:處理前台來的同步回調(不一定能收得到,所有不能在該方法完成后台訂單狀態等信息操作) post方法:處理支付寶來的異步回調 3)訂單狀態確認接口:隨你前台任何時候來校驗訂單狀態的接口
5.第三方支付寶接口實現過程
1.支付寶開放平台
https://open.alipay.com/platform/home.htm
2. alipay六大接口
3. alipay.trade.page.pay
非對稱加密:公鑰簽發加密,私鑰解密
開發助手生成本地應用公鑰私鑰
拿生成的本地應用公鑰生成阿里雲公鑰
基於python alipay SDK 應用私鑰 支付寶公鑰
生成支付對象 alipay 包含商戶的應用私鑰(2048個字節)只有商戶自己知道,支付寶公鑰
調用對象alipay的方法 apipay.api_alipay_trade_page_pay 方法生成支付連接二維碼頁面
輸入pay_url 即可
同步回調頁面
二次封裝 其它寫道公共方法和配置文件
店員動作:生成支付碼
過程:生成支付連接(網關+字符串)==> 向支付寶發送get請求獲得支付二維碼頁面
接口1:向后台發送訂單信息,獲取支付連接()
參數: 訂單號,總金額,商品,(同步回調地址,異步回調地址 在配置文件中讀取,接口中無此參數)
接口2: 向支付寶發送get請求,獲取支付頁面
生成連接分析:
https://openapi.alipaydev.com/gateway.do?參數1=...&參數2=...&sign_type=RSA2&sign=mZsBK....(很長)
說簡單點即是:支付寶網關?必要的參數&簽名參數
商戶私鑰
參考此博客 驗簽
用戶動作:掃碼支付
1.前奏:
訂單模塊表分析
1)支付接口(需要登錄認證:是誰):前台提交商品等信息,得到支付鏈接(或二維碼) post方法
發起支付 分析:支付寶回調 同步:支付寶get給前台 => 前台可以在收到支付寶同步get回調時,前台ajax異步在給消息同步給后台,也采用get,后台處理前台的get請求 異步:post給后台 => 后台直接處理支付寶的post請求 2)支付回調接口(不需要登錄認證:哪個訂單(訂單信息中有非對稱加密)、支付寶壓根不可能有你的token): get方法:處理前台來的同步回調(不一定能收得到,所有不能在該方法完成后台訂單狀態等信息操作) post方法:處理支付寶來的異步回調 3)訂單狀態確認接口:隨你前台任何時候來校驗訂單狀態的接口
支付接口
支付回調接口
1.支付寶同步回調接口
return_url + 回調參數
回調參數
` charset=utf-8& out_trade_no=7f7c7d12d57d45b693e1b49a6b01e1dd& method=alipay.trade.page.pay.return& total_amount=39.00& sign=FUmceqiNMWvxcD%2BUPCHiOTaEwlJ%2FXIXL5UwZWOSI1TwRjPIZVzjRLB4j2G5CQpn472JO8X%2BwMx04dHqjLxqLcY3TRu0XurQ%2FwKTNpyfDrtNuNv0rfGPuVHw52y3blbS7%2FKFVsWryw4%2BBuF2fCrJ4qWH8Zg14Rct7qoMbu73N74WkQtDyzXefiKDbkMMRMfLbelE9TFyeIeygeMId8%2B58mcJMUOh6aQqwpr9bzuBbfJ17fkqU%2F0ys9zGr%2FlDtLL7aAh6BPViqZN%2F9T7byCoferD1BhcSzJNR6V6VuhOdTq8iEaH2XgJT9aIiyHgg3GT1taBBvZX2gK41FSmkguk%2BfsA%3D%3D& trade_no=2020030722001464020500585462& auth_app_id=2016093000631831& version=1.0& app_id=2016093000631831& sign_type=RSA2& seller_id=2088102177958114& timestamp=2020-03-07%2014%3A47%3A48 ` // 同步回調沒與訂單狀態
return_url 返回的字段信息解析到界面 顯示購買成功,此時並沒有回調訂單狀態,所以不能以此判斷支付成功
同步回調異步回調處理
* 第一步:驗證簽名,簽名通過后進行第二步 * 第二步:按一下步驟進行驗證 * 1、商戶需要驗證該通知數據中的out_trade_no是否為商戶系統中創建的訂單號, * 2、判斷total_amount是否確實為該訂單的實際金額(即商戶訂單創建時的金額), * 3、校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方
(有的時候,一個商戶可能有多個seller_id/seller_email), * 4、驗證app_id是否為該商戶本身。上述1、2、3、4有任何一個驗證不通過,則表明本次通知是異常通知,務必忽略。 * 在上述驗證通過后商戶必須根據支付寶不同類型的業務通知,正確的進行不同的業務處理,並且過濾重復的通知結果數據。 * 在支付寶的業務通知中,只有交易通知狀態為TRADE_SUCCESS或TRADE_FINISHED時,支付寶才會認定為買家付款成功。
測試分析: 驗簽只能說明支付寶給你的數據沒有問題,支付寶只認訂單號
1.直接修改支付寶post接口數據,驗簽則無法通過,那么數據是否可以在前面的步驟中修改
2. 在生成支付二位碼的時候修改支付數量,金額,訂單號(不存在,重復),那么異步回調時候你就要效驗訂單,金額了
3.如果使用別的商戶私鑰和公鑰去生成支付二維碼,那么這時候異步回調的時候你就要效驗appid(商戶id)
4.在生成支付二維碼,填入非法字段,不存在的,或者trade_status in ("TRADE_SUCCESS", "TRADE_FINISHED")
5.並發單號會不會重復 :如果做了服務器集群,考慮使用分布式鎖,鎖住outTradeNo后再處理業務,不然有可能重復處理
6.服務器弱網斷網: 支付寶一天8次異步回調
from utils.logging import logger # 支付回調接口 class SuccessViewSet(ViewSet): authentication_classes = () permission_classes = () # 支付寶同步回調給前台,在同步通知給后台處理 def get(self, request, *args, **kwargs): # return Response('后台已知曉,Over!!!') # 不能在該接口完成訂單修改操作 # 但是可以在該接口中校驗訂單狀態(已經收到支付寶post異步通知,訂單已修改),告訴前台 # print(type(request.query_params)) # django.http.request.QueryDict # print(type(request.query_params.dict())) # dict out_trade_no = request.query_params.get('out_trade_no') try: #去數據判斷有此訂單,且此訂單狀態為1 models.Order.objects.get(out_trade_no=out_trade_no, order_status=1) return APIResponse(result=True) except: return APIResponse(1, 'error', result=False) # 支付寶異步回調處理 def post(self, request, *args, **kwargs): try: result_data = request.data.dict() out_trade_no = result_data.get('out_trade_no') signature = result_data.pop('sign') from libs import iPay # 先把返回的字符串用explode()解析成數組,去掉多余的數組元素,然后在用支付寶給你們約定的加密
# 方法重新加密一次,然后在把加密出來的字符串重新和你的sign匹配一下 result = iPay.alipay.verify(result_data, signature) if result and result_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"): # 完成訂單修改:訂單狀態、流水號、支付時間 models.Order.objects.filter(out_trade_no=out_trade_no).update(order_status=1) # 完成日志記錄 logger.warning('%s訂單支付成功' % out_trade_no) return Response('success') else: logger.error('%s訂單支付失敗' % out_trade_no) except: pass return Response('failed')
支付寶同步驗簽 與 異步驗簽
6.第三方支付並發數據一致性問題
第三方支付同步和異步回調並發數據一致性的問題 在第三方交易系統中的支付場景下,一般的步驟是,用戶在系統產生訂單,支付系統向第三方發起支付請求創建支付訂單,用戶跳轉至第三方系統進行支付,
支付完成后會產生 同步回調 和 異步回調。系統一般根據 第三方異步回調 來確認本次交易結果 特殊業務場景 由於目前存在特殊的業務場景,本次交易結果必須依賴前端的 同步回調 請求來決定用戶是否能進入下一步的產品交付場景。簡單來說,在特殊的業務場景下,
必須依賴 同步回調 的結果來判定本次交易狀態 並發一致性問題 當同步回調和異步回調同時發生的時候,由於實現細節的不同,兩個流程需要將訂單狀態分別流轉到不同的狀態,由於查詢數據庫使用的是快照讀,
在某一個流程中修改狀態的事務未提交的時候,查詢到這條記錄一樣的事務提交之前的狀態,所以會存在數據沒有被流轉到正確的處理狀態 原因 在 A B 事務並發的情況下,A B 兩個事務都依賴同一行數據中數據字段的狀態進行下一步的操作,當 A 事務決定將狀態更新到 x 時的事務還未提交的時候,
B 查詢到的數據狀態和 A 事務是相同的,導致 B 事務會將數據字段更新到 y 導致數據結果和預期不一致 解決方式 事務 + 當前讀 保證兩個業務的查詢,更新都在一個事務中,且使用當前讀查詢數據的最新狀態 利用分布式鎖串行化接口 由於業務強依賴同步回調,所以將同步回調與異步回調串行,使同步回調保持在異步回調之前,異步回調在同步回調請求未產生之前不進行處理 第三方異步回調返回問題 由於第三方依賴異步回調的結果來分析我方業務是否正常,如果在異步場景下直接返回異常那么在第三方的業務系統中會存在大量錯誤,這是我們不希望看到的。 由於不強依賴第三方的異步回調,系統可以使用消息中間件將回調消息收取,返回第三方正常,利用消息 + Job 腳本的方式對數據沒有正常流轉的訂單進行補償重試