網(wǎng)上有很多關(guān)于pos機拆機基地,基于有限狀態(tài)機與消息隊列的三方支付系統補單實(shí)踐的知識,也有很多人為大家解答關(guān)于pos機拆機基地的問(wèn)題,今天pos機之家(www.xjcwpx.cn)為大家整理了關(guān)于這方面的知識,讓我們一起來(lái)看下吧!
本文目錄一覽:
1、pos機拆機基地
pos機拆機基地
0.引言在日常生活中,從線(xiàn)下的超市購物到線(xiàn)上的外賣(mài)點(diǎn)餐、電商網(wǎng)購等,支付無(wú)時(shí)無(wú)刻不在發(fā)生,不論是通過(guò)現金、pos 機刷卡還是微信支付寶等第三方支付。線(xiàn)上支付有著(zhù)及時(shí)便捷一氣呵成的極致體驗,當然也有少數的時(shí)候體驗不夠絲滑,比如早期我們在 PC 版 12306 買(mǎi)火車(chē)票,當支付完成后,訂單的支付狀態(tài)卻經(jīng)常不能及時(shí)更新,會(huì )有一段時(shí)間的延遲,有時(shí)甚至會(huì )等待很長(cháng)時(shí)間處在未支付狀態(tài)。
在支付的過(guò)程中由于各種各樣的原因(比如外部渠道處理出了問(wèn)題,異步回調遲遲不來(lái))導致流程走了一半停了下來(lái),用戶(hù)看到訂單依然是未支付狀態(tài),會(huì )不知所措,此時(shí)就需要一種機制來(lái)推動(dòng)完成這筆交易。本文就以三方支付系統中的補單機制為例,來(lái)介紹一種較為通用的單據補償模式。
1.三方支付系統簡(jiǎn)介1.1 什么是三方支付所謂第三方支付,就是和各大銀行簽約,獨立于商戶(hù)和銀行,具備一定實(shí)力和信譽(yù)保障的,為商戶(hù)與消費者提供支付結算服務(wù)的第三方獨立機構。它是處于買(mǎi)方和賣(mài)方之間具備公信力的第三方,承擔擔保人和資金托管人的角色。三方支付也可以稱(chēng)為虛擬賬戶(hù)支付,由消費者在第三方支付機構開(kāi)設虛擬賬戶(hù),并用虛擬賬戶(hù)中的資金進(jìn)行支付。業(yè)界常見(jiàn)的三方支付有支付寶、微信支付、美團支付、京東支付等等。
1.2 三方支付中的交易&支付系統交易是什么,最直觀(guān)的描述就是“一手交錢(qián)、一手交貨” ,交易會(huì )使買(mǎi)賣(mài)雙方形成債權和債務(wù)關(guān)系。交易的存在是支付發(fā)生的前提,用戶(hù)通過(guò)使用某種支付方式去完成交易。交易是支付流程的驅動(dòng)者,根據具體場(chǎng)景組合不同的支付指令,來(lái)完成交易資金的轉移。
支付是交易處理資金流的工具,目的是清償債權和債務(wù)關(guān)系;支持多種支付方式(如銀行卡支付、余額支付、優(yōu)惠券組合支付、類(lèi)似花唄的信用支付等),負責對接賬務(wù)、會(huì )計、計費系統等資金處理能力,接收支付指令,驅動(dòng)完成資金交換。將實(shí)際的支付行為(實(shí)際資金)與內部的記賬(虛擬資金)相結合,保證虛實(shí)一致。
三方支付整體業(yè)務(wù)架構如圖 1 所示,其中交易核心與支付核心在業(yè)務(wù)劃分上處于"收單支付域",具備普通交易的收款、付款、退款及充值、轉賬與提現等常見(jiàn)功能,還包括了支撐電商業(yè)務(wù)的合單支付、擔保與分賬的能力。其中交易與支付核心都有一個(gè)異常查補模塊,它囊括了所有業(yè)務(wù)的補償流程,也是本文主要介紹的部分。
圖 1. 三方支付業(yè)務(wù)架構
2.什么是補單&為什么需要補單一筆交易在支付過(guò)程中由于鏈路中的各種異常而中斷,此時(shí)的交易處在一種中間狀態(tài),這種情況俗稱(chēng)"卡單",即卡在那里不動(dòng)了,沒(méi)有繼續向下推進(jìn)。還有一種情形,支付核心向渠道發(fā)起了扣款,渠道受理后,銀行卡扣款成功,但由于種種原因沒(méi)有向支付核心發(fā)起回調,導致這筆支付沒(méi)有完成,用戶(hù)沒(méi)有享受到相應權益,但銀行卡的錢(qián)已經(jīng)扣了,這種情況稱(chēng)為“掉單”。
不管是卡單還是掉單,都是處在中間態(tài)的訂單。補單就是將處在中間態(tài)的訂單進(jìn)行補償,直到推進(jìn)到終態(tài)(成功或失?。?/strong>。補單一般有兩個(gè)關(guān)鍵點(diǎn),一個(gè)是補償的有效性,極端情況下可能補償多次都不成功,不能就此放棄了,需要有兜底的機制;另一個(gè)是補償的及時(shí)性,因為交易掛起的時(shí)間越長(cháng),用戶(hù)的體驗越差。
交易核心和支付核心的補單相得益彰,具有一定相似程度的設計與實(shí)現,我們就以支付核心的補單為例介紹下異常補單機制。
3.補單是如何實(shí)現的本章首先了解一下業(yè)務(wù)流程,說(shuō)明一下實(shí)現補單需要的前提基礎,然后介紹一下補單機制的演進(jìn)路線(xiàn),每個(gè)版本存在的問(wèn)題以及在下一個(gè)版本是如何解決的。
3.1 有限狀態(tài)機與冪等性標識資金操作的有限狀態(tài)機我們首先以用戶(hù)發(fā)起一筆余額提現為例,說(shuō)明下業(yè)務(wù)流程,簡(jiǎn)化后如圖 2 所示。
圖 2. 余額提現流程
首先生成支付訂單,然后請求賬務(wù)系統,扣減用戶(hù)賬戶(hù)下的余額,接著(zhù)向外部渠道發(fā)起付款操作,資金操作完成后統一處理結果并更新單據信息,最后還有一些對上下游的異步通知,形式上包括消息和 RPC 回調。
我們將每個(gè)關(guān)鍵資金操作的狀態(tài)記錄落庫,如下表所示。其中出款即錢(qián)從哪里來(lái),入款即錢(qián)到哪里去,沖正即回滾交易。在提現場(chǎng)景下就是從用戶(hù)支付賬戶(hù)出錢(qián),到用戶(hù)的銀行卡去。其他場(chǎng)景比如充值(銀行卡->用戶(hù)支付賬戶(hù)),會(huì )有不同的資金流向。表中最后兩行加粗的場(chǎng)景還沒(méi)有達到終態(tài),是我們需要去補償的。
為了便于理解,我們在這里省略了沖正的相關(guān)操作,一次余額提現流程的狀態(tài)機轉換如圖 3 所示。
圖 3.附帶狀態(tài)機轉換的余額提現流程
可重入與冪等性保證發(fā)起一次支付會(huì )涉及到多個(gè)系統間調用,由于網(wǎng)絡(luò )原因導致的通信超時(shí)是常見(jiàn)的問(wèn)題。同時(shí)上游系統也可能會(huì )重新發(fā)起請求,這需要我們的系統保證操作結果的冪等性。少數用戶(hù)也可能會(huì )有多個(gè)終端同時(shí)操作帶來(lái)的并發(fā)請求,需要我們保證接口的可重入性。除了服務(wù)自身,我們的下游依賴(lài)同樣也需要保證其接口具有同樣的能力。
先說(shuō)一說(shuō)什么是可重入與冪等性。
可重入:在并發(fā)請求下可以保證正確性。冪等性:重復多次相同的輸入,獲得相同的輸出。冪等性在技術(shù)上其實(shí)也包含了可重入的要求。具體到業(yè)務(wù)中,冪等性是針對一筆已經(jīng)到達終態(tài)的支付而言的,對于初次未能拿到最終業(yè)務(wù)結果的請求,再次發(fā)起調用的結果可以是不同的(處理中->處理成功或失?。?。那么我們如何保證業(yè)務(wù)流程的可重入與冪等性呢?我們分別拆解每一步來(lái)看:
生成支付單:首先支付單據可以將業(yè)務(wù)方傳遞的可保證唯一性的外部訂單號作為唯一索引,插入數據庫時(shí)若發(fā)生唯一索引沖突,則將查詢(xún)已有數據進(jìn)行冪等參數校驗,若與當次請求的參數完全一致說(shuō)明是重復請求,可使用 DB 中的支付單繼續推進(jìn)后續流程;若不一致則返回錯誤。資金處理流程:賬戶(hù)和渠道系統各自保證其接口冪等性。我們也維護了每個(gè)下游操作的狀態(tài),根據狀態(tài)機決定是否要繼續推進(jìn),盡量不向下游輸出重復流量。比如支付單已經(jīng)完成了所有資金處理,狀態(tài)機已經(jīng)是終態(tài),那么接口可以直接返回相應結果。更新支付單信息,先將支付單加行級排他鎖,再進(jìn)行更新,保證多個(gè)并發(fā)請求只會(huì )有一個(gè)成功。異步通知,在支付單推進(jìn)到終態(tài)后進(jìn)行。有了可重入與冪等性保證,我們就可以大量地復用正向流程來(lái)實(shí)現補單接口。
3.2 初始版一般來(lái)說(shuō)最常見(jiàn)的補單形式是設置一個(gè)定時(shí)任務(wù),定時(shí)去掃表完成業(yè)務(wù)補償,實(shí)現比較簡(jiǎn)單,但是及時(shí)性不夠,對于收款轉賬類(lèi)的交易而言用戶(hù)體驗不佳。我們采用了通過(guò)消息隊列進(jìn)行即時(shí)補償的方式,如圖 4 所示。補償消費者并沒(méi)有去做補償工作,而是解析消息然后通過(guò) RPC 調用支付核心暴露的補償接口。為什么不在消費者中直接補償?這么做主要是考慮將邏輯收斂到一處便于維護。
圖 4. 余額提現發(fā)生異常時(shí)的補單流程
當然,補單可能依然失敗,我們可以再次發(fā)送補償消息。但不能一直這樣循環(huán)下去,所以需要設置一個(gè)最大重試次數,超出后不再發(fā)送。當補償多次都不成功時(shí),一般是下游系統出了問(wèn)題,這時(shí)我們需要放緩補償的頻次,隨著(zhù)重試次數增加,會(huì )讓每次補償時(shí)間間隔逐漸增大,通過(guò) RocketMQ 的延時(shí)消息實(shí)現。
這里有三個(gè)很容易想到的問(wèn)題:
如果異常消息發(fā)送失敗,上游也沒(méi)有重試機制,這筆訂單就可能一直掛在這里不了了之了,如圖 5 所示。補償消費者請求支付核心補單時(shí)不成功,可能是超時(shí)但實(shí)際補償成功了,或者是請求壓根沒(méi)有過(guò)去,如圖 6 所示。如果重試達到最大次數依然沒(méi)有成功,這筆單子該怎么處理。圖 5. 補償消息發(fā)送失敗
圖 6. 補償消息消費失敗
3.3 改進(jìn)版針對問(wèn)題 1,如果重試依然發(fā)送失敗,我們通過(guò)引入一張異常消息表,將發(fā)送失敗的消息落庫來(lái)解決。表中記錄了訂單號、當前的重試次數、異常分類(lèi)、記錄狀態(tài)、消息體等字段。如果圖 6 中的第 4 步消息發(fā)送失敗,就將這筆訂單放入 DB 中的一張異常表中,會(huì )設置一個(gè)定時(shí)任務(wù)去處理。以目前 RocketMQ 的可用性來(lái)說(shuō),異常數據很少會(huì )出現。如圖 7 所示。
圖 7. 針對消息生產(chǎn)/消費異常的改進(jìn)版 - 1
對于第 2 個(gè)問(wèn)題,如果補償消費者調用支付核心失敗,補償消費者 HandleMessage 會(huì )向上層拋出 error,利用 RocketMQ 的梯度重試機制,當消費重試次數達到一定上限后會(huì )進(jìn)入死信隊列。如圖 8 所示,這種情況一般是服務(wù)或網(wǎng)絡(luò )出了問(wèn)題,待恢復之后,可以從死信隊列拉取這些消息再統一處理。
圖 8. 針對消息生產(chǎn)/消費異常的改進(jìn)版 - 2
當然還有更極端的情況,請求 MQ 和 DB 都失敗了咋辦?以目前 MQ 和 DB 的可用性來(lái)說(shuō),同時(shí)失敗這種基本可以不用考慮,報警人工介入即可。
針對問(wèn)題 3,如果重試超過(guò)最大次數,依然補償不成功,一般是下游依賴(lài)出了問(wèn)題。這種情況我們也將它放進(jìn)異常表中。
對于這兩類(lèi)漏網(wǎng)之魚(yú),需要支持單條/批量支付單補償的運營(yíng)能力以供人工介入;最好有一個(gè)在業(yè)務(wù)低峰期運行的兜底任務(wù),掃描業(yè)務(wù)單據表,將一段時(shí)間內還未完成的訂單進(jìn)行補償。
另外,兜底任務(wù)可能造成消息的短暫堆積,影響線(xiàn)上的實(shí)時(shí)補償流程推進(jìn),對此可以使用獨立的隊列隔離開(kāi)來(lái)。
3.4 最終版其實(shí)如果只是異步通知類(lèi)的操作出現了異常,并沒(méi)有必要每次都重新走一遍完整業(yè)務(wù)流程,缺啥補啥即可。因此我們將異常劃分為多種類(lèi)型,將一些異步操作和業(yè)務(wù)處理劃分開(kāi)來(lái),進(jìn)行精細化的處理:
通知下游的 MQ 失敗,就將這個(gè)消息體重發(fā)一次即可;通知交易的回調 RPC 失敗,可將 RPC 請求序列化到消息體中,補償時(shí)通過(guò)反序列化消息體中的 RPC 請求,直接再發(fā)起一次 RPC 即可;對于更新 DB 失敗,將更新參數序列化到消息體中,補單時(shí)再次發(fā)起一次更新;如果在業(yè)務(wù)處理時(shí)遇到了異常情況,需要再走一遍業(yè)務(wù)補償;圖 9 以這幾種異常為例,說(shuō)明了每種補償類(lèi)型的消息參數。
圖 9. 分類(lèi)補償
我們最終的補單體系見(jiàn)圖 10,它既通過(guò)即時(shí)消息保證了補償的及時(shí)性,是主動(dòng)出擊之茅;也利用延時(shí)消息重試、落地失敗消息的異常表與兜底任務(wù)保證了補償的有效性,是萬(wàn)無(wú)一失之盾。不僅可用于支付單據的補償,通過(guò)保證流程的可重入性,也可作為一種通用解決方案,但不適用于無(wú)狀態(tài)、不可重入的業(yè)務(wù)形態(tài)。
圖 10. 異常補償體系
4.總結本文首先介紹了什么是補單,接著(zhù)基于三方支付系統的實(shí)現完整闡述了補單機制的演進(jìn)過(guò)程,最終演化為一種相對通用的異常處理模式,即基于消息隊列、有限狀態(tài)機與多重任務(wù)兜底的業(yè)務(wù)層最終一致性保障機制,供大家參考指正。
更多分享UME - 豐富的Flutter調試工具
一例 Go 編譯器代碼優(yōu)化 bug 定位和修復解析
字節跳動(dòng)破局聯(lián)邦學(xué)習:開(kāi)源Fedlearner框架,廣告投放增效209%
抖音品質(zhì)建設 - iOS啟動(dòng)優(yōu)化《原理篇》
歡迎關(guān)注「 字節跳動(dòng)技術(shù)團隊 」
簡(jiǎn)歷投遞聯(lián)系郵箱「 tech@bytedance.com 」
以上就是關(guān)于pos機拆機基地,基于有限狀態(tài)機與消息隊列的三方支付系統補單實(shí)踐的知識,后面我們會(huì )繼續為大家整理關(guān)于pos機拆機基地的知識,希望能夠幫助到大家!
