想要解決支付掉單問題?這有兩種系統(tǒng)設(shè)計方案
編輯導(dǎo)語:在訂單支付的過程中,我們常常會遇到這樣的問題:明明付了錢,也扣了款,但是訂單卻并沒有成功。上文中,作者為我們分享了一次解決方案。在本篇文章中,作者又結(jié)合實際情況和案例,總結(jié)出了兩種系統(tǒng)設(shè)計方案。
上次在文章《錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案》提到,支付過程會出現(xiàn)「掉單、卡單」的情況,這種情況對于用戶來講,體驗非常差,明明自己付了錢,扣了款,但是訂單卻未成功。
上篇文章我們簡單說了下解決方案,這次小黑哥就結(jié)合生產(chǎn)實際碰到的情況,給出兩種詳細(xì)設(shè)計的方案:
- 定時輪詢補償方案
- 延遲消息補償方案
大家可以根據(jù)自己系統(tǒng)的實際情況,選擇性參考。
「當(dāng)然了,以下設(shè)計方案可能并不完美,如果各位讀者還有其他解決方案,歡迎留言指出,一起討論,一起成長~」
一、定時輪詢補償方案
1. 整體流程
這個方案主要采用定時任務(wù),批量查詢掉單記錄,從而驅(qū)動查詢具體支付支付結(jié)果,然后更新內(nèi)部訂單。
整體方案流程圖如下:
定時任務(wù)補償
前三步流程沒什么好說的,正常的支付流程,咱們針對后面幾步具體詳細(xì)說下。
第三步調(diào)用支付通道之后,如果支付通道端返回「支付受理成功或者支付處理中」,我們就需要調(diào)用第四步,將這類訂單插入掉單表。
如果支付直接成功了,那就正常流程返回即可。
復(fù)習(xí)一下,網(wǎng)關(guān)類支付,比如支付寶、微信支付、網(wǎng)銀支付,這種支付模式,支付通道僅僅返回支付受理成功,具體支付結(jié)果需要接收支付通道端的支付通知,這類支付我們將其稱為異步支付。
相應(yīng)的還有同步支付,比如銀行卡支付,微信、支付寶代扣類支付,這類支付,同步就能返回支付結(jié)果。
第五步,補單應(yīng)用將會定時查詢數(shù)據(jù)庫,批量查詢掉單記錄;第六步,補單應(yīng)用使用線程池,多線程異步的方式發(fā)起掉單查詢;第七步,調(diào)用支付通道支付查詢接口。
重點來了,如果第七步支付結(jié)果查詢?yōu)橐韵聽顟B(tài):
- 「支付結(jié)果為扣款成功」
- 「支付結(jié)果為明確失敗」
- 「掉單記錄查詢達到最大次數(shù)」
「第八步就會刪除掉單記錄。」
最后,如果掉單查詢依舊還是處理中,那么經(jīng)過一定的延時之后,重復(fù)第五步,再次重新掉單補償,直到成功或者查詢到達最大次數(shù)。
2. 相關(guān)問題
「為什么需要新建一張掉單表?不能直接使用支付訂單表,查詢未成功的訂單嗎?」
這個問題,實際上確實可以直接使用的支付訂單表,然后批量查詢當(dāng)天未成功的訂單,補單程序發(fā)起支付查詢。
那為什么需要新建一張掉單表?
主要是因為數(shù)據(jù)庫查詢效率問題,因為支付訂單表每天都會大量記錄新增,隨著時間,這張表記錄將會越來越多,越來越大。
「支付記錄越多,批量范圍查詢效率就會變低,查詢速度將會變慢?!?/p>
所以為了查詢效率,新建一張掉單表。這張表里僅記錄支付未成功的訂單,所以數(shù)據(jù)量就會很小,那么查詢效率就會很高。
另外,掉單表里的記錄,不會被永久保存,只是臨時性。當(dāng)支付結(jié)果查詢成功,或者支付結(jié)果明確失敗,再或者查詢次數(shù)到達規(guī)定最大次數(shù),就會刪除掉單記錄。
「這就是第八步為什么需要刪除掉單表的原因?!?/p>
如果需要保存每次掉單表查詢詳情,那么這里建議再新增一張掉單查詢記錄表,保存每一次的查詢記錄。針對這個方案,如果還有其他問題,歡迎留言。
3. 方案優(yōu)缺點
定時輪詢補償方案,最大的優(yōu)點可能就是系統(tǒng)架構(gòu)方案比較簡單,比較容易實施,那么這個方案的缺點主要在于「定時任務(wù)」上。定時任務(wù)輪詢方案天然會存在以下不足:
- 「輪詢效率稍低」;
- 每次查詢數(shù)據(jù)庫,已經(jīng)被執(zhí)行過記錄,仍然會被掃描(補單程序?qū)鶕?jù)一定策略決定是否發(fā)起支付通道查詢),有「重復(fù)計算」的嫌疑;
- 「時效性不夠好」,如果每小時輪詢一次,最差的情況下,時間誤差會達到1小時;
- 如果為了解決時效性問題,增加定時任務(wù)查詢效率,那么 1 中查詢效率跟 2 的重復(fù)計算問題將會更加明顯。
二、延遲消息補償方案
下面介紹另外一種掉單補償方案,延遲消息補償方案,這個方案整體流程與定時任務(wù)方案類似,最大區(qū)別可能在于,從一種「拉模式」變成一種「推模式」。
整體方案流程圖如下:
這個方案主要流程跟定時方案類似,主要區(qū)別在于第四步、第五步、第八步。
第四步的流程從插入掉單表變更為往「延遲隊列發(fā)送掉單消息」;第五步,補單程序接收掉單消息,然后觸發(fā)支付掉單查詢;第八步,如果第七步支付結(jié)果查詢?yōu)橐韵聽顟B(tài):
- 支付結(jié)果為扣款成功
- 支付結(jié)果為明確失敗
- 掉單記錄查詢達到最大次數(shù)
補單程序?qū)嬷舆t隊列消費成功,延遲隊列將會刪除這條掉單消息。其他狀態(tài)將會告知消費失效,延遲隊列將會在一定延時之后,再次發(fā)送掉單消息,然后繼續(xù)重復(fù)第五步。
方案優(yōu)缺點:
延遲消息的方案相對于定時輪詢方案來講:
- 無需再查詢?nèi)坑唵?/li>
- 效率高時效性較好
不過延遲消息這種方案,需要基于「延遲隊列」,實現(xiàn)起來比較復(fù)雜,目前開源實現(xiàn)也比較少。
三、小結(jié)
支付掉單、卡單是支付過程中經(jīng)常會碰到的事,我們可以采用異步補償?shù)姆桨?,解決該問題,異步補償方案可以采用如下兩種:
- 定時輪詢補償方案
- 延遲消息補償方案
定時輪詢補償方案實現(xiàn)起來比較簡單,但是時效性稍差。而延遲消息補償方案總體來說比較優(yōu)秀,但是實現(xiàn)起來比較復(fù)雜。如果沒有自定義的延遲時間的需求,可以直接采用 RocketMQ 延遲消息,簡單快捷。
另外「延遲隊列」使用場景還是比較多,不僅僅能用在掉單補償上,還可以用于支付關(guān)單等場景。所以有能力開發(fā)的團隊,可以開發(fā)一個通用的延遲隊列。
歷史支付文章推薦:
2.?產(chǎn)品設(shè)計:解讀銀行卡支付背后的原理
4.?錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案
5.?一筆訂單,但是誤付了兩筆錢!這種重復(fù)付款異常到底該如何解決?
作者:樓下小黑哥;微信公號@程序通事,支付行業(yè),后端技術(shù)
本文由 @樓下小黑哥 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載
題圖來自Unsplash,基于CC0協(xié)議
“支付掉單異常解決方案”文章鏈接錯了
看完啦,我猜是后臺技術(shù)果然,我是支付產(chǎn)品,向您學(xué)習(xí)!
哈哈,是的。