如何理解pos機訂單支付,基于有限狀態(tài)機與消息隊列的三方支付系統(tǒng)補單實踐

 新聞資訊2  |   2023-05-25 09:37  |  投稿人:pos機之家

網(wǎng)上有很多關(guān)于如何理解pos機訂單支付,基于有限狀態(tài)機與消息隊列的三方支付系統(tǒng)補單實踐的知識,也有很多人為大家解答關(guān)于如何理解pos機訂單支付的問題,今天pos機之家(m.afbey.com)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!

本文目錄一覽:

1、如何理解pos機訂單支付

如何理解pos機訂單支付

0.引言

在日常生活中,從線下的超市購物到線上的外賣點餐、電商網(wǎng)購等,支付無時無刻不在發(fā)生,不論是通過現(xiàn)金、pos 機刷卡還是微信支付寶等第三方支付。線上支付有著及時便捷一氣呵成的極致體驗,當然也有少數(shù)的時候體驗不夠絲滑,比如早期我們在 PC 版 12306 買火車票,當支付完成后,訂單的支付狀態(tài)卻經(jīng)常不能及時更新,會有一段時間的延遲,有時甚至?xí)却荛L時間處在未支付狀態(tài)。

在支付的過程中由于各種各樣的原因(比如外部渠道處理出了問題,異步回調(diào)遲遲不來)導(dǎo)致流程走了一半停了下來,用戶看到訂單依然是未支付狀態(tài),會不知所措,此時就需要一種機制來推動完成這筆交易。本文就以三方支付系統(tǒng)中的補單機制為例,來介紹一種較為通用的單據(jù)補償模式。

1.三方支付系統(tǒng)簡介1.1 什么是三方支付

所謂第三方支付,就是和各大銀行簽約,獨立于商戶和銀行,具備一定實力和信譽保障的,為商戶與消費者提供支付結(jié)算服務(wù)的第三方獨立機構(gòu)。它是處于買方和賣方之間具備公信力的第三方,承擔擔保人和資金托管人的角色。三方支付也可以稱為虛擬賬戶支付,由消費者在第三方支付機構(gòu)開設(shè)虛擬賬戶,并用虛擬賬戶中的資金進行支付。業(yè)界常見的三方支付有支付寶、微信支付、美團支付、京東支付等等。

1.2 三方支付中的交易&支付系統(tǒng)

交易是什么,最直觀的描述就是“一手交錢、一手交貨” ,交易會使買賣雙方形成債權(quán)和債務(wù)關(guān)系。交易的存在是支付發(fā)生的前提,用戶通過使用某種支付方式去完成交易。交易是支付流程的驅(qū)動者,根據(jù)具體場景組合不同的支付指令,來完成交易資金的轉(zhuǎn)移。

支付是交易處理資金流的工具,目的是清償債權(quán)和債務(wù)關(guān)系;支持多種支付方式(如銀行卡支付、余額支付、優(yōu)惠券組合支付、類似花唄的信用支付等),負責(zé)對接賬務(wù)、會計、計費系統(tǒng)等資金處理能力,接收支付指令,驅(qū)動完成資金交換。將實際的支付行為(實際資金)與內(nèi)部的記賬(虛擬資金)相結(jié)合,保證虛實一致。

三方支付整體業(yè)務(wù)架構(gòu)如圖 1 所示,其中交易核心與支付核心在業(yè)務(wù)劃分上處于"收單支付域",具備普通交易的收款、付款、退款及充值、轉(zhuǎn)賬與提現(xiàn)等常見功能,還包括了支撐電商業(yè)務(wù)的合單支付、擔保與分賬的能力。其中交易與支付核心都有一個異常查補模塊,它囊括了所有業(yè)務(wù)的補償流程,也是本文主要介紹的部分。

圖 1. 三方支付業(yè)務(wù)架構(gòu)

2.什么是補單&為什么需要補單

