如何做一個對賬系統(tǒng)
在互聯(lián)網(wǎng)行業(yè)中只要涉及到支付,必然就會有對賬的需求,幾乎所有互聯(lián)網(wǎng)公司的業(yè)務中多多少少的都會涉及到支付,大一點的公司甚至都標配有了自己的第三方支付公司,因此對賬具有普遍性。對賬系統(tǒng)是支付體系中最重要的一環(huán),也是保證交易、資金安全的***一道防線。在大多數(shù)的互聯(lián)網(wǎng)公司中,一般都會有獨立的對賬系統(tǒng)來處理,比如:電商平臺、互聯(lián)網(wǎng)金融、第三方支付公司等。
對賬是支付系統(tǒng)中的一環(huán),因此在對賬前我們先了解一下相關的業(yè)務知識
業(yè)務知識
什么是對賬
傳統(tǒng)的對賬就是核對賬目,是指在會計核算中,為保證賬簿記錄正確可靠,對賬簿中的有關數(shù)據(jù)進行檢查和核對的工作。在銀行或者第三方支付中,對賬其實是對一定周期內的交易進行雙方確認的過程,一般都是在第二天銀行或者第三方支付公司對前一日交易進行清分,生成對賬單供平臺商戶下載,并將應結算款結算給平臺商戶。在往下一層,在互聯(lián)網(wǎng)金融行業(yè)或者電商行業(yè)中,對賬其實就是確認在固定周期內和支付提供方(銀行和第反方支付)的交易、資金的正確性,保證雙方的交易、資金一致正確。
廣義的對賬,所有跨應用的數(shù)據(jù)交互,理論上都應該進行對賬。所以對賬也可以分為信息流對賬,資金流對賬。信息流對賬也一般用在自己內部系統(tǒng)的對賬,比如支付系統(tǒng)的支付數(shù)據(jù)和業(yè)務系統(tǒng)的業(yè)務數(shù)據(jù)進行對賬,保證資金交易和業(yè)務交易的一致性。資金流對賬也就是支付系統(tǒng)和銀行或者第三方支付系統(tǒng)之間的資金交易對賬。
對賬方式
- 單向對賬:一般拿第三方支付機構或銀行流水,與自己系統(tǒng)進行對賬,防止出現(xiàn)掉單問題;
 - 雙向對賬:兩個應用間的流水進行雙向核對,如訂單與財務系統(tǒng),既要保證財務系統(tǒng)支付成功的記錄,訂單系統(tǒng)也是成功的;也要確保訂單系統(tǒng)記錄成功的記錄,財務系統(tǒng)也成功。
 
我們一般采用雙向對賬的方式進行對賬
對賬相關的問題
不同系統(tǒng)日切點不一致問題:滾動對賬
差錯處理:補賬,補償(退款)
相關概念
軋帳和平帳
每一筆交易,都要做到各參與者的記錄能夠吻合,沒有偏差。對賬系統(tǒng)的工作,是發(fā)現(xiàn)有差異的記錄,即軋帳;然后通過人工或者自動的方式,解決這些差異,即平帳。
長款和漏單
在以平臺交易為基準的情況下和銀行對賬,發(fā)現(xiàn)周期內的交易,平臺有此訂單而第三方支付中沒有訂單,成為平臺長款。平臺長款一般是由于用戶在支付的時候跨天的情況,比如用戶在23:58分創(chuàng)建了訂單,在第二天的凌晨00:03分進行了支付。在以銀行交易為基準的情況下對賬,銀行有此訂單而平臺無此訂單,即為平臺漏單。平臺漏單很少見,一般直接轉人工處理。
賬戶體系
在一般的支付體系中會分為登錄賬戶和支付賬戶,支付賬戶指用戶在支付系統(tǒng)中用于交易的資金所有者權益的憑證;登錄賬號指用戶在系統(tǒng)中登錄的憑證和個人信息。一個用戶可以有多個登錄賬戶,一個登錄賬戶可以有多個支付賬戶,比如零錢賬戶、儲值卡賬戶等。一般來說,支付賬戶不會在多個登錄賬戶之間共用。對賬的交易一般都是支付賬戶參與交易。
交易與賬戶
賬戶設置,一般是從交易開始的。 交易的實現(xiàn)必須有賬戶的支持,賬戶是交易的基本構成元素。 從支付系統(tǒng)的角度,交易中涉及到的資金流是資金從一個賬戶流向另一個賬戶。 發(fā)起交易的一方,被稱之為交易主體,他可以是一個人,也可以是一個機構。
清算和結算
清算主要是指不同銀行間的貨幣收付,可以認為是結算進行之前,發(fā)起行和接收行對支付指令的發(fā)送、接收、核對確認,其結果是全面交換結算工具和支付信息,并建立最終結算頭寸。
結算是指將清算過程產(chǎn)生的待結算頭寸分別在發(fā)起行、接收行進行相應的會計處理,完成資金轉移,并通知收付雙方的過程。當前,大多數(shù)銀行結算業(yè)務的完成主要通過兩類賬戶:一是銀行間互相開立的代理賬戶,二是開立在央行、獨立金融機構如銀聯(lián)、或者第三方支付機構的賬戶。
清算:計算各方應收應付錢款的時間與金額。結算:根據(jù)清算的結果在指定的時間對各方進行實際的資金轉移操作
資金池
用戶備付資金(如充值)統(tǒng)一放在企業(yè)的銀行賬戶中,企業(yè)可以隨意支配這些資金,即為資金池。與之對應的是第三方托管,用戶備付資金是放在企業(yè)在第三方支付機構為用戶開設的虛擬賬戶中,企業(yè)無法隨意取出這些資金?,F(xiàn)在互聯(lián)網(wǎng)金融全面要求接入銀行存管,就是銀行會為每個用戶創(chuàng)建一個資金賬戶來保護用戶的資金,互聯(lián)金融公司不能隨意劃撥這些資金賬戶中的金額。
對賬系統(tǒng)
對賬設計
對賬系統(tǒng)的設計階段,將對賬系統(tǒng)分為四個模塊,每個模塊的負責自己的職能。
- 文件獲取模塊:下載或者讀取各渠道對賬文件
 - 文件解析模塊:創(chuàng)建不同的解析模板,根據(jù)渠道和文件類型獲取對應的解析模板進行解析
 - 對賬處理模塊:對賬的業(yè)務邏輯處理
 - 差錯處理模塊:處理差錯池中的訂單
 
