1、定義
- 同步調用:當一個支付請求被發送到支付渠道方,支付渠道會很快返回一個結果。但是這個結果,只是告訴你調用成功了,不是扣款成功,這叫同步調用;
- 異步調用:同步請求參數里面會有一個回調地址,這個地址是支付渠道在扣款成功后調用的,這叫異步調用;
- 當一個支付請求被發送到支付渠道方,支付渠道會很快返回一個結果。但是這個結果,只是告訴你調用成功了,不是扣款成功,這叫同步調用。很多新手會拿這個結果當作支付成功了,那就會被坑死,結果就是支付成功率特別高,伴隨着一堆無法解釋的壞賬率,測試人員尤其要注意測試數據的篡改:金額,同步返回結果,訂單號等。
- 同步請求參數里面會有一個回調地址,這個地址是支付渠道在扣款成功后調用的,這叫異步調用。一般同步接口僅檢查參數是否正確,簽名是否無誤等。異步接口才告訴你扣款結果。一般異步接口有5秒以內的延遲。調用不成功會重試。有時候是這邊成功了,但支付渠道側沒收到返回,於是會繼續調。當天的支付到第二天還在被異步調用也都是正常的。這也是開發人員需要特別注意的地方,不要當做重復支付。測試人員也要對重復回調進行測試,應只有一次有效。這還不是最坑的,一般支付渠道側,只有支付成功了才通知你。要是支付失敗了,壓根兒都不告訴你。 另一方面,如何老收不到異步結果呢?那就得查查了。同步結果不可靠,異步調用不可靠,那怎么確定支付結果?最終的殺招就是查單了,反查,一般支付渠道側都會提供反查接口,定時獲取DB中待支付的訂單調用支付渠道側的反查接口,最終把支付渠道側扣款成功的訂單完成掉。
- "同步" 就好比:你去外地上學(人生地不熟),突然生活費不夠了;此時你決定打電話回家,通知家里轉生活費過來,可是當你撥出電話時,對方一直處於待接聽狀態(即:打不通,聯系不上),為了拿到生活費,你就不停的 oncall 、等待,最終可能不能及時要到生活費,導致你今天要做的事都沒有完成,而白白花掉了時間。
- "異步" 就是:在你打完電話發現沒人接聽時,猜想:對方可能在忙,暫時無法接聽電話,所以你發了一條短信(或者語音留言,亦或是其他的方式)通知對方后便忙其他要緊的事了;這時你就不需要持續不斷的撥打電話,還可以做其他事情;待一定時間后,對方看到你的留言便回復響應你,當然對方可能轉錢也可能不轉錢。但是整個一天下來,你還做了很多事情。 或者說你找室友臨時借了一筆錢,又開始 happy 的上學時光了。
- 簡而言之,言而總之: 同步就是我強依賴你(對方),我必須等到你的回復,才能做出下一步響應。即我的操作(行程)是順序執行的,中間少了哪一步都不可以,或者說中間哪一步出錯都不可以,類似於編程中程序被解釋器順序執行一樣;同時如果我沒有收到你的回復,我就一直處於等待、也就是阻塞的狀態。 異步則相反,我並不強依賴你,我對你響應的時間也不敏感,無論你返回還是不返回,我都能繼續運行;你響應並返回了,我就繼續做之前的事情,你沒有響應,我就做其他的事情。也就是說我不存在等待對方的概念,我就是非阻塞的。
4、Python 模擬測試異步接口
# order 下單接口: url = localhost:1234/order/create method = post body = { "goodsId":"102030", "userId":"6666", "num":10, "amount":100 } response = { "code":"0000", "msg":"sucess", "data":{ "order":"dcs123456789", "locator":"/order/get_result/" }}
# getOrder 查詢訂單接口: url = localhost:1234/order/get_result?orderId=dcs123456789 method = get response = { "code":"0000", "msg":"sucess", "data":{ "order":"dcs123456789", "status": 1, "desc": "下單成功", "goodsId":"102030", "userId":"6666", "num":10, "amount":100 }}
import time import requests def create_order(): url = "http://localhost:1234/order/create" # 異步接口 data = { "goodsId":"102030", "userId":"6666", "num":10, "amount":100 } res = requests.post(url=url, json=data) return res.json().get("data").get("order") # 返回order_id用於追蹤 def get_order_result(interval=1, time_out=10): # 設置了默認時間間隔和超時時間,可以修改 order_id = create_order() # 查詢結果接口 url = "http://localhost:1234/order/get_result?orderId={}".format("2423432") start_time = time.time() # 啟動時間 end_time = start_time + time_out #啟動時間 + 超時時間 = 結束時間 count = 1 # 計數器, 此處是為了顯示更直觀, 可以去掉 while time.time() < end_time: # 當未到結束時間時, 循環請求 res = requests.get(url) # 請求查詢結果接口 print(count) count += 1 time.sleep(interval) # 休眠指定時間 if res: # 如果有數據則退出循環 break else: return None # 正常退出(達到end_time, 非break退出) 返回None return res.json() # break退出返回 接口數據 if __name__ == '__main__': # print(create_order()) print(get_order_result())