一筆交易在支付過程中由于鏈路中的各種異常而中斷,此時的交易處在一種中間狀態(tài),這種情況俗稱"卡單",即卡在那里不動了,沒有繼續(xù)向下推進。還有一種情形,支付核心向渠道發(fā)起了扣款,渠道受理后,銀行卡扣款成功,但由于種種原因沒有向支付核心發(fā)起回調(diào),導(dǎo)致這筆支付沒有完成,用戶沒有享受到相應(yīng)權(quán)益,但銀行卡的錢已經(jīng)扣了,這種情況稱為“掉單”。

不管是卡單還是掉單,都是處在中間態(tài)的訂單。補單就是將處在中間態(tài)的訂單進行補償,直到推進到終態(tài)(成功或失?。?/strong>。補單一般有兩個關(guān)鍵點,一個是補償?shù)挠行?,極端情況下可能補償多次都不成功,不能就此放棄了,需要有兜底的機制;另一個是補償?shù)募皶r性,因為交易掛起的時間越長,用戶的體驗越差。

交易核心和支付核心的補單相得益彰,具有一定相似程度的設(shè)計與實現(xiàn),我們就以支付核心的補單為例介紹下異常補單機制。

3.補單是如何實現(xiàn)的

本章首先了解一下業(yè)務(wù)流程,說明一下實現(xiàn)補單需要的前提基礎(chǔ),然后介紹一下補單機制的演進路線,每個版本存在的問題以及在下一個版本是如何解決的。

3.1 有限狀態(tài)機與冪等性標識資金操作的有限狀態(tài)機

我們首先以用戶發(fā)起一筆余額提現(xiàn)為例,說明下業(yè)務(wù)流程,簡化后如圖 2 所示。

圖 2. 余額提現(xiàn)流程

首先生成支付訂單,然后請求賬務(wù)系統(tǒng),扣減用戶賬戶下的余額,接著向外部渠道發(fā)起付款操作,資金操作完成后統(tǒng)一處理結(jié)果并更新單據(jù)信息,最后還有一些對上下游的異步通知,形式上包括消息和 RPC 回調(diào)。

我們將每個關(guān)鍵資金操作的狀態(tài)記錄落庫,如下表所示。其中出款即錢從哪里來,入款即錢到哪里去,沖正即回滾交易。在提現(xiàn)場景下就是從用戶支付賬戶出錢,到用戶的銀行卡去。其他場景比如充值(銀行卡->用戶支付賬戶),會有不同的資金流向。表中最后兩行加粗的場景還沒有達到終態(tài),是我們需要去補償?shù)摹?/p>

為了便于理解,我們在這里省略了沖正的相關(guān)操作,一次余額提現(xiàn)流程的狀態(tài)機轉(zhuǎn)換如圖 3 所示。

圖 3.附帶狀態(tài)機轉(zhuǎn)換的余額提現(xiàn)流程

可重入與冪等性保證

發(fā)起一次支付會涉及到多個系統(tǒng)間調(diào)用,由于網(wǎng)絡(luò)原因?qū)е碌耐ㄐ懦瑫r是常見的問題。同時上游系統(tǒng)也可能會重新發(fā)起請求,這需要我們的系統(tǒng)保證操作結(jié)果的冪等性。少數(shù)用戶也可能會有多個終端同時操作帶來的并發(fā)請求,需要我們保證接口的可重入性。除了服務(wù)自身,我們的下游依賴同樣也需要保證其接口具有同樣的能力。

先說一說什么是可重入與冪等性。

可重入:在并發(fā)請求下可以保證正確性。冪等性:重復(fù)多次相同的輸入,獲得相同的輸出。冪等性在技術(shù)上其實也包含了可重入的要求。

具體到業(yè)務(wù)中,冪等性是針對一筆已經(jīng)到達終態(tài)的支付而言的,對于初次未能拿到最終業(yè)務(wù)結(jié)果的請求,再次發(fā)起調(diào)用的結(jié)果可以是不同的(處理中->處理成功或失?。?。那么我們?nèi)绾伪WC業(yè)務(wù)流程的可重入與冪等性呢?我們分別拆解每一步來看:

