使用微服務架構重構支付網關
從這一篇開始,進入重構工作的正題了。 在支付系統中,支付網關和支付渠道的對接是最核心的功能。其中支付網關是對外提供服務的接口,所有需要渠道支持的資金操作都需要通過網關分發到對應的渠道模塊上。一旦定型,后續就很少,也很難調整。而支付渠道模塊是接收網關的請求,調用渠道接口執行真正的資金操作。每個渠道的接口,傳輸方式都不盡相同,所以在這里,支付渠道模塊的作用,類似設計模式中的wrapper,封裝各個渠道的差異,對網關呈現統一的接口。而網關的功能是為業務提供通用接口,一些和渠道交互的公共操作,也會放置到網關中。
初始架構
早期啟動的時候,對接的渠道不多,所有渠道和網關都實現在一個項目中,部署在一起。采用SSH架構,支付網關實現為一個大Apache Struts Action類,在我們重構前,這個類有2000多行代碼。實現時提煉了一個支付渠道對接的抽象類,用來封裝渠道的差異。最終在這個系統中對接了有30多個渠道,類規模達到2000個。隨著業務發展,問題越來越多。高峰期同時有5個渠道在并行開發,還有大量的其他渠道對接問題需要修復。多個人同時修改一個項目代碼導致版本控制的工作驟增。上線頻發引起服務中斷也讓業務方很不滿。諸多問題,在前面的文章中都有描述。
微服務架構
相對來說,支付渠道拆分微服務還是比較容易的,按照渠道來拆分即可。不過前幾天拜讀了 大眾點評支付渠道網關系統的實踐之路 的文章,才知道居然還有人按照服務來拆分。
- 按渠道拆分 ,指每個渠道單獨部署在一個容器中,對支付網關提供相同的服務。
- 按服務拆分 ,是按接口來拆分,分為支付,對賬,退款等子系統,每個服務單獨部署,所有容器的服務都實現在一起。
表面上看起來沒有區別,可是還是懷疑他們接的銀行還是少,應該著看這篇文章 支付渠道那些事 。當然,大眾點評折騰了一通后,最終也是調整為按照渠道來拆分系統。原因有:
- 銀行的加密客戶端會有各種奇葩的需求,有些可以支持linux,有些要windows系統,如何在一個容器中滿足所有需求?
- 這樣拆分后,每個渠道接口獨立部署。某個渠道出問題也不會影響其他渠道。至于渠道訪問量小導致資源浪費問題,可以通過虛機或者docker的資源調度來解決,誰也不會在物理機上玩微服務。
- 對接渠道難點在于對輸入輸出做加密和解密,以及組裝和解析報文。同一個渠道對不同的服務的加密解密方式是一樣的,報文格式也是一樣的。按渠道來構建服務可以共用這樣方法,減少開發投入。
- 從安全的角度,按渠道劃分也有優勢。一般渠道都要求只對接到特定ip的機器,這樣每個渠道對接系統所在的機器僅開放對渠道和支付網關前置機的訪問白名單即可,盡可能的縮減被暴露的風險。
這樣整體軟件架構如下所示:
支付網關前置
支付網關前置是對接業務系統的模塊。它是所有支付功能的集成前置,將不同支付渠道提供的接口通過統一的方式呈現給業務方。 支付網關前置的設計對整個支付系統的穩定性、功能、性能以及其他非功能性需求有著直接的影響。
- 支付網關前置應保持穩定,盡量減少系統重啟等操作對業務方的影響。為此,我們在支付網關前置前端增加Nginx的LBS網關,專門用于請求轉發。當服務器需要重啟時,首先從LBS中摘取,重啟后再掛接上。
- 支付網關前置的性能問題,通過各個后續盡量異步化來處理。 主流程僅保留記錄流水、 執行風控、調用支付路由、調用支付渠道服務,其他操作都異步化處理。
- 接口的安全性問題,包括通道安全和防篡改機制。 通道安全通過HTTPS/SSL來保證,防篡改則通過接口參數簽名來處理。現在主流的簽名是對接口參數按照參數名稱排序后,做加密和散列,參考 微信的簽名規范 。
交易流水和記賬
每一筆交易都需要記錄流水,并登記到個人和機構的分戶賬戶上,統計和分析也需要根據交易流水來更新相關數據。 而個人和機構賬戶總額更新、交易流水記錄以及庫存的處理,更是需要事務處理機制的支持。 從性能角度, 我們弱化了事務處理的要求,采用消息機制來異步化和交易相關的數據處理。
- 在支付網關前置的主流程中,僅記錄交易流水,即將當前的請求保存到數據庫中。
- 完成數據記錄后,發送MQ出來,記賬、統計、分析,都是接收MQ來完成數據處理。
- 涉及到本地資金支付,比如錢包支付,會需要分布式事務處理,扣減賬號余額,記賬,扣減庫存等,每個操作失敗,都要回滾。 阿里 有很不錯的分享,這里不詳細描述。
- 當交易量上來后,需要考慮交易表的分表分庫的事情。分表分庫有兩個策略,按照流水號或者交易主體id來走。后者可以支持按用戶來獲取交易記錄。我們用的是前者。后者可以走elastic,確保數據庫專用。風控,信用和統計所需要的數據,通過MQ同步到Hbase里面。作為支付系統最有價值的數據,在存儲上做到專庫專用,無可厚非,畢竟存儲成本還是廉價的。
風控模塊
風控對支付的重要性怎么強調都不過分。有些系統在風控出問題時可以旁路風控,但是在支付系統中,風控出問題必須停止交易。
整體上,風控可以分為數據采集,數據分析,實時計算,規則配置,實時攔截等模塊。風控本身是個大話題,以后專門討論。又欠一個債。
但風控和交易的接口比較簡單。對每一次交易,風控一般返回四個結果:攔截,增強驗證,人工核實和通過。通過指交易沒有問題,可以直接放行。攔截則是阻止本次交易。增強驗證則是交易存疑,需要用戶進一步核實身份才能繼續,比如輸入手機號或者身份證號,一般用于身份被盜用的場景。而人工核實則是對交易有疑問,一般用于個人惡意消費滿場景。
支付路由
支付路由是一個復雜的話題。對支付系統來說,能支持的支付方式越多越好,不能由于支付方式的不支持斷了財路。現實中的支付方式多得難以置信。用戶隨時甩出一張你聽都沒聽說過的卡。如果一個銀行卡只有幾個用戶在用,那針對這個卡開發個對接有點得不嘗失。現在第三方支付的爆發,確實給開發支付系統省了不少事。但是公司不可能只對接一個第三方支付,如果這個渠道出問題了,或者鬧矛盾了,把鏈接給掐了,老板還不欲哭無淚。總之,得對接多個渠道。對于交易量大的銀行,還得考慮直聯。支付路由的作用是定義對用戶選用的銀行卡或者其他支付方式,使用什么渠道來完成支付。一般來說,銀行會提供兩種支付途徑:無跳轉的快捷支付接口和帶跳轉的網銀接口。前者在綁卡,支付的時候,不需要跳到銀行頁面上去處理,后者則需要在銀行的網銀頁面上完成。顯然前者對用戶來說體驗要好多了,用戶流程不會被打斷。快捷支付要求支付系統在本地保存用戶的支付信息,如卡號,登記手機。系統要確保這些信息不被泄漏。風險非常好,所以大部分銀行要求接入方必須經過ADSS檢驗才能夠接入快捷支付。
這種固定方式的接入有單點故障的問題,一旦某個渠道出問題,綁定的支付方式就無法使用。改進策略是為每個支付方式定義多個渠道,第一個渠道出問題即選擇第二個,以此類推。
當然,更進一步,可以為候選渠道定義權重,按照權重來選擇支付方式。當渠道出問題,自動調整權重。
路由實現上還會更復雜,對同一張銀行卡,運營上會要求在不同的系統上,比如android,iOS,windows上,或者不同地區,如大陸,臺灣,香港,北美等,甚至不同業務上,采用不同渠道來支付。
支付渠道
對于支付渠道,首先考慮的是接入哪些渠道。要對接的渠道按優先級有:
- 第三方支付 ,對大部分應用來說,支付寶和微信支付都是必須的,一般來說,這兩者可以占到90%以上的交易量。用戶不需要綁卡,授權后直接支付就行。各種平臺都支持,性能和穩定性都不錯。對于一些特殊業務,比如游戲,企業支付,可以查看一些專用的第三方支付平臺。
- 銀聯 ,這貨的存在,極大方便了和銀行的對接。和第三方支付主要不同在兩個地方一是需要綁卡,也就是用戶先把卡號,手機,身份證號提供出來。這一步會折損不少用戶。綁卡后,以后的支付操作就簡單了,用戶只需要輸入密碼就行。手機客戶端不需要像第三方支付那樣安裝SDK,都在服務器端完成。當然,這是針對快捷支付。網銀支付還是挺麻煩的。銀聯接入也需要ADSS認證。
- 銀行 ,建議先看這一篇文章,了解下對接銀行的難度。那最終需要選擇哪些銀行?先看個統計數據。 截至 2015 年底,我國銀行業金融機構包括 5 家大型商業銀行、12 家股份制商業銀行、133 家城市商業銀行、5 家民營銀行、859 家農村商業銀行、71 家農村合作銀行、1373家農村信用社、1 家郵政儲蓄銀行、3 家政策性銀行、 311 家村鎮銀行、48 家農村資金互助社。優先選擇5家商業銀行,他們占40%的交易量。其次是股份制銀行和郵儲。這就18家銀行了。老板要是不滿意,城商行和農商行加起來有1000多家呢。一般對接一個銀行預計有3周左右的工作量,大部分銀行需要專線接入,費用和帶寬有關,一年也得幾萬費用。不同銀行對接入環境有不同要求,這也是成本。另外,還有一個重大風險,就是央行在搞得網聯系統,畢竟還沒有出來。
- 手機支付 ,現在不少廠商都內置了各種支付,比如蘋果的In-App支付, 三星支付、華為支付等, 這些支付僅針對特定的手機型號, 支持NFC等,根據業務需要也可以接入。 就是目前用戶群不大,收益不明顯。
- 話費支付 , 這一塊容易被人忽略,但考慮到國內不少職場人士,話費是公司報銷的,每個月多的用不完,所以這塊支付還是相當有市場的。 問題是,聯通和移動兩大運營商,不僅接口不能互通,內部各個地域也是各自為政,所以對接起來還是有點麻煩。不過話費支付領域也有類似支付寶微信的第三方支付公司,比如虹軟、聯動優勢等公司。
這篇文章對支付系統整體設計做一個概要描述,其實每個模塊都是一個大坑,有很多的技術細節。 歡迎大家提提意見,一起探討。
來自:http://dockone.io/article/1845