千萬級支付對賬系統怎麼玩(上篇)?

樓下小黑哥發表於2022-01-16

上篇文章聊到了對賬系統業務邏輯以及千萬資料集對賬系統存在的難點,這篇文章就來聊下千萬級資料集下對賬系統實現方案。

首先我們先來看下對賬整體時序圖,先有個印象:

下面整篇文章將會圍繞上面時序圖開始講解,由於文章篇幅過長,所以文章將會拆分成上下兩部分。

資料平臺

上次文章中提到,千萬級資料需要使用 Hive,Spark等相關大資料技術,這就離不開大資料平臺的技術支援。

簡單聊下我們這邊大資料平臺DP (Data Platform),它提供使用者大資料離線任務開發所需要的環境、工具以及資料,具有入口統一性、一站式、簡化hadoop本身的複雜性、資料安全等特點。

DP 平臺提供功能如下:

  • 資料雙向離線同步,MySQL 與 Hive 互相同步
  • 大資料離線計算,支援SQL(SparkSQL/HiveSQL/Presto)形式處理各類的資料清洗、轉化、聚合操作,也支援使用MapReduce、Spark等形式,處理比較複雜的計算場景
  • 即時的SQL查詢,允許使用者即時的執行SQL、檢視執行的日誌和結果數以及進行結果資料的視覺化分析
  • 資料包表

那本篇文章不會涉及具體的大資料技術相關的實現細節,相關原理(主要是我們也不會~),主要聊下對賬系統如何聯合 DP 平臺實現完整資料對賬方案。

對賬系統概覽

開頭的時序圖,我們可以看到整個對賬過程設計好幾個業務流程,那在這裡對賬系統內部將會維護一個流程狀態機,當前一個流程處理結束之後,下一個流程才能被觸發。

由於當前對賬系統實現方案,涉及對賬系統與 DP 平臺,對賬系統目前沒辦法呼叫 DP 平臺觸發任務,但是 DP 平臺可以通過通過 HTTP 介面呼叫對賬系統。

所以當前流程觸發的方式使用的是定時任務的方案,每個流程有一個單獨的定時任務。

對賬系統內的定時任務觸發的時候,將會判斷當前流程是否已經到達執行條件,即判斷一下當前任務的狀態。

每個定時任務觸發時間人為設定的時候,岔開一兩分鐘,防止同時執行。

DP 平臺使用自帶排程任務,對賬系統無法控制 DP 任務的執行。

DP 平臺定時任務可以通過執行 Scala 指令碼程式碼,呼叫對賬系統提供 HTTP 查詢介面,通過這種方式判斷當前流程是否已經到達執行條件。

下面詳細解釋一下每個流程。

初始化對賬任務

對賬系統依靠對賬任務記錄推動流轉,目前每天凌晨將會初始化生成對賬任務記錄,後續任務流轉就可以從這裡開始。

對賬系統維護一張對賬核對規則表:

對賬核對規則表關鍵欄位含義如下:

  • channel_code 渠道編碼,每個支付渠道將會分配一個唯一渠道編碼,例如微信,支付寶
  • biz_type 業務型別,例如支付,退款,提現等
  • status 是否生效

每次對接新的支付渠道,對賬配置規則需要新增核對規則。

初始化對賬定時任務將會查詢核對規則表中所有的生效的配置規則,依次生成當天的對賬任務記錄:

對賬任務記錄部分欄位與核對規則表含義一樣,不再贅述,其他欄位含義如下:

  • bill_date 賬期,一般 D 日對賬任務核對 D-1 資料,所以賬期為 D-1 日
  • batch_no 對賬批次,生成規則如下:賬期+渠道編碼+ 001
  • phase,當前對賬任務處於階段,根據上面對賬流程可以分為
    • 初始化
    • 資料收集
    • 存疑處理
    • 資料核對
    • 二次存疑處理
    • 資料彙總
    • 差錯資料推送
  • error_reason 錯誤原因

