想要解決支付掉單問題?這有兩種系統設計方案

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

想要解決支付掉單問題?這有兩種系統設計方案

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

上篇文章我們簡單説了下解決方案,這次小黑哥就結合生產實際碰到的情況,給出兩種詳細設計的方案:

大家可以根據自己系統的實際情況,選擇性參考。

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

一、定時輪詢補償方案1. 整體流程

這個方案主要採用定時任務,批量查詢掉單記錄,從而驅動查詢具體支付支付結果,然後更新內部訂單。

整體方案流程圖如下:

想要解決支付掉單問題?這有兩種系統設計方案

定時任務補償

前三步流程沒什麼好説的,正常的支付流程,咱們針對後面幾步具體詳細説下。

第三步調用支付通道之後,如果支付通道端返回「支付受理成功或者支付處理中」,我們就需要調用第四步,將這類訂單插入掉單表。

如果支付直接成功了,那就正常流程返回即可。

複習一下,網關類支付,比如支付寶、微信支付、網銀支付,這種支付模式,支付通道僅僅返回支付受理成功,具體支付結果需要接收支付通道端的支付通知,這類支付我們將其稱為異步支付。

相應的還有同步支付,比如銀行卡支付,微信、支付寶代扣類支付,這類支付,同步就能返回支付結果。

第五步,補單應用將會定時查詢數據庫,批量查詢掉單記錄;第六步,補單應用使用線程池,多線程異步的方式發起掉單查詢;第七步,調用支付通道支付查詢接口。

重點來了,如果第七步支付結果查詢為以下狀態:

  • 「支付結果為扣款成功」
  • 「支付結果為明確失敗」
  • 「掉單記錄查詢達到最大次數」

「第八步就會刪除掉單記錄。」

最後,如果掉單查詢依舊還是處理中,那麼經過一定的延時之後,重複第五步,再次重新掉單補償,直到成功或者查詢到達最大次數。

2. 相關問題

「為什麼需要新建一張掉單表?不能直接使用支付訂單表,查詢未成功的訂單嗎?」

這個問題,實際上確實可以直接使用的支付訂單表,然後批量查詢當天未成功的訂單,補單程序發起支付查詢。

那為什麼需要新建一張掉單表?

主要是因為數據庫查詢效率問題,因為支付訂單表每天都會大量記錄新增,隨着時間,這張表記錄將會越來越多,越來越大。

「支付記錄越多,批量範圍查詢效率就會變低,查詢速度將會變慢。」

所以為了查詢效率,新建一張掉單表。這張表裏僅記錄支付未成功的訂單,所以數據量就會很小,那麼查詢效率就會很高。

另外,掉單表裏的記錄,不會被永久保存,只是臨時性。當支付結果查詢成功,或者支付結果明確失敗,再或者查詢次數到達規定最大次數,就會刪除掉單記錄。

「這就是第八步為什麼需要刪除掉單表的原因。」

如果需要保存每次掉單表查詢詳情,那麼這裏建議再新增一張掉單查詢記錄表,保存每一次的查詢記錄。針對這個方案,如果還有其他問題,歡迎留言。

3. 方案優缺點

定時輪詢補償方案,最大的優點可能就是系統架構方案比較簡單,比較容易實施,那麼這個方案的缺點主要在於「定時任務」上。定時任務輪詢方案天然會存在以下不足:

  1. 「輪詢效率稍低」;
  2. 每次查詢數據庫,已經被執行過記錄,仍然會被掃描(補單程序將會根據一定策略決定是否發起支付通道查詢),有「重複計算」的嫌疑;
  3. 「時效性不夠好」,如果每小時輪詢一次,最差的情況下,時間誤差會達到1小時;
  4. 如果為了解決時效性問題,增加定時任務查詢效率,那麼 1 中查詢效率跟 2 的重複計算問題將會更加明顯。
二、延遲消息補償方案

下面介紹另外一種掉單補償方案,延遲消息補償方案,這個方案整體流程與定時任務方案類似,最大區別可能在於,從一種「拉模式」變成一種「推模式」。

整體方案流程圖如下:

想要解決支付掉單問題?這有兩種系統設計方案

這個方案主要流程跟定時方案類似,主要區別在於第四步、第五步、第八步。

第四步的流程從插入掉單表變更為往「延遲隊列發送掉單消息」;第五步,補單程序接收掉單消息,然後觸發支付掉單查詢;第八步,如果第七步支付結果查詢為以下狀態:

  • 支付結果為扣款成功
  • 支付結果為明確失敗
  • 掉單記錄查詢達到最大次數

補單程序將會告知延遲隊列消費成功,延遲隊列將會刪除這條掉單消息。其他狀態將會告知消費失效,延遲隊列將會在一定延時之後,再次發送掉單消息,然後繼續重複第五步。

方案優缺點:

延遲消息的方案相對於定時輪詢方案來講:

不過延遲消息這種方案,需要基於「延遲隊列」,實現起來比較複雜,目前開源實現也比較少。

三、小結

支付掉單、卡單是支付過程中經常會碰到的事,我們可以採用異步補償的方案,解決該問題,異步補償方案可以採用如下兩種:

定時輪詢補償方案實現起來比較簡單,但是時效性稍差。而延遲消息補償方案總體來説比較優秀,但是實現起來比較複雜。如果沒有自定義的延遲時間的需求,可以直接採用 RocketMQ 延遲消息,簡單快捷。

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

歷史支付文章推薦:

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

2. 產品設計:解讀銀行卡支付背後的原理

3. 手機沒網了,卻還能支付,這是什麼原理?

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

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

作者:樓下小黑哥;微信公號@程序通事,支付行業,後端技術

本文由 @樓下小黑哥 原創發佈於人人都是產品經理。未經許可,禁止轉載

題圖來自Unsplash,基於CC0協議

版權聲明:本文源自 網絡, 於,由 楠木軒 整理發佈,共 2310 字。

轉載請註明: 想要解決支付掉單問題?這有兩種系統設計方案 - 楠木軒