生成支付單:首先支付單據(jù)可以將業(yè)務(wù)方傳遞的可保證唯一性的外部訂單號作為唯一索引,插入數(shù)據(jù)庫時若發(fā)生唯一索引沖突,則將查詢已有數(shù)據(jù)進行冪等參數(shù)校驗,若與當次請求的參數(shù)完全一致說明是重復(fù)請求,可使用 DB 中的支付單繼續(xù)推進后續(xù)流程;若不一致則返回錯誤。資金處理流程:賬戶和渠道系統(tǒng)各自保證其接口冪等性。我們也維護了每個下游操作的狀態(tài),根據(jù)狀態(tài)機決定是否要繼續(xù)推進,盡量不向下游輸出重復(fù)流量。比如支付單已經(jīng)完成了所有資金處理,狀態(tài)機已經(jīng)是終態(tài),那么接口可以直接返回相應(yīng)結(jié)果。更新支付單信息,先將支付單加行級排他鎖,再進行更新,保證多個并發(fā)請求只會有一個成功。異步通知,在支付單推進到終態(tài)后進行。

有了可重入與冪等性保證,我們就可以大量地復(fù)用正向流程來實現(xiàn)補單接口。

3.2 初始版

一般來說最常見的補單形式是設(shè)置一個定時任務(wù),定時去掃表完成業(yè)務(wù)補償,實現(xiàn)比較簡單,但是及時性不夠,對于收款轉(zhuǎn)賬類的交易而言用戶體驗不佳。我們采用了通過消息隊列進行即時補償?shù)姆绞?,如圖 4 所示。補償消費者并沒有去做補償工作,而是解析消息然后通過 RPC 調(diào)用支付核心暴露的補償接口。為什么不在消費者中直接補償?這么做主要是考慮將邏輯收斂到一處便于維護。

圖 4. 余額提現(xiàn)發(fā)生異常時的補單流程

當然,補單可能依然失敗,我們可以再次發(fā)送補償消息。但不能一直這樣循環(huán)下去,所以需要設(shè)置一個最大重試次數(shù),超出后不再發(fā)送。當補償多次都不成功時,一般是下游系統(tǒng)出了問題,這時我們需要放緩補償?shù)念l次,隨著重試次數(shù)增加,會讓每次補償時間間隔逐漸增大,通過 RocketMQ 的延時消息實現(xiàn)。

這里有三個很容易想到的問題:

如果異常消息發(fā)送失敗,上游也沒有重試機制,這筆訂單就可能一直掛在這里不了了之了,如圖 5 所示。補償消費者請求支付核心補單時不成功,可能是超時但實際補償成功了,或者是請求壓根沒有過去,如圖 6 所示。如果重試達到最大次數(shù)依然沒有成功,這筆單子該怎么處理。

圖 5. 補償消息發(fā)送失敗

圖 6. 補償消息消費失敗

3.3 改進版

針對問題 1,如果重試依然發(fā)送失敗,我們通過引入一張異常消息表,將發(fā)送失敗的消息落庫來解決。表中記錄了訂單號、當前的重試次數(shù)、異常分類、記錄狀態(tài)、消息體等字段。如果圖 6 中的第 4 步消息發(fā)送失敗,就將這筆訂單放入 DB 中的一張異常表中,會設(shè)置一個定時任務(wù)去處理。以目前 RocketMQ 的可用性來說,異常數(shù)據(jù)很少會出現(xiàn)。如圖 7 所示。

圖 7. 針對消息生產(chǎn)/消費異常的改進版 - 1

對于第 2 個問題,如果補償消費者調(diào)用支付核心失敗,補償消費者 HandleMessage 會向上層拋出 error,利用 RocketMQ 的梯度重試機制,當消費重試次數(shù)達到一定上限后會進入死信隊列。如圖 8 所示,這種情況一般是服務(wù)或網(wǎng)絡(luò)出了問題,待恢復(fù)之后,可以從死信隊列拉取這些消息再統(tǒng)一處理。