初始化對賬任務結束之後,對賬任務流程推動到第二階段,資料收集。

資料收集

資料收集階段,收集兩端待核對的資料,為後面的資料核對任務提供核對資料。

資料收集階段分為兩部分:

  • 本端資料收集,即自己方產生的支付資料
  • 對端資料收集,即三方渠道產生支付資料

本端資料收集

本端資料,是自己業務產生的支付資料,這些資料原本存在各個業務的資料庫中。

對賬系統獲取這些支付資料,一般有兩種方式:

  • 查詢,對賬系統主動拉取
  • 推送,對賬系統監聽獲取資料

查詢資料方式上篇文章也聊到過,資料量小的情況下,沒什麼問題。一旦資料量變大,查詢效率就會變低。

所以這裡我們採用推送的方式,對賬系統監聽各個業務資料表 binlog,每當業務資料發生變動,對賬系統就可以接受到 binlog 訊息。

對賬系統接受到 binlog 訊息,將會判斷當前訊息是否需要過濾,是否已經支付成功等等,滿足條件之後,binlog 訊息將會插入本端資料表中,表結構如下:

本端記錄表關鍵欄位含義如下:

  • channel_code 渠道編碼,每個支付渠道將會分配一個唯一渠道編碼,例如微信,支付寶
  • biz_order_no 本端支付流水號
  • bill_date 賬期
  • status 狀態
  • is_check 對賬狀態,0-未核對,1-已核對
  • trade_amount 支付金額
  • channel_order_no 三方渠道支付單號
  • merchant_no 商戶號
  • sub_merchant_no 子商戶號

上面展示的支付記錄表結構,根據業務型別不同,本端其實還有退款記錄表,提現記錄表等。

這裡設計的時候,實際上也可以將所有業務資料放在一張表中,然後根據業務型別欄位區分。

對端資料收集

對端資料,就是第三方支付渠道產生支付資料,一般 D 日產生交易之後,D+1 日第三方渠道將會生成一個對賬檔案。

對賬系統需要從對端提供的對賬檔案獲取對端資料。

渠道的對賬檔案,下載方式,檔案型別存在很大的差異,每次接入新的支付渠道,這裡需要經過新的開發。

對端資料這裡維護了一張渠道下載配置表,對端資料收集的時候將會獲取所有可用配置:

渠道下載配置表關鍵欄位含義如下:

  • mch_id 三方渠道分配的商戶號
  • type 下載型別
    • FTP
    • SFTP
    • HTTP
  • download_param 下載的配置引數,比如 ftp 的地址,登入密碼,下載地址等。

對賬檔案下載成功之後,需要根據檔案型別進行解析,最後轉化自己的需要的對賬資料入庫。

對端資料表結構如下:

上面關鍵欄位與本端記錄表類似,額外新增欄位:

  • channel_fee 渠道手續費,用於統計渠道收的手續費

同樣渠道記錄表根據根據業務型別也分為退款渠道記錄表,提現渠道記錄表等,同樣也可以合併成一張表,根據業務型別區分。

對端資料收集階段,由於拉取三方渠道的對賬檔案,那有時候渠道端存在異常,將會導致對賬檔案下載延遲,從而導致其他任務也出現的相應的延遲。

這一點是整個對賬流程中,相對不可控的問題。我們需要在對賬流程設計中考慮這一點。

對賬檔案下載解析成功入庫之後,對賬流程將會流轉到下一個流程存疑資料處理。

存疑資料處理

講解這個流程之前,先給大家解釋一下什麼是存疑資料?

正常支付過程中,會存在一個兩邊賬期不一致的問題,比如說本端資料支付時間是 2021 年 12 月 28 日 23 點 59 分 59 秒,那麼本端認為這筆支付交易賬期是 2021 年 12 月 28 日。

然而這筆支付傳送給三方渠道之後,三方渠道支付成功的時間已經是 2021 年 12 月 29 日 0 點 0 分 2 秒,三方渠道支付賬期記為2021 年 12 月 29 日。

