支付網(wǎng)關(guān)的設(shè)計:核心模塊的功能需求、軟件架構(gòu)設(shè)計以及注意要點(diǎn)
支付網(wǎng)關(guān)和支付渠道是支付渠道最核心的功能。本文介紹這兩個核心模塊的功能需求、軟件架構(gòu)設(shè)計以及設(shè)計上的注意要點(diǎn)。
在支付系統(tǒng)中,支付網(wǎng)關(guān)和支付渠道的對接是最核心的功能。其中支付網(wǎng)關(guān)是對外提供服務(wù)的接口,所有需要渠道支持的資金操作都需要通過網(wǎng)關(guān)分發(fā)到對應(yīng)的渠道模塊上。一旦定型,后續(xù)就很少,也很難調(diào)整。
而支付渠道模塊是接收網(wǎng)關(guān)的請求,調(diào)用渠道接口執(zhí)行真正的資金操作。每個渠道的接口,傳輸方式都不盡相同,所以在這里,支付網(wǎng)關(guān)相對于支付渠道模塊的作用,類似設(shè)計模式中的wrapper,封裝各個渠道的差異,對網(wǎng)關(guān)呈現(xiàn)統(tǒng)一的接口。而網(wǎng)關(guān)的功能是為業(yè)務(wù)提供通用接口,一些和渠道交互的公共操作,也會放置到網(wǎng)關(guān)中。
功能概述
支付系統(tǒng)對其他系統(tǒng),特別是交易系統(tǒng),提供的支付服務(wù)包括簽約,支付,退款,充值,轉(zhuǎn)帳,解約等。有些地方還會額外提供簽約并支付的接口,用于支持在支付過程中綁卡。 每個服務(wù)實(shí)現(xiàn)的流程也是基本類似,包括下單,取消訂單,退單,查單等操作。每個操作實(shí)現(xiàn),都包括參數(shù)校驗(yàn),支付路由,生成訂單,風(fēng)險評估,調(diào)用渠道服務(wù),更新訂單和發(fā)送消息這7步,對于一些比較復(fù)雜的渠道服務(wù),還會涉及到異步同通知處理的步驟。這里詳細(xì)介紹這些步驟的實(shí)現(xiàn)要點(diǎn)。
1. 執(zhí)行參數(shù)校驗(yàn)
所有的支付操作,都需要對輸入執(zhí)行參數(shù)校驗(yàn),避免接口受到攻擊。
- 驗(yàn)證輸入?yún)?shù)中各字段的有效性驗(yàn)證,比如用戶ID,商戶ID,價格,返回地址等參數(shù)。
- 驗(yàn)證賬戶狀態(tài):交易主體、交易對手等賬戶的狀態(tài)是處于可交易的狀態(tài)。
- 驗(yàn)證訂單:如果涉及到預(yù)單,還需要驗(yàn)證訂單號的有效性,訂單狀態(tài)是未支付。為了避免用戶緩存某個URL地址,還需要校驗(yàn)下單時間和支付時間是否超過預(yù)定的間隔。
- 驗(yàn)證簽名:簽名也是為了防止支付接口被偽造。 一般簽名是使用分發(fā)給商戶的key來對輸入?yún)?shù)拼接成的字符串做MD5 Hash或者RSA加密,然后作為一個參數(shù)隨其他參數(shù)一起提交到服務(wù)器端。
2. 根據(jù)支付路由尋找合適的支付服務(wù)
根據(jù)用戶選擇的支付方式確定用來完成該操作的合適的支付渠道。用戶指定的支付方式不一定是最終的執(zhí)行支付的渠道。比如用戶選擇通過工行信用卡來執(zhí)行支付,但是我們沒有實(shí)現(xiàn)和工行的對接,而是可以通過第三方支付,比如支付寶、微信支付、易寶支付,或者銀聯(lián)來完成。那如何選擇合適的支付渠道,就通過支付路由來實(shí)現(xiàn)。支付路由會綜合考慮收費(fèi)、渠道的可用性等因素來選擇最優(yōu)方案。
3. 評估交易風(fēng)險
檢查本次交易是否有風(fēng)險。風(fēng)控接口返回三種結(jié)果:阻斷交易、增強(qiáng)驗(yàn)證和放行交易。
- 阻斷交易,說明該交易是高風(fēng)險的,需要終止,不執(zhí)行第5個步驟;
- 增強(qiáng)驗(yàn)證,說明該交易有一定的風(fēng)險,需要確認(rèn)下是不是用戶本人在操作。這可以通過發(fā)送短信驗(yàn)證碼或者其他可以驗(yàn)證用戶身份的方式來做校驗(yàn),驗(yàn)證通過后,可以繼續(xù)執(zhí)行該交易。
- 放行交易,即本次交易是安全的,可以繼續(xù)往下走。
4. 生成交易訂單
將訂單信息持久化到數(shù)據(jù)庫中。當(dāng)訪問壓力大的時候,數(shù)據(jù)庫寫入會成為一個瓶頸。
5. 調(diào)用支付渠道提供的服務(wù)
所有的支付服務(wù)都需要第三方通道來完成執(zhí)行。一般銀行渠道的調(diào)用比較簡單,可以直接返回結(jié)果。一些第三方支付,支付寶,微信支付等,會通過異步接口來告知支付結(jié)果。
6. 更新訂單
對于同步返回的結(jié)果,需要在主線程中更新訂單的狀態(tài),標(biāo)記是支付成功還是失敗。對于異步返回的渠道,需要在異步程序中處理。
7. 發(fā)送消息
通過消息來通知相關(guān)系統(tǒng)關(guān)于訂單的變更。風(fēng)控,信用BI等,都需要依賴這數(shù)據(jù)做準(zhǔn)實(shí)時計算。
8. 異步通知
如上述流程,其中涉及到調(diào)用遠(yuǎn)程接口,其延遲不可控。如果調(diào)用方一直阻塞等待,很容易超時。引入異步通知機(jī)制,可以讓調(diào)用方在主線程中盡快返回,通過異步線程來得到支付結(jié)果。對于通過異步來獲取支付結(jié)果的渠道接口,也需要對應(yīng)的在異步通知中將結(jié)果返回給調(diào)用方。 異步通知需要調(diào)用方提供一個回調(diào)地址,一般以http或者h(yuǎn)ttps的方式。這就有技術(shù)風(fēng)險,如果調(diào)用失敗,還需要重試。而重試不能過于頻繁,需要逐步拉大每一次重試的時間間隔。 在異步處理程序中,訂單根據(jù)處理結(jié)果變更狀態(tài)后,也要發(fā)消息通知相關(guān)系統(tǒng)。
整體架構(gòu)
整體軟件參考架構(gòu)如下所示:
支付網(wǎng)關(guān)前置
支付網(wǎng)關(guān)前置是對接業(yè)務(wù)系統(tǒng),為其提供支付服務(wù)的模塊。它是所有支付服務(wù)接口的集成前置,將不同支付渠道提供的接口通過統(tǒng)一的方式呈現(xiàn)給業(yè)務(wù)方。這樣接入方就只需要對接支付網(wǎng)關(guān),增加和調(diào)整支付渠道對業(yè)務(wù)方是透明的。 支付網(wǎng)關(guān)前置的設(shè)計對整個支付系統(tǒng)的穩(wěn)定性、功能、性能以及其他非功能性需求有著直接的影響。
在支付網(wǎng)關(guān)中需要完成大量的操作,為了保證性能,這些操作都盡量異步化來處理。
支付網(wǎng)關(guān)前置應(yīng)保持穩(wěn)定,盡量減少系統(tǒng)重啟等操作對業(yè)務(wù)方的影響。支付網(wǎng)關(guān)也避免不了升級和重啟。這可通過基于Nginx的LBS(Load Balance System)網(wǎng)關(guān)來解決。LBS在這里有兩個作用: 一個是實(shí)現(xiàn)負(fù)載均衡,一個是隔離支付網(wǎng)關(guān)重啟對調(diào)用的影響。 支付網(wǎng)關(guān)也采用多臺機(jī)器分布式部署,重啟時,每個服務(wù)器逐個啟動。某臺服務(wù)器重啟時,首先從LBS系統(tǒng)中取消注冊,重啟完成后,再重新注冊到LBS上。這個過程對調(diào)用方是無感知的。
為了避免接口受攻擊,在安全上,還得要求業(yè)務(wù)方通過HTTPS來訪問接口,并提供防篡改機(jī)制。防篡改則通過接口參數(shù)簽名來處理。現(xiàn)在主流的簽名是對接口參數(shù)按照參數(shù)名稱排序后,做加密和散列,參考微信的簽名規(guī)范。
交易流水和記賬
每一筆交易都需要記錄流水,并登記到個人和機(jī)構(gòu)的分戶賬戶上,統(tǒng)計和分析也需要根據(jù)交易流水來更新相關(guān)數(shù)據(jù)。 而個人和機(jī)構(gòu)賬戶總額更新、交易流水記錄以及庫存的處理,更是需要事務(wù)處理機(jī)制的支持。 從性能角度, 可以弱化了事務(wù)處理的要求,采用消息機(jī)制來異步化和交易相關(guān)的數(shù)據(jù)處理。
在支付網(wǎng)關(guān)前置的主流程中,僅記錄交易流水,即將當(dāng)前的請求保存到數(shù)據(jù)庫中。
完成數(shù)據(jù)記錄后,發(fā)送MQ出來,記賬、統(tǒng)計、分析,都是接收MQ來完成數(shù)據(jù)處理。
涉及到本地資金支付,比如錢包支付,會需要分布式事務(wù)處理,扣減賬號余額,記賬,扣減庫存等,每個操作失敗,都要回滾。阿里有很不錯的分享,這里不詳細(xì)描述。
當(dāng)交易量上來后,需要考慮交易表的分表分庫的事情。分表分庫有兩個策略,按照流水號或者交易主體id來走。后者可以支持按用戶來獲取交易記錄。我們用的是前者。后者可以走elastic,確保數(shù)據(jù)庫專用。風(fēng)控,信用和統(tǒng)計所需要的數(shù)據(jù),通過MQ同步到Hbase里面。作為支付系統(tǒng)最有價值的數(shù)據(jù),在存儲上做到專庫專用,無可厚非,畢竟存儲成本還是廉價的。
風(fēng)控模塊
風(fēng)控對支付的重要性怎么強(qiáng)調(diào)都不過分。有些系統(tǒng)在風(fēng)控出問題時可以旁路風(fēng)控,但是在支付系統(tǒng)中,風(fēng)控出問題必須停止交易。 整體上,風(fēng)控可以分為數(shù)據(jù)采集,數(shù)據(jù)分析,實(shí)時計算,規(guī)則配置,實(shí)時攔截等模塊。風(fēng)控本身是個大話題,以后專門討論。又欠一個債。 但風(fēng)控和交易的接口比較簡單。對每一次交易,風(fēng)控一般返回三個結(jié)果:攔截,增強(qiáng)驗(yàn)證,通過。通過指交易沒有問題,可以直接放行。攔截則是阻止本次交易。增強(qiáng)驗(yàn)證則是交易存疑,需要用戶進(jìn)一步核實(shí)身份才能繼續(xù),比如輸入手機(jī)號或者身份證號,一般用于身份被盜用的場景。而人工核實(shí)則是對交易有疑問,一般用于個人惡意消費(fèi)滿場景。
支付路由
支付路由是一個復(fù)雜的話題。對支付系統(tǒng)來說,能支持的支付方式越多越好,不能由于支付方式的不支持?jǐn)嗔素斅贰,F(xiàn)實(shí)中的支付方式多得難以置信。用戶隨時甩出一張你聽都沒聽說過的卡。如果一個銀行卡只有幾個用戶在用,那針對這個卡開發(fā)個對接有點(diǎn)得不嘗失。現(xiàn)在第三方支付的爆發(fā),確實(shí)給開發(fā)支付系統(tǒng)省了不少事。但是公司不可能只對接一個第三方支付,如果這個渠道出問題了,或者鬧矛盾了,把鏈接給掐了,老板還不欲哭無淚??傊?,得對接多個渠道。對于交易量大的銀行,還得考慮直聯(lián)。
支付路由的作用是定義對用戶選用的銀行卡或者其他支付方式,使用什么渠道來完成支付。
一般來說,銀行會提供兩種支付途徑:無跳轉(zhuǎn)的快捷支付接口和帶跳轉(zhuǎn)的網(wǎng)銀接口。前者在綁卡,支付的時候,不需要跳到銀行頁面上去處理,后者則需要在銀行的網(wǎng)銀頁面上完成。顯然前者對用戶來說體驗(yàn)要好多了,用戶流程不會被打斷??旖葜Ц兑笾Ц断到y(tǒng)在本地保存用戶的支付信息,如卡號,登記手機(jī)。系統(tǒng)要確保這些信息不被泄漏。風(fēng)險非常好,所以大部分銀行要求接入方必須經(jīng)過ADSS檢驗(yàn)才能夠接入快捷支付。
這種固定方式的接入有單點(diǎn)故障的問題,一旦某個渠道出問題,綁定的支付方式就無法使用。改進(jìn)策略是為每個支付方式定義多個渠道,第一個渠道出問題即選擇第二個,以此類推。
當(dāng)然,更進(jìn)一步,可以為候選渠道定義權(quán)重,按照權(quán)重來選擇支付方式。當(dāng)渠道出問題,自動調(diào)整權(quán)重。
路由實(shí)現(xiàn)上還會更復(fù)雜,對同一張銀行卡,運(yùn)營上會要求在不同的系統(tǒng)上,比如android,iOS,windows上,或者不同地區(qū),如大陸,臺灣,香港,北美等,甚至不同業(yè)務(wù)上,采用不同渠道來支付。
支付渠道
如果采用微服務(wù)來實(shí)現(xiàn),整體設(shè)計上,可以考慮將支付渠道分離、支付網(wǎng)關(guān)前置分離。支付渠道的微服務(wù)實(shí)現(xiàn)有兩種策略,一種是按照服務(wù)來拆分,一種是按照渠道來拆分。
- 按渠道拆分,指每個渠道單獨(dú)部署在一個容器中,對支付網(wǎng)關(guān)提供相同的服務(wù)。
- 按服務(wù)拆分,是按接口來拆分,分為支付,對賬,退款等子系統(tǒng),每個服務(wù)單獨(dú)部署,所有容器的服務(wù)都實(shí)現(xiàn)在一起。
渠道拆分
按照服務(wù)來拆分的一個典型案例是大眾點(diǎn)評網(wǎng)的早期實(shí)現(xiàn)。?大眾點(diǎn)評支付渠道網(wǎng)關(guān)系統(tǒng)的實(shí)踐之路。 每個支付服務(wù)接口實(shí)現(xiàn)為一個獨(dú)立的子系統(tǒng),獨(dú)立部署,通過支付網(wǎng)關(guān)前置來對外提供服務(wù)。 這篇文章里面也提到這種方式存在的問題,
銀行的加密客戶端會有各種奇葩的需求,有些可以支持linux,有些要windows系統(tǒng),如何在一個容器中滿足所有需求?
這樣拆分后,每個渠道接口獨(dú)立部署。某個渠道出問題也不會影響其他渠道。至于渠道訪問量小導(dǎo)致資源浪費(fèi)問題,可以通過虛機(jī)或者docker的資源調(diào)度來解決,誰也不會在物理機(jī)上玩微服務(wù)。
對接渠道難點(diǎn)在于對輸入輸出做加密和解密,以及組裝和解析報文。同一個渠道對不同的服務(wù)的加密解密方式是一樣的,報文格式也是一樣的。按渠道來構(gòu)建服務(wù)可以共用這樣方法,減少開發(fā)投入。
從安全的角度,按渠道劃分也有優(yōu)勢。一般渠道都要求只對接到特定ip的機(jī)器,這樣每個渠道對接系統(tǒng)所在的機(jī)器僅開放對渠道和支付網(wǎng)關(guān)前置機(jī)的訪問白名單即可,盡可能的縮減被暴露的風(fēng)險。
接入渠道
對于支付渠道,首先考慮的是接入哪些渠道。要對接的渠道按優(yōu)先級有:
(1)第三方支付
對大部分應(yīng)用來說,支付寶和微信支付都是必須的,一般來說,這兩者可以占到90%以上的交易量。用戶不需要綁卡,授權(quán)后直接支付就行。各種平臺都支持,性能和穩(wěn)定性都不錯。對于一些特殊業(yè)務(wù),比如游戲,企業(yè)支付,可以查看一些專用的第三方支付平臺。
(2)銀聯(lián)
這貨的存在,極大方便了和銀行的對接。和第三方支付主要不同在兩個地方一是需要綁卡,也就是用戶先把卡號,手機(jī),身份證號提供出來。這一步會折損不少用戶。綁卡后,以后的支付操作就簡單了,用戶只需要輸入密碼就行。手機(jī)客戶端不需要像第三方支付那樣安裝SDK,都在服務(wù)器端完成。當(dāng)然,這是針對快捷支付。網(wǎng)銀支付還是挺麻煩的。銀聯(lián)接入也需要ADSS認(rèn)證。
(3)銀行
建議先看這一篇文章,了解下對接銀行的難度。那最終需要選擇哪些銀行?先看個統(tǒng)計數(shù)據(jù)。 截至 2015 年底,我國銀行業(yè)金融機(jī)構(gòu)包括 5 家大型商業(yè)銀行、12 家股份制商業(yè)銀行、133 家城市商業(yè)銀行、5 家民營銀行、859 家農(nóng)村商業(yè)銀行、71 家農(nóng)村合作銀行、1373家農(nóng)村信用社、1 家郵政儲蓄銀行、3 家政策性銀行、 311 家村鎮(zhèn)銀行、48 家農(nóng)村資金互助社。優(yōu)先選擇5家商業(yè)銀行,他們占40%的交易量。其次是股份制銀行和郵儲。這就18家銀行了。老板要是不滿意,城商行和農(nóng)商行加起來有1000多家呢。一般對接一個銀行預(yù)計有3周左右的工作量,大部分銀行需要專線接入,費(fèi)用和帶寬有關(guān),一年也得幾萬費(fèi)用。不同銀行對接入環(huán)境有不同要求,這也是成本。另外,還有一個重大風(fēng)險,就是央行在搞得網(wǎng)聯(lián)系統(tǒng),畢竟還沒有出來,相關(guān)資料參考知乎上關(guān)于網(wǎng)聯(lián)的一篇討論。
(4)手機(jī)支付
現(xiàn)在不少廠商都內(nèi)置了各種支付,比如蘋果的In-App支付, 三星支付、華為支付等, 這些支付僅針對特定的手機(jī)型號, 支持NFC等,根據(jù)業(yè)務(wù)需要也可以接入。 就是目前用戶群不大,收益不明顯。
(5)話費(fèi)支付
這一塊容易被人忽略,但考慮到國內(nèi)不少職場人士,話費(fèi)是公司報銷的,每個月多的用不完,所以這塊支付還是相當(dāng)有市場的。 問題是,聯(lián)通和移動兩大運(yùn)營商,不僅接口不能互通,內(nèi)部各個地域也是各自為政,所以對接起來還是有點(diǎn)麻煩。不過話費(fèi)支付領(lǐng)域也有類似支付寶微信的第三方支付公司,比如虹軟、聯(lián)動優(yōu)勢等公司。
這篇文章對支付系統(tǒng)整體設(shè)計做一個概要描述,其實(shí)每個模塊都是一個大坑,有很多的技術(shù)細(xì)節(jié)。 歡迎大家提提意見,一起探討。
作者:鳳凰牌老熊(微信公眾號:鳳凰牌老熊)
來源:http://blog.lixf.cn/essay/2016/11/02/account-7-gateway
本文由 @鳳凰牌老熊 授權(quán)發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)作者許可,禁止轉(zhuǎn)載。
這種固定方式的接入有單點(diǎn)故障的問題,一旦某個渠道出問題,綁定的支付方式就無法使用。改進(jìn)策略是為每個支付方式定義多個渠道,第一個渠道出問題即選擇第二個,以此類推。
這段話不太好理解,假如平臺接入了快錢和易寶兩個支付渠道,用戶通過快錢這個渠道開通了快捷支付,但是某天快錢渠道出問題了,如何平滑的切換到易寶?一般用戶在綁卡的時候只收到一個渠道的快捷開通驗(yàn)證碼,如果想要平滑切換到其他渠道,是不是要同時給他開通其他渠道的快捷?如果這樣可以做到,難道不用接收短信嗎?
同問!這個問題是否有答案了
感覺好抽象
首先謝謝作者的干貨分享,受益良多么,同時求問文中所說的阿里的文章是哪篇,非常感謝!