圖 8. 針對消息生產(chǎn)/消費異常的改進版 - 2

當然還有更極端的情況,請求 MQ 和 DB 都失敗了咋辦?以目前 MQ 和 DB 的可用性來說,同時失敗這種基本可以不用考慮,報警人工介入即可。

針對問題 3,如果重試超過最大次數(shù),依然補償不成功,一般是下游依賴出了問題。這種情況我們也將它放進異常表中。

對于這兩類漏網(wǎng)之魚,需要支持單條/批量支付單補償?shù)倪\營能力以供人工介入;最好有一個在業(yè)務(wù)低峰期運行的兜底任務(wù),掃描業(yè)務(wù)單據(jù)表,將一段時間內(nèi)還未完成的訂單進行補償。

另外,兜底任務(wù)可能造成消息的短暫堆積,影響線上的實時補償流程推進,對此可以使用獨立的隊列隔離開來。

3.4 最終版

其實如果只是異步通知類的操作出現(xiàn)了異常,并沒有必要每次都重新走一遍完整業(yè)務(wù)流程,缺啥補啥即可。因此我們將異常劃分為多種類型,將一些異步操作和業(yè)務(wù)處理劃分開來,進行精細化的處理:

通知下游的 MQ 失敗,就將這個消息體重發(fā)一次即可;通知交易的回調(diào) RPC 失敗,可將 RPC 請求序列化到消息體中,補償時通過反序列化消息體中的 RPC 請求,直接再發(fā)起一次 RPC 即可;對于更新 DB 失敗,將更新參數(shù)序列化到消息體中,補單時再次發(fā)起一次更新;如果在業(yè)務(wù)處理時遇到了異常情況,需要再走一遍業(yè)務(wù)補償;

圖 9 以這幾種異常為例,說明了每種補償類型的消息參數(shù)。

圖 9. 分類補償

我們最終的補單體系見圖 10,它既通過即時消息保證了補償?shù)募皶r性,是主動出擊之茅;也利用延時消息重試、落地失敗消息的異常表與兜底任務(wù)保證了補償?shù)挠行裕侨f無一失之盾。不僅可用于支付單據(jù)的補償,通過保證流程的可重入性,也可作為一種通用解決方案,但不適用于無狀態(tài)、不可重入的業(yè)務(wù)形態(tài)。

圖 10. 異常補償體系

4.總結(jié)

本文首先介紹了什么是補單,接著基于三方支付系統(tǒng)的實現(xiàn)完整闡述了補單機制的演進過程,最終演化為一種相對通用的異常處理模式,即基于消息隊列、有限狀態(tài)機與多重任務(wù)兜底的業(yè)務(wù)層最終一致性保障機制,供大家參考指正。

更多分享

UME - 豐富的Flutter調(diào)試工具

一例 Go 編譯器代碼優(yōu)化 bug 定位和修復(fù)解析

字節(jié)跳動破局聯(lián)邦學(xué)習(xí):開源Fedlearner框架,廣告投放增效209%

抖音品質(zhì)建設(shè) - iOS啟動優(yōu)化《原理篇》

歡迎關(guān)注「 字節(jié)跳動技術(shù)團隊 」

簡歷投遞聯(lián)系郵箱「 tech@bytedance.com 」

以上就是關(guān)于如何理解pos機訂單支付,基于有限狀態(tài)機與消息隊列的三方支付系統(tǒng)補單實踐的知識,后面我們會繼續(xù)為大家整理關(guān)于如何理解pos機訂單支付的知識,希望能夠幫助到大家!

轉(zhuǎn)發(fā)請帶上網(wǎng)址:http://m.afbey.com/newsone/52998.html

你可能會喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 babsan@163.com 舉報,一經(jīng)查實,本站將立刻刪除。