這種情況下我們這邊記錄賬期是2021 年 12 月 28 日,但是第三方渠道這筆記錄是 2021 年 12 月 29 日,所以 2021 年 12 月 28 日對賬單上沒有這筆支付記錄,這就導致一筆差異資料(一端有/一端無)的情況。

上面這種情況就是典型因為日切問題導致差異。

但是我們知道 2021 年 12 月 29 日對賬單上肯定會包含這筆,所以我們可以先把這筆差異資料掛起,當做存疑資料,等到2021 年 12 月 29 日賬期對賬的時候,對方賬單包含這筆,當天就能核對成功,這就解決這筆差異資料。

所以說存疑資料,就跟其字面意思一樣,當這筆資料當前處理不了的時候,那就現放著,不做定論,過一天我再嘗試處理一下。

除了上面日切問題導致的差異資料以外,還有一些情況:

  • 網路問題,導致兩邊訂單狀態不一致。
  • 測試環境與生產環境共用一個三方渠道商戶號,測試環境產生的交易出現在對賬單裡

存疑資料分為三種型別:

  • 本端有,渠道無,即本端存在訂單資訊,渠道賬單記錄沒有訂單資訊,可能是日切導致的問題
  • 渠道有,本端無,即本端不存在訂單資訊,渠道端賬單記錄卻有訂單資訊,可能是測試環境與生產環境共用渠道引數
  • 金額不平,即雙方都存在訂單資訊,但是雙方訂單金額不一致

瞭解完存疑資料的定義,我們再來看下存疑資料處理的流程。

存疑資料將會由下面的流程中產生,這裡先來看下存疑表結構:

關鍵欄位如下:

  • batch_no 批次號
  • biz_id 業務單號
  • biz_amount 金額
  • status 0-未處理,1-已處理
  • biz_date 賬期
  • biz_type 業務型別
  • channel_code 渠道型別
  • delayed_times 延遲天數
  • merchant_no 商戶號
  • sub_merchant_no 子商戶號
  • buffer_type 存疑型別,0-本端存疑,1-渠道存疑

存疑處理過程將會撈起所有存疑表中還未處理的存疑資料,根據存疑型別反向查詢對賬資料表。例如:

  • 渠道存疑(第一天對賬,本端有,渠道無),查詢對端資料
  • 本端存疑(第一天對賬,本端無,渠道有),查詢本端資料

查詢對端/本端資料,都是根據支付流水號加業務型別查詢定位。

如果在本端/對端資料中找到,這裡還需要再對比一下金額

  • 如果金額不相等,代表單號相同,但是金額不等,將這筆移動到支付差異表
  • 如果金額相等,代表這兩筆核平,存疑表將這筆資料更新為核對成功,本端/對端資料更新為對賬成功

上面這一步比較重要,因為下面對賬核對過程主要核對要素是支付流水號+支付金額,通過這種方式收集單片賬是無法知道是因為單號不存在,還是因為金額不存在原因,具體流程可以看下下面核對流程。

如果在本端/對端資料還是找不到,那就根據渠道配置的存疑規則,如果當前已經存疑的天數大於配置渠道存疑天數,則將資料直接移動到差錯表。

如果存疑天數小於當前渠道配置天數,那就不要管,繼續儲存在存疑表,等待下一天存疑資料處理。

一般來說,日切導致的資料,存疑一天,就可以解決。但是有些渠道可能是 T+1 在對賬,這種情況需要配置的存疑天數就要長一點了。

本地存疑資料處理結束之後,下面就要開始 DP 資料處理。

總結

上篇文章主要聊了對賬流程前半部分,這幾個流程主要是為了後續 DP 平臺核對收集業務資料。

這裡存疑流程處理比較關鍵,不熟悉對賬流程的同學,這裡需要重點關注下。

下篇文章主要講下 DP 平臺對賬資料如何核對,敬請期待。

相關文章