1. 程式人生 > >我對支付平臺架構設計的一些思考

我對支付平臺架構設計的一些思考

微信公眾號「後端進階」,專注後端技術分享:Java、Golang、WEB框架、分散式中介軟體、服務治理等等。
老司機傾囊相授,帶你一路進階,來不及解釋了快上車!

我在前一家公司的第一個任務是開發統一支付平臺,由於公司的業務需求,需要接入多個第三方支付,之前公司的支付都是散落在各個專案中,及其不利於支付的管理,於是聚合三方支付,統一支付平臺的任務就落在我手上,可以說是完全從 0 開始設計,經過一翻實戰總結,我得出了一些架構設計上的思考,之前就一直很想把自己的架構設計思路寫出來,但一直沒動手,前幾天在技術群裡有人問到相關問題,我覺得有必要把它寫出來,以幫助到更多需要開發支付平臺的開發人員。

元件模式

由於公司業務在很多地區都有,需要提供多種支付途徑,以滿足業務的發展,所以設計的支付平臺需要接入多種第三方支付渠道,如:微信支付、支付寶支付、PayPal、IPayLinks 等等,我們都知道,每個第三方支付,都有自己一套對外 API,官方都有一套 SDK 來實現這些 API,我們應該如何組織這些 API 呢?

由於第三方支付渠道會隨著業務的發展變動,所以組織這些 SDK 就需要在不影響支付平臺整體架構的前提下可靈活插拔,這裡我使用了元件的思想,將支付 API 拆分成各種元件支付元件、退款元件、訂單元件、賬單元件等等,那麼這樣就可以當引入一個第三方支付 SDK 時,可靈活在元件上面新增需要的 API,架構設計如下:

通過 Builder 模式根據請求引數構建對應的元件物件,將元件與外部分離,隱藏元件構建的實現。元件模式 + Builder 模式使得支付平臺具備了高擴充套件性。

多賬戶體系

在接入各種第三方支付平臺,我們當時又遇到一個賬戶的問題,原因是公司當時的小程式與 APP 使用的是不同的微信賬號,因此會出現微信支付會對應到多個賬戶的問題,而我當時設計支付平臺時,沒有考慮到這個問題,當時第三方支付只對應了一個賬戶,而且不同的第三方支付的賬戶之間相互獨立且不統一。

於是我引入了多賬戶體系,多賬戶體系最重要的一個核心概念是以賬戶為粒度,接入多個第三方支付,統一賬戶的引數,構建了統一的支付賬戶體系,支付平臺無需關心不同支付之間的賬戶差異以及第三方支付是否有多少個賬戶。

此時我在支付平臺架構圖加上賬戶層:

前端只需要傳遞 accountId,支付平臺就可以根據 accountId 查詢出對應的支付賬戶,然後通過 Builder 模式構建支付賬戶對應的元件物件,完全遮蔽不同支付之間的差異,在多賬戶體系裡面,可以支援無限多個支付賬戶,完全滿足了公司業務的發展需求。

統一回調與非同步分發處理

做過支付開發的同學都知道,目前的第三方支付都有一個特點,就是支付/退款成功後,會有一個支付/退款回撥的功能,目的是為了讓商戶平臺自行校驗該筆訂單是否合法,比如:防止在支付時,客戶端惡意篡改金額等引數,那麼此時支付成功後,訂單會處於支付中狀態,需要等待第三方支付的回撥,如果此時收到了回撥,在校驗時發現訂單的金額與支付的金額不對,然後將訂單改成支付失敗,以防止資金損失。回撥的思想是隻要保證最終的一致性,所以我們調起支付時,並不需要在此時校驗引數的正確性,只需要在回撥時校驗即可。

講完了回撥的目的,那麼我們如何來設計支付平臺的回撥呢?

由於支付平臺接入了多個第三方支付,如果此時每個第三方支付設定一個回撥地址,那麼將會出現多個回撥地址,由於回撥的 API 必須是暴露出去才能接受第三方的回撥請求,所以就會有安全問題,我們必須在 API 外層設定安全過濾,不然很容易出現一些非法暴力訪問,所以我們需要統一回調 API,統一做安全校驗,之後再進行一層分發。

