從業務事件到複式入賬:一張流程圖和一套前提
把收款、佔用、結算、退款和未知結果放進同一條賬務流程,說明複式賬上線前需要準備什麼,以及最後應該達到什麼效果。
複式賬的難點通常不在「借方加一行、貸方加一行」,而在於業務事件什麼時候已經足夠確定,可以進入賬本。授權通過、通道接受、商戶請款、銀行到賬和頁面顯示成功,可能是五個不同的時刻。
下面用一條簡化流程說明如何把業務狀態、賬務狀態和對賬狀態分開。流程圖是系統設計示意,不是某個國家或企業的會計制度。
業務事件先不要直接改餘額
一筆支付先進入業務事件層,保留穩定的業務引用、訂單號、階段、賬戶、原幣金額、幣種、來源和發生時間。每次通知的投遞編號也要保留,但它可能隨重試改變,不能代替業務引用。服務可以先把事件標記為 received、pending 或 unknown,不要因為收到一條回調就直接把賬戶餘額改成一個新數字。
事件層保存「外部發生了什麼」和「我們收到了什麼證據」。賬本層把已經滿足當前階段入賬規則的事件轉換為憑證和分錄。餘額層提供快速查詢,但應從已過賬分錄或可核驗的快照計算,不承擔事件解釋。
這樣做的好處是,重複通知可以被識別,遲到的成功可以回到原業務,未知結果可以停留在待核對,而不是被迫選擇成功或失敗。
校驗、資格和資金佔用
先驗證來源與對應關係:回調簽名或其他可信來源證明是否有效,通道賬戶是否映射到正確租戶和主體,業務引用、金額、幣種與原請求是否匹配。再檢查賬戶狀態、金額精度、訂單方向和允許的狀態遷移。跨境或多幣種業務還要檢查報價、手續費、限額和賬戶資格。
發起需要預留資金的授權時,把可用額度檢查和佔用寫入作為同一受控操作,覆蓋共享資金池的併發請求。請款或成功回調不能再佔一次,而應按實際金額消耗已有佔用;部分請款、超額請款和剩餘釋放分別按規則處理。佔用成功只說明資金暫時不能被其他操作使用,不等於收入確認或外部結算完成。
如果外部請求已經發出,本地失敗或超時不能直接釋放佔用。只有確認外部未執行、失敗或已撤銷,並滿足釋放規則,才做關聯釋放;結果未知時保留受控佔用並繼續查詢,不能把資金提前交給下一筆交易。
校驗失敗時記錄具體的 reasonCode、requestId 和關聯引用,區分賬戶關閉、幣種不支持、額度不足和重複階段。保留脫敏的決策與資金變化證據,便於之後復盤。
生成並提交一張憑證
先判斷「這個業務階段有什麼已經確認的權利義務」,再生成憑證。已確認的請款可能先借記通道應收、貸記商戶應付款,之後銀行到賬再以另一張憑證結清應收;不必等全部外部結算完成才記任何賬。但一條「已受理」通知不能單獨證明銀行存款已經增加。
賬本服務按事件類型和版本化的科目映射生成憑證,再強制檢查:至少兩條分錄且借貸都存在,同憑證、賬簿、主體和幣種內借貸相等,賬戶與期間允許過賬,業務階段冪等鍵和憑證號滿足唯一約束。失敗就不提交,進入有明確原因的異常隊列。
這張圖可以按七步閱讀:
- 校驗可信來源、主體、欄位和引用,不合格的事件記錄原因並停止。
- 按穩定業務引用和階段冪等:已提交的相同請求返回原結果,載荷衝突拒絕;待定事件補充證據後繼續判斷。
- 檢查本階段的入賬證據;不足則停在未知,經查詢、可信回調或核對取得新證據後回到本步驟。
- 證據充分後按版本化映射生成憑證,不把下一階段的資金結果提前寫入。
- 檢查借貸、幣種、主體、賬戶、期間和唯一約束;失敗整張不生效。
- 在本地事務中提交憑證、全部分錄、冪等結果及資金判斷所需的餘額或佔用變化,返回可查詢的 postingId。
- 將賬內記錄與外部報告、銀行流水對賬;差異複核後產生關聯調整,保留原記錄。
「原子」是結果要求:併發請求不能看到互相矛盾的中間狀態,憑證不能只寫一半。跨服務通知可以用事務發件箱傳遞並由消費方冪等處理;遠程通道的最終結果繼續透過狀態機、查詢和對賬收斂。
異步結果要保留未知
外部通道可能先受理、之後回調成功,也可能請求超時但實際已經扣款。本地響應、通道響應、賬本提交和外部結算要分別記錄,不能互相替代。
結果不確定時保留原事件、證據和受控佔用,使用支持的查詢、可信回調、結算報告和銀行流水繼續收斂,並明確負責人、重試節奏和升級時限。亂序的舊狀態不能覆蓋已確認的新狀態;遲到的證據應推進正確階段,而非重新記一次原階段。
待核對狀態不等於可以任意使用待核對科目。銀行到賬已有證據但歸屬不明時,可以按批准規則借記銀行、貸記暫收;連資金是否發生都不確定時,先保存未決事件,不能用平衡憑證製造已經到賬的事實。之前已確認的應收等分錄仍保留。
對賬要把內部事件、賬本分錄、外部引用、手續費和實際到賬匹配起來。差異記錄類型、金額、幣種、時間範圍和處理狀態,不用一條沒有來源的手工加減抹平。
退款、沖正和修復
退款、授權撤銷、過期釋放和結算失敗分別有自己的業務階段,並引用原始交易。不要刪除原憑證,也不要把舊分錄改成「看起來正確」的數字。
退款根據當時的權利義務和資金位置記賬。已結算給商戶的款項,退款可能需要確認商戶應收或其他已約定的追償關係,再記錄實際退款;不能機械地把最初收款憑證整張反向。部分退款累計檢查上限,手續費是否退回單獨表達。科目映射錯誤則保留原憑證,按授權流程生成沖正或調整,並記錄原因、審批人和關聯關係。
同一業務引用加階段及必要的子事件引用應只產生一次對應的資金變化。不同投遞編號仍可能是同一業務;不同部分請款或退款也不能因金額相同就合併。規則升級不構成重記同一事件的理由。
前提和應該達到的效果
上線前至少需要準備:
- 賬戶和主體邊界:平台、客戶、商戶、銀行或清算方分別是誰。
- 事件字典與證據門檻:授權、佔用、請款、清算、到賬、退款、沖正和費用分別何時確認。
- 科目映射版本:每種階段、幣種和費用條件如何生成分錄。
- 金額規則:精度、捨入、匯率來源、費用承擔方和跨幣種橋接。
- 一致性機制:穩定業務標識、冪等約束、併發佔用、原子提交、權限和期間控制。
- 切換與營運機制:核對期初、盤點在途與未決、確定唯一寫入方,以及對賬資料、異常負責人和升級時限。
預期效果是每個狀態都能解釋:隨機抽一筆交易,可以還原事件、決策、佔用、憑證、外部結果和對賬;重複投遞不重複入賬;超時停在未知;退款與沖正能回到原記錄;餘額可按賬戶和幣種重算;報表把待核對金額和已結算金額分開。
驗收可用重放同一事件、併發爭用同一資金池、憑證寫入中斷、亂序回調和已結算退款等場景檢查。它們是待實現賬本的目標,本站只展示知識文檔,沒有運行資金賬本或執行這些資金場景。前提不足時先做只讀流水和影子對賬,再逐步擴大自動過賬範圍。