一般會設計一個定時任務,每天固定的時間點觸發(fā),定時驅動調度類分別調用四個模塊來處理對賬。也有的銀行會主動的推送對賬單,再通過http回調來觸發(fā)對賬流程。
對賬算法
***程:
1、從上游渠道(銀行、銀聯(lián)等金融機構)獲取對賬文件,程序逐行解析入庫;
2、在程序處理中,以上游對賬文件的表為基準,程序逐行讀取并與我們系統(tǒng)的交易記錄對比賬務記錄(有賬務系統(tǒng)情況下,合理方案應該是于賬務記錄)對比,查找出差異記錄;
3、以我們系統(tǒng)的交易記錄對比賬務記錄為基準,程序逐行讀取與上游對賬文件對比,查找出差異記錄。
二、缺陷:
1、對賬過程中查詢相關數(shù)據(jù),如果數(shù)據(jù)量巨大,對數(shù)據(jù)庫性能影響較大,而且對賬邏輯擴展極為麻煩;
2、逐行比對算法效率較低,但算法上并無好的優(yōu)化余地。如果采用數(shù)據(jù)庫INTERSECT、MINUS對數(shù)據(jù)庫壓力也高;
3、在業(yè)務量大的情況下(例如有上百家上游渠道需要對,每一家都有幾十萬條交易記錄),對賬服務器及數(shù)據(jù)庫服務器負荷較高。即便采用讀寫分離,對賬時候使用讀庫,壓力一樣很大;
4、導入批量文件,逐行入庫效率較為低下(每一次都需要建立網(wǎng)絡連接、關閉連接)。
三、改進:
1、涉及網(wǎng)絡傳輸?shù)?,盡量采用批量方式操作,減少網(wǎng)絡消耗及時間消耗;
2、使用Redis等NOSQL數(shù)據(jù)庫,降低數(shù)據(jù)庫服務器的壓力。同時在擴展上也容易,一臺Redis服務器不夠,可以***制增加用于對賬用的服務器;
3、使用Redis的set集合的sdiff功能,利用Redis sdiff算法的高性能,比對上游記錄和我方記錄的差異。
對賬流程
1、下載對賬單
大多數(shù)銀行都要求接入方提供ftp服務,銀行定時將對賬單推送到接入方提供的ftp服務器上面;還有一部分銀行會提供對賬單的下載服務,通過ftp/http的都有,ftp方式居多;另外網(wǎng)銀的對賬單比較特殊,一般都需要結算登錄網(wǎng)銀的后臺管理系統(tǒng)中,手動下載,結算下載完對賬單后在導入到對賬系統(tǒng)。
技術實現(xiàn)上可以做成工廠模式,不同的支付渠道有不同的下載類,如果是http接口將文件寫入到對賬單,如果是ftp服務器,將服務器中的對賬單下載到本地帶解析的目錄中。主要涉及的代碼ftp工具類、http(s)工具類,相關IO讀寫。
技術選型上,HTTP(S)用apache httpclient即可實現(xiàn)鏈接池和斷點續(xù)傳, FTP也可以使用Apache Commons Net API。 但不管是哪一個,都需要設置重試次數(shù)和鏈接超時間。重試次數(shù)和間隔的設置需要小心,重試太頻繁,容易把服務器打死.;時間間隔太大,又會阻塞后續(xù)處理步驟。5~10分鐘是一個合適的重試間隔區(qū)間。
2、創(chuàng)建批次
創(chuàng)建批次一方面是為了防止重復對賬,另一方面需要在對賬結束的時候將對賬的結果信息存儲到批次中。
3、解析文件
解析文件主要是將下載的對賬文件解析成我們可以對賬的數(shù)據(jù)類型并且入庫。解析的文件不同渠道有不同的類型,因此也可以設計成不同的解析模板,使用工廠模式將不同格式的文件解析成可以對賬的統(tǒng)一數(shù)據(jù)類型。解析的文件類型一般包括:json、text、cvs、excle等,另外部分銀行會對賬單做加密或者提供zip打包的格式,這里就需要額外開發(fā)zip工具類和加解密工具類進行處理。
對賬文件中包含的主要信息有:商戶訂單號、交易流水號、交易時間、支付時間、付款方、交易金額、交易類型、交易狀態(tài)這些字段。
4、對賬處理
對賬處理也是對賬的核心邏輯,具體分為以下的幾個步驟來實現(xiàn):
- 查詢平臺所有交易成功的訂單
 - 查詢平臺所有的交易訂單
 - 查詢平臺緩存池中的數(shù)據(jù)
 - 查詢銀行交易成功的訂單
 - 開始以平臺的數(shù)據(jù)為準對賬,平臺長款記入緩沖池
 - 開始以銀行通道的數(shù)據(jù)為準對賬
 
