想要解決支付掉單問題?這有兩種系統(tǒng)設(shè)計方案

3 評論 9751 瀏覽 38 收藏 10 分鐘

編輯導(dǎo)語:在訂單支付的過程中,我們常常會遇到這樣的問題:明明付了錢,也扣了款,但是訂單卻并沒有成功。上文中,作者為我們分享了一次解決方案。在本篇文章中,作者又結(jié)合實際情況和案例,總結(jié)出了兩種系統(tǒng)設(shè)計方案。

上次在文章《錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案》提到,支付過程會出現(xiàn)「掉單、卡單」的情況,這種情況對于用戶來講,體驗非常差,明明自己付了錢,扣了款,但是訂單卻未成功。

上篇文章我們簡單說了下解決方案,這次小黑哥就結(jié)合生產(chǎn)實際碰到的情況,給出兩種詳細(xì)設(shè)計的方案:

  1. 定時輪詢補償方案
  2. 延遲消息補償方案

大家可以根據(jù)自己系統(tǒng)的實際情況,選擇性參考。

「當(dāng)然了,以下設(shè)計方案可能并不完美,如果各位讀者還有其他解決方案,歡迎留言指出,一起討論,一起成長~」

一、定時輪詢補償方案

1. 整體流程

這個方案主要采用定時任務(wù),批量查詢掉單記錄,從而驅(qū)動查詢具體支付支付結(jié)果,然后更新內(nèi)部訂單。

整體方案流程圖如下:

定時任務(wù)補償

定時任務(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ù)輪詢方案天然會存在以下不足:

  1. 「輪詢效率稍低」;
  2. 每次查詢數(shù)據(jù)庫,已經(jīng)被執(zhí)行過記錄,仍然會被掃描(補單程序?qū)鶕?jù)一定策略決定是否發(fā)起支付通道查詢),有「重復(fù)計算」的嫌疑;
  3. 「時效性不夠好」,如果每小時輪詢一次,最差的情況下,時間誤差會達到1小時;
  4. 如果為了解決時效性問題,增加定時任務(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ù)姆桨?,解決該問題,異步補償方案可以采用如下兩種:

  1. 定時輪詢補償方案
  2. 延遲消息補償方案

定時輪詢補償方案實現(xiàn)起來比較簡單,但是時效性稍差。而延遲消息補償方案總體來說比較優(yōu)秀,但是實現(xiàn)起來比較復(fù)雜。如果沒有自定義的延遲時間的需求,可以直接采用 RocketMQ 延遲消息,簡單快捷。

另外「延遲隊列」使用場景還是比較多,不僅僅能用在掉單補償上,還可以用于支付關(guān)單等場景。所以有能力開發(fā)的團隊,可以開發(fā)一個通用的延遲隊列。

歷史支付文章推薦:

1.?“輕輕一掃,立刻扣款”,解讀付款碼背后的原理

2.?產(chǎn)品設(shè)計:解讀銀行卡支付背后的原理

3.?手機沒網(wǎng)了,卻還能支付,這是什么原理?

4.?錢被扣走了,但是訂單卻未成功!支付掉單異常最全解決方案

5.?一筆訂單,但是誤付了兩筆錢!這種重復(fù)付款異常到底該如何解決?

 

作者:樓下小黑哥;微信公號@程序通事,支付行業(yè),后端技術(shù)

本文由 @樓下小黑哥 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載

題圖來自Unsplash,基于CC0協(xié)議

更多精彩內(nèi)容,請關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號或下載App
評論
評論請登錄
  1. “支付掉單異常解決方案”文章鏈接錯了

    回復(fù)
  2. 看完啦,我猜是后臺技術(shù)果然,我是支付產(chǎn)品,向您學(xué)習(xí)!

    來自廣東 回復(fù)
    1. 哈哈,是的。

      來自浙江 回復(fù)