分發的機制我這裡建議用 RocketMQ 來處理,可能有人會問,如果用 RocketMQ 來做分發處理,此時怎麼實時返回校驗結果到第三方支付呢?這個問題也是我當時一直頭疼的問題,以下是我對回撥設計的一些思考:

  1. 公司的系統是基於 SpringCloud 微服務架構,微服務之間通過 HTTP 通訊,當時有很多個微服務接入了我的支付平臺,如果用 HTTP 作分發,可以保證訊息返回的實時性,但也會出現一個問題,由於網路不穩定,就會出現請求失敗或超時的問題,介面的穩定性得不到保障。
  2. 由於第三方支付如果收到 false 響應,就在接下來一段時間內再次發起回撥請求,這麼做的目的是為了保證回撥的成功率,對於第三方支付來說,這沒毛病,但對於商戶支付平臺來說,也許就是一個比較坑爹的設計,你想一下,假設有一筆訂單在支付時惡意篡改了金額,回撥校驗失敗,返回 false 到第三方支付,此時第三方支付會再重複傳送回撥,無論傳送多少次回撥,都會校驗失敗,這就額外增加了不必要的互動,當然這裡也可以用冪等作處理,以下是微信支付回撥的應用場景說明:

基於以上兩點思考,我認為返回 false 到第三方支付是沒必要的,為了系統的健壯性,我採用了訊息佇列來做非同步分發,支付平臺收到回撥請求後直接返回 true,這時你可能會提出一個疑問,如果此時校驗失敗了,但此時返回 true,會不會出現問題?首先,校驗失敗情況,訂單必定是處於支付失敗的狀態,此時返回 true 目的是為了減少與第三方支付不必要的遠端互動。

因為 RocketMQ 的訊息是持久化到磁碟的,所以用訊息佇列來做非同步分發最大的好處,就是可以複查訊息佇列裡面的訊息來排查問題,而且訊息佇列可以在業務的高峰期進行流量削峰。

以下是統一回調與分發處理的架構設計圖:

聚合支付

支付平臺聚合了多種第三方支付,因此在請求層需要做很多的適配工作,以滿足多種支付的需求,可能你會想,直接在適配那裡加幾行 if else 不就得了嗎,這麼做也沒問題,也可以滿足多種支付的需求,但你有沒有想過,假設此時再加一個第三方支付,你會怎麼做?你只能原有方法上加多個 else 條件,這樣就會導致請求層程式碼不斷地隨著業務發展改變,使得程式碼及其不優雅,而且也不好維護,這時我們就得用上策略模式,將這些 if else 程式碼消除,當我們增加一個第三方支付時,我們只需要新建一個 Strategy 類就可以了,策略模式究竟怎麼使用可以看看大話設計模式。

因此我在 Builder 模式前加多了一層支付策略層:

請求處理

由於支付平臺涉及到資金,支付的各種請求與返回,以及異常記錄在一個支付平臺中異常重要,因此我們需要記錄每一次的支付請求記錄,以便後續排查問題。

基於這點需求,我在開始請求第三方支付之前,設計了一層 Handler 層,所有的請求都必須經過 Handler 層進行處理,Handler 核心方法如下:

public K handle(T t) {
  K k;
  try {
    before(t);
    k = execute(t);
    after(k);
  } catch (Exception e) {
    exception(t, e);
  }
  return k;
}
protected abstract void before(T t);
protected abstract void after(K k);
protected abstract void exception(T t, Exception exception);

原則上來說,我設計的 Handler 層,利用了模版模式,不僅僅可以實現日誌的記錄,還可以實現多種處理方式,比如請求監控,訊息推送等等,實現了 Handler 層的高擴充套件性。

以下是 Handler 層的架構設計圖:

寫在最後