以平臺訂單為基準對賬邏輯:以平臺所有交易成功的訂單為基準,遍歷銀行訂單的所有數(shù)據(jù),找出訂單號相同的訂單,對比訂單的金額、手續(xù)費是否一致。如果一致跳過;如果不一致,平臺訂單進入差錯池;如果在銀行訂單中沒有找到此筆交易,訂單進入緩存池,記錄平臺長款。同時統(tǒng)計對賬相關金額和訂單數(shù)。
以銀行訂單為基準對賬邏輯:以銀行的交易數(shù)據(jù)為基準,遍歷所有平臺的交易(包括未成功的訂單),找出訂單號相同但支付狀態(tài)不一致的訂單,在進行對比金額存入差錯池。如果沒有在平臺的交易中找到此訂單,再從緩存池中遍歷查找,找到對應的平臺訂單驗證金額是否一致,不一致進入差錯池。如果在緩存池匯中依然沒有找到對應的訂單,直接進入差錯池,記錄平臺漏單。同時統(tǒng)計對賬相關金額和訂單數(shù)。
5、對賬統(tǒng)計
根據(jù)對賬處理中,統(tǒng)計的相關信息包括:對賬完成時間、對賬是否成功、平賬的金額和訂單數(shù)、差錯的金額和訂單數(shù)、緩存池金額和訂單數(shù)等。
6、差錯處理
在一般系統(tǒng)中,差錯處理分為兩種,一種人工來處理,一種系統(tǒng)自動來處理。
主要有如下情況:
- 本地未支付,支付渠道已支付。這主要是本地未正確接收到渠道下發(fā)的異步通知導致。 一般處理是將本地狀態(tài)修改為已支付,并做響應的后續(xù)處理,比如通知業(yè)務方等。
 - 本地已支付,支付渠道已支付,但是金額不同,這個需要人工核查。
 - 本地已支付,但是支付渠道中無記錄;或者本地無記錄,支付渠道有記錄。在排除跨日因素外,這種情況非常少見,需要了解具體原因后做處理。
 
示例代碼
網(wǎng)上的對賬系統(tǒng)的開源代碼不是很多,但有一家還不錯:龍果支付。龍果支付中有比較完整的對賬流程,代碼中以微信、支付寶的對賬單為例寫了對賬的流程,大家可以參考。
- roncoo-pay
 
【本文為51CTO專欄作者“純潔的微笑”的原創(chuàng)稿件,轉載請通過微信公眾號聯(lián)系作者獲取授權】


















 
 
 









 
 
 
 