訂單支付

目錄

前言

支付系統的作用

核心流程

架構圖

代碼流程

線程池中處理髮送消息到MQ、持久化的數據庫

支付成功後,消息分發流程圖

​訂單作爲消費者消費消息

測試



前言

文章中的圖片和在摘錄不是來自一篇文章,所以細節不是完全對應。可借鑑的是開發的思路:

  1. 從整體的功能模塊的使用;
  2. 到核心流程;
  3. 到系統實現的架構;
  4. 再到代碼流程(可以採用序列圖)。

前兩點是業務需求,後兩點是功能實現。

支付系統的作用

https://www.cnblogs.com/veblen/p/10992167.html

 

核心流程

http://www.woshipm.com/pd/1392102.html

訂單支付:

用戶支付完訂單後,需要獲取訂單的支付信息,包括支付流水號、支付時間等。支付完訂單接着就是等商家發貨,但在發貨過程中,根據平臺業務模式的不同,可能會涉及到訂單的拆分。

架構圖

https://blog.csdn.net/egworkspace/article/details/78900438?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

跟着標註的序號,可以跟蹤到一個支付請求是如何發起的(Sequence Diagram就免了),流程描述如下:

  1. Submit a pay task,當客戶端需要發起支付的時候,起始是向支付任務隊列裏面加入了一個新的支付任務,這個過程是異步實現的。先根據客戶端提交的參數,構造好一個新的支付任務;
  2. Offer a task,開啓一個異步任務,做的事情就是向MQ中添加一個新的支付任務,等待被消費;
  3. Pay task description,一旦異步任務被成功創建,將會把第一步構造好的支付任務信息直接return給客戶端;
  4. Poll a task,與此同時,支付任務的消費者將新的支付任務poll下來進行執行;
  5. Send a pay request,這一步需要根據實際情況而定。並不是所有的支付請求都要先經過第三方支付平臺,比如支付寶;而對於微信,則還需要憑支付參數申請一個prepay_id,再經由客戶端發起支付;
  6. Response,沒什麼好說的,第三方渠道返回的支付必要參數;
  7. Cache result,至此,一個支付任務可以算是完成了,可以將任務的執行結果(無論成功與否)緩存在Redis中,隨時等待客戶端的回訪;
  8. Query result,客戶端在提交支付任務後,間隔一定時間後(建議2~3s),發起一個結果查詢的請求;
  9. Query,直接進Redis查找結果;
  10. Synchronize,這是一個異步的操作,將支付任務的執行結果“順便”同步到MongoDB中,並刪除Redis中緩存的任務執行結果。持久化到MongoDB主要是爲後續的容錯,重試,數據分析等提供落地的數據源;
  11. Return,由Redis返回給應用服務器;
  12. Return payment,應用服務器再將最終的支付對象返回給客戶端。

讓我們更深入一點,我們來看三張Class Diagram:

① 先說說支付任務(PayTask)部分。PayTask和Payment兩個都是MongoDB中的Document對象,但在任務執行期間,PayTask是用Redis進行緩存的,方便客戶端隨時發起Query,任務執行成功後,會生成Payment對象,最終PayTask和Payment都會持久化到MongoDB中。在PayService中,有對支付任務的一些基本操作,包括任務提交,取消,重試,構建等等。

② 再說說任務的執行(runner)。這部分和RabbitMQ緊密相關,一旦一個支付任務形成了,就會放入任務執行隊列中,由消費者取出執行。在TaskRunner中,有兩個基本的接口方法:run(task)、retry(task),分別是執行任務和重試任務。在AbstractPayTaskRunner中已經封裝好了這兩個方法,繼承AbstractPayTaskRunner需要實現doTask方法,從返回值可以看出,這個過程是異步化的。關於Retry機制,用戶可以設置重試與否,一旦設置了TaskInfo.needRetry=true(不出意外,默認就是允許重試),就啓用了Retry機制。還可以設置重試的次數(TaskInfo.retryTimes),默認三次,分別間隔1s,2s,3s,間隔時間以公差爲1的等差數列組成。當然不會讓用戶無限重試,系統內置有一個最大重試次數,最大重試次數內置爲5次。

爲什麼是5次?

你感受一下,1s,2s,3s,4s,5s,整個請求鏈條就被拉長到了15s,這對客戶端簡直就是災難了!!

代碼流程

創建支付

 

線程池中處理髮送消息到MQ、持久化的數據庫

支付成功後,消息分發流程圖

訂單作爲消費者消費消息

測試

在測試程序中調用sendMessage

因爲發送消息是在線程池中,當測試程序(主程序)停止運行,線程池也就停止運行,所以,爲了讓主程序不停止,在方法末尾加上:System.in.read();

System.in.read()可以實現輸入字符,返回字符的Unicode碼,但是缺點是隻能輸入一個字符
System.in.read() 返回的是輸入數值的 ASKII 碼(一個 int 整數)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章