以上就是我的支付平臺架構設計思路,總結來說,支付平臺需要具備可擴充套件性、穩定性、高可用性,因此我在設計支付平臺時使用了很多設計模式以及引入訊息佇列處理回撥分發的問題,使得支付平臺具備這幾點特性,希望能夠給你一些啟發與幫助,最後我把支付平臺整體的架構設計圖貼出來:

公眾號「後端進階」,專注後   
 
 </div> 
 <div class=

相關推薦

支付平臺架構設計一些思考

微信公眾號「後端進階」,專注後端技術分享:Java、Golang、WEB框架、分散式中介軟體、服務治理等等。 老司機傾囊相授,帶

無伺服器架構一些看法

作者: Will James 譯者: 大愚若智 我想通過本文簡單談談自己對奧斯丁 Serverlessconf 大會上所涉及主要議題的看法。這次活動讓我受益匪淺,還見到了不少行業牛人,萬分感謝 A Cloud Guru 舉辦的這次活動。此外我還領到了很多新 T 恤,吃了美味的甜甜圈,拜訪了住在奧斯

架構設計---對於架構一些思考

  其實說到架構的話,我個人覺得沒有什麼可以說的,無論是以前常說的SOA,還是現在流行的微服務,其實無非就是CAP原理的一些運用而已(可伸縮、可擴充套件、容錯),無非就是犧牲可用性獲取一致性,或者一致性換取可用性,然後在這個過程中需要考慮容錯的問題的而已,具體的可以百度下Consist

移動端架構思考

本文由玉剛說寫作平臺提供寫作贊助,版權歸玉剛說微信公眾號所有 原作者:Mr.s(豬_隊友) 版權宣告:未經玉剛說許可,不得以任何形式轉載 架構就像是一場進化史,根據不同時期的需求,演變出不同的架構,車輪滾滾,到今天,移動端框架百花齊放,讓人目不暇接。但是其中的本質是磨滅不了的,換

平臺架構

ges 架構 alt src ima bsp .com nbsp img 對賬平臺架構 指令 數據源 對賬結果 對賬平臺架構

博客網站的一些思考

table 也有 borde csdn 定制 pan 目前 編輯器 廣告 對博客網站的一些思考 本篇文章只討論我曾經使用過的博客網站,有新浪、QQ空間、CSDN、博客園。 博客網站對比 QQ空間 QQ空間日誌目前有訪問權限,不便於分享

大快大數據平臺架構設計的構成模塊

大數據平臺架構設計 大數據平臺架構 大數據架構設計 大數據也不是近幾年才出現的新東西,只是最近幾年才真正意義上變得熱門、火爆!而這要得益於互聯網信息技術的快速發展,網絡改變世界、改變生活,大數據技術的應用讓這樣的改變更為深刻。關註大數據或者是互聯網方面新聞的人應該知道,大數據已經上升到了國家戰略的

主流Paas雲平臺架構設計思想

提供簡便的海量連線、雲端儲存、訊息分發和大資料分析等優質服務,從而降低物聯網企業和個人(創客)的研發、運營和運維成本,使物聯網企業和個人(創客)更加專注於應用。 高併發可用 支撐高併發應用及終端接入,保證可靠服務 提供高達99.9%的SLA服務可用性 多協議接入

VUE學習筆記(一) --VUE作用域的一些思考

我學習有一個習慣,就是在用的時候一定要搞清楚一些基本問題,要不然稀裡糊塗的,腦子裡沒有一根清晰的線,總感覺是一團亂。所以學習筆記裡不會有什麼語法之類的,這些在各大教程裡都講的很清楚,在這裡只記錄一些我自己的思考和理解,如果有不對的地方,歡迎路過的大神幫忙指點。 1.VUE中,作用域及作用範圍

一次架構設計的總結和反思

  最近做了一次架構(流程)的設計,簡單來說,是設計一個流程,提供相應的API,方便其他程式設計師將業務邏輯逐步遷移到另一套框架。在完成這次設計的過程中,還是有許多經驗、教訓,值得思考和記錄。其實,這些經驗總結,可能在其他地方看到過,也聽別人分享過,不過只是“夫子言之,於我心有慼慼焉”,只有當自己親身經歷過,

網易考拉規則引擎平臺架構設計與實踐

此文已由作者肖凡授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 背景 考拉安全部技術這塊目前主要負責兩塊業務:一個是內審,主要是通過敏感日誌管理平臺蒐集考拉所有後臺系統的操作日誌,資料匯入到es後,結合storm進行實時計算,主要有行為查詢、資料監控、事件追溯、風險大盤等功能;一個是

微服務架構:基於微服務和Docker容器技術的PaaS雲平臺架構設計(微服務架構實施原理)

基於微服務架構和Docker容器技術的PaaS雲平臺建設目標是給我們的開發人員提供一套服務快速開發、部署、運維管理、持續開發持續整合的流程。平臺提供基礎設施、中介軟體、資料服務、雲伺服器等資源,開發人員只需要開發業務程式碼並提交到平臺程式碼庫,做一些必要的配置,

call與apply的一些理解

call與apply: call與apply最重要的一個作用就是改變函式內的上下文(其實就是改變函式內this的指向) 如果不是一個物件內的方法 this均為當前window物件(可自行在控制檯下測試): fu

Agile中scrum的一些看法

這已經是第4個sprint了,可是我發現很多人對於Agile還是不太懂,而且最可悲的是scrum master,著實令我覺得很失望。我發現他們中的好多人都只是用了一個形式,比如scrum裡面要求有plan meetin

分享 ASP.NET vNext 的一些感受,也許多年回過頭看 So Easy!

寫在前面 閱讀目錄:   ASP.NET vNext 釋出已經過去了一個多月的時間,釋出詳情請訪問:振奮人心吶!關於下一代.NET——ASP.NET vNext 的更多說明,當時看這完篇新聞的第一感覺就像文章標題一樣“振奮人心”,其實每個人都有自己的感受,對於我來說,ASP.NET vNext 最

輕鬆監控上萬臺伺服器:企業運維監控平臺架構設計與實踐指南

一、Cacti/Nagios/Zabbix/centreon/Ganglia之抉擇 1、cacti Cacti是一套基於PHP,MySQL,SNMP及RRDTool開發的網路流量監測圖形分析工具。 簡單的說Cacti 就是一個PHP 程式。它通過使用SNMP 協議獲取遠端網路裝置和相關資訊,

國產作業系統發展的一些思考

跟行業內的朋友交流,對國產作業系統的開發和推廣,有一些個人的觀點,分享出來,歡迎朋友們批評和討論。以下是我個人的一些思考,基於個人對行業的粗淺理解,以及個人在推動物聯網作業系統時遇到的問題的總結。觀點不一定準確,有的甚至有些偏激,目的在於交流碰撞,“拋磚引玉”,以形成更好的思

動態規劃問題的一些思考

HDOJ刷了一些動態規劃(DP)問題,做些總結. 1 序列 目前看來,所有的動態規劃問題基本上都存在一個序列,序列中的元素可以按照某種順序唯一地排序.更抽象地說,排序的方式通常是這些元素在某個事件發生過程的時間軸上的位置. 我們說”序列”而非”集合

iOS開發移動平臺架構設計

http://www.cnblogs.com/iOS-Blog/archive/2013/04/24/3039482.html 表示層:UIkit Framework 檢視 控制器 控制元件 事件處理 業務邏輯層:框架 各種封裝的函式或者方法 資料持久層:訪問SQ

淺談DDD領域驅動設計的理解

從遇到問題開始 當人們要做一個軟體系統時,一般總是因為遇到了什麼問題,然後希望通過一個軟體系統來解決。 比如,我是一家企業,然後我覺得我現線上下銷售自己的產品還不夠,我希望能夠在線上也能銷售自己的產品。所以,自然而然就想到要做一個普通電商系統,用於實現線上銷售自己企業產品的目的。 再比如,我是一家網際網