:預(yù)付費實時扣費鏈路詳解)
簡介華為內(nèi)部技術(shù)文檔《OCS計費原理與實現(xiàn)排版后》面向電信計費研發(fā)、系統(tǒng)運維及通信專業(yè)讀者系統(tǒng)闡述在線計費系統(tǒng)的原理與落地實現(xiàn)。內(nèi)容涵蓋計費系統(tǒng)從離線到實時的演進(jìn)脈絡(luò)詳細(xì)解釋TAG、業(yè)務(wù)用量、費用項、產(chǎn)品、訂購、入帳關(guān)系等核心概念并完整梳理事件捕獲、事件處理、生成賬單、結(jié)算的計費流程。實現(xiàn)部分涉及計費引擎、數(shù)據(jù)庫、消息中間件及安全機制等關(guān)鍵組件可幫助讀者建立從原理到實際部署的整體認(rèn)知。文檔源自華為技術(shù)有限公司內(nèi)部資料保留原始章節(jié)結(jié)構(gòu)與流程圖說明對于梳理實時計費系統(tǒng)的業(yè)務(wù)邏輯與關(guān)鍵節(jié)點非常有幫助。資源包共1個文件為doc格式文檔壓縮包大小1.87MB排版后的正文便于閱讀。目前已有297人學(xué)習(xí)下載適合需要深入理解OCS機制或開展內(nèi)部培訓(xùn)的工程師參考。1. OCS計費原理與實現(xiàn)為什么預(yù)付費用戶離不開這條實時扣費鏈路客服坐席被用戶質(zhì)問余額明明還有38.6元為什么10元的流量包訂購失敗。查了一圈發(fā)現(xiàn)賬務(wù)系統(tǒng)里的余額和OCS實時余額差了正好10元——這筆錢在離線賬本里還沒扣但OCS已經(jīng)把它預(yù)占走了。OCS計費原理與實現(xiàn)講的就是這條實時扣費鏈路用戶每次上網(wǎng)、打電話、發(fā)短信網(wǎng)元都會先向OCS申請配額OCS完成鑒權(quán)、批價、扣費后才放行業(yè)務(wù)。這套系統(tǒng)適合預(yù)付費用戶的余額實時控制、套餐流量和時長的準(zhǔn)實時扣減以及需要賬務(wù)聯(lián)動同步的業(yè)務(wù)線。下面按位置、原理、落表、踩坑、驗證的順序展開新手能照著建表寫邏輯熟手可以對著排查思路核對邊界。2. OCS在計費域里的位置離線計費撐不住的地方在線計費來兜底2.1 離線計費為什么跟不上預(yù)付費話單延遲的代價離線計費的鏈路是網(wǎng)絡(luò)設(shè)備在會話結(jié)束后生成CDR話單經(jīng)過采集、清洗、批價進(jìn)入賬務(wù)系統(tǒng)最后在出賬日統(tǒng)一結(jié)算。這條鏈路的延遲通常以分鐘甚至小時計。對后付費用戶來說延遲一個月都沒問題對預(yù)付費用戶來說延遲幾分鐘就可能讓余額耗盡的用戶繼續(xù)享受服務(wù)形成欠費風(fēng)險。更麻煩的是用戶通過營業(yè)廳或App查詢余額時看到的是賬務(wù)系統(tǒng)里的“滯后數(shù)字”和實際可用的實時余額對不上投訴就來了。OCS把流程倒過來會話開始前網(wǎng)元必須先向OCS發(fā)起鑒權(quán)計費請求拿到配額才允許業(yè)務(wù)使用。配額用完網(wǎng)元再次申請申請不到業(yè)務(wù)被切斷。這樣“用多少錢由OCS現(xiàn)場決定”的模式才是在線計費的正解。OCS與網(wǎng)元之間走的是Diameter Credit-Control協(xié)議Ro接口承載在線計費請求。網(wǎng)元發(fā)出的請求叫CCRCredit-Control RequestOCS返回的叫CCACredit-Control Answer。CCR/CCA里的“CC-Request-Type”字段區(qū)分這是一次會話的初始請求、中間更新還是最終結(jié)束這套協(xié)議棧是3GPP標(biāo)準(zhǔn)定義的自研實現(xiàn)時只要把該字段和配額字段對清楚就能和設(shè)備廠商聯(lián)調(diào)。離線與在線的關(guān)鍵差異可以用一張表說清維度離線計費在線計費計費時機會話結(jié)束后會話開始前與過程中數(shù)據(jù)來源CDR話單計費請求/應(yīng)答超額控制出賬后追繳配額用盡即斷余額查詢滯后賬本實時余額典型場景后付費月結(jié)預(yù)付費語音、流量2.2 OCS、GRS、RCS在生產(chǎn)網(wǎng)里的配合方式在運營商內(nèi)部的生產(chǎn)培訓(xùn)教材里常把OCS、GRS、RCS這些網(wǎng)元縮寫畫在同一張鏈路上。很多新人被縮寫嚇住實際上它們之間的交互最終都是同一個動作網(wǎng)元發(fā)配額申請OCS回配額結(jié)果。OCS前面接的是各類業(yè)務(wù)網(wǎng)關(guān)——語音的、流量的、消息的OCS后面接的是賬務(wù)系統(tǒng)、客服系統(tǒng)和批價規(guī)則庫。一次流量上網(wǎng)會話的交互大概是這樣PGW收到用戶上網(wǎng)請求發(fā)現(xiàn)是預(yù)付費用戶先不直接放行而是向OCS發(fā)一個Initial CCR里面帶用戶標(biāo)識、業(yè)務(wù)標(biāo)識、請求的流量大小。OCS經(jīng)過批價發(fā)現(xiàn)用戶套餐里還有2GB月度流量于是回一個CCA帶“本次授權(quán)可以使用1GB有效期600秒”。PGW放行1GB。用戶跑完900MB后PGW再發(fā)Update CCROCS繼續(xù)授權(quán)下一段。這中間網(wǎng)元和OCS之間沒有任何人工賬單參與完全是機器對話?,F(xiàn)網(wǎng)實現(xiàn)里OCS內(nèi)部控制一般分成四個域批價引擎負(fù)責(zé)把業(yè)務(wù)使用量換算成金額余額中心負(fù)責(zé)統(tǒng)籌賬戶下的現(xiàn)金、贈送、套餐額度配額管理器負(fù)責(zé)決定本次下發(fā)多少配額、有效期多長話單網(wǎng)關(guān)負(fù)責(zé)把會話結(jié)束后的使用明細(xì)轉(zhuǎn)成標(biāo)準(zhǔn)CDR送給賬務(wù)系統(tǒng)。GRS、RCS這類縮寫要么是圍繞OCS的配置/規(guī)則管理能力要么是會話與資源狀態(tài)統(tǒng)計能力不必一個一個背抓住“批價余額配額”這條主線就夠了。2.3 哪些業(yè)務(wù)必須交給OCS判斷標(biāo)準(zhǔn)不是所有業(yè)務(wù)都要塞進(jìn)OCS。我一般按三條標(biāo)準(zhǔn)判斷一是業(yè)務(wù)是否需要“事前實時放行”。比如VoLTE通話、流量上網(wǎng)、短信發(fā)送用戶對實時性要求高且存在透支風(fēng)險必須在線計費。二是是否存在“配額”概念。凡是可以按時間、流量、條數(shù)切分成一段一段使用的資源都適合OCS一次性點播內(nèi)容更適合按次計費也可以走OCS的靈活配額。三是是否需要余額聯(lián)動。如果業(yè)務(wù)要保證用戶余額與可用資源強一致OCS就是正確選擇。一個反例企業(yè)專線月結(jié)業(yè)務(wù)用戶按合同月底統(tǒng)一付款業(yè)務(wù)是長期在線的沒有“配額”概念硬套OCS的話要么每個會話都下發(fā)超大配額要么頻繁中斷體驗很差。這種走傳統(tǒng)離線計費更合適。所以O(shè)CS是工具不是所有計費問題的銀彈。判斷清楚了再進(jìn)入原理層。3. OCS計費核心原理配額、會話和余額倒扣的三層模型3.1 配額是實時計費的最小單位余額不能直接當(dāng)令牌發(fā)OCS不把“余額”直接下發(fā)給網(wǎng)元。原因很實際網(wǎng)元是網(wǎng)絡(luò)設(shè)備它只認(rèn)“能用多少時間/流量”不認(rèn)“賬上有多少錢”。而且余額是總賬如果網(wǎng)元拿到總賬就直接放行用戶很可能把余額一次耗盡、甚至超額等到話單回來已經(jīng)晚了。所以O(shè)CS要把余額轉(zhuǎn)成配額Quota。配額的含義是“本次會話中網(wǎng)元最多可以用掉的量”。它可以按時間秒、按流量字節(jié)、按費用金額或按業(yè)務(wù)特定單位來定義。一次授權(quán)通常包含三要素配額大小本次允許用多少時間/流量/金額配額類型time、total-octets、input-octets、output-octets、service-specific有效期Validity Time在這個時間內(nèi)配額有效過了時間網(wǎng)元必須停用并用完的部分歸還。配額的粒度是OCS調(diào)優(yōu)的關(guān)鍵。給大了用戶可能透支給小了網(wǎng)元頻繁發(fā)請求信令壓力大。常見做法是先按套餐周期估算可用量再按“單次會話最多使用量”切分。比如一個用戶套餐里有10GB月流量OCS一般不會一次下發(fā)10GB而是按1GB或2GB一段一段給每段都帶有效期。這樣即使用戶余額突然被管控下一段配額也發(fā)不出去。3.2 會話計費的三個動作授權(quán)、更新、釋放一個典型的OCS會話跑三次交互。第一次是Initial Request初始授權(quán)。網(wǎng)元發(fā)現(xiàn)新會話向OCS申請配額。OCS做的事情依次是識別用戶、檢查用戶狀態(tài)、查可用余額/套餐余量、按資費批價、預(yù)占費用、下發(fā)配額并記錄會話狀態(tài)。預(yù)占不是真的扣掉而是把“這筆錢可能消耗掉”標(biāo)記出來避免后續(xù)其他會話重復(fù)花。第二次是Update Request中間更新。用戶在配額快用完時網(wǎng)元會先上報“上一段已經(jīng)用了多少”O(jiān)CS根據(jù)實際使用量結(jié)算上一段、再決定下一段批多少。如果余額不足OCS可以下Final-Unit-Indication告訴網(wǎng)元“這是最后一次授權(quán)”用完就停。有些實現(xiàn)里網(wǎng)元也會主動在配額沒過期但業(yè)務(wù)空閑時發(fā)更新請求把未用的配額還回來。第三次是Termination Request最終釋放。會話結(jié)束網(wǎng)元上報最終使用量。OCS計算實際費用對比之前預(yù)占的金額多退少補關(guān)閉會話狀態(tài)。這里的“預(yù)占-確認(rèn)-回沖”就是余額倒扣的基本姿態(tài)。如果只做“結(jié)束再扣”會話期間的透支持續(xù)存在OCS就退化成離線計費了。會話狀態(tài)的流轉(zhuǎn)是OCS實現(xiàn)里最容易亂的部分。每個會話在OCS側(cè)都有一個狀態(tài)常見是IDLE沒有會話、AUTHORIZED已授權(quán)、UPDATING更新中、TERMINATED已結(jié)束。網(wǎng)元每發(fā)一個請求OCS都先校驗“當(dāng)前狀態(tài)是否允許這個請求”。比如一個Initial請求如果出現(xiàn)在AUTHORIZED狀態(tài)說明網(wǎng)元重復(fù)初始化應(yīng)該直接拒絕而不是重復(fù)給配額。狀態(tài)流轉(zhuǎn)表是OCS開發(fā)里必畫的圖不畫你會在第5章的時序坑里栽跟頭。3.3 余額模型與扣費優(yōu)先級贈送、套餐、現(xiàn)金誰先扣OCS的余額不是單一大字段而是一個帶優(yōu)先級的余額集合。一個賬戶下面通常掛多種余額現(xiàn)金余額、贈送余額通常有有效期、套餐余額按流量/分鐘/條數(shù)計。扣費時要按規(guī)則排序。我常用的優(yōu)先級排序是定向贈送余額比如“夜間流量包”先扣因為有效期短不用也會過期套餐內(nèi)余額月度流量/語音分鐘其次通用贈送余額充話費贈送的錢再扣最后扣現(xiàn)金余額。每個檔位扣到不足時剩余部分從下一檔繼續(xù)扣而不是“要么全扣要么不扣”。這個邏輯叫余額分?jǐn)侽CS在預(yù)占時也要按分?jǐn)偨Y(jié)果去鎖額度。實現(xiàn)時余額表里的每一條記錄都要關(guān)系到一個配額記錄否則賬實無法核對。贈送余額和套餐余額的過期處理也是OCS的常見矛盾點。比如用戶有一筆贈送金30天后過期扣費優(yōu)先級排在套餐后面結(jié)果套餐一直夠用贈送金過期了用戶投訴“白送的為什么一句提示都沒有”。實現(xiàn)上可以在有效期到期前做提醒但提醒端到端的延遲是另一套體系不是OCS單點能解決的。在OCS內(nèi)部能做的是過期結(jié)算時生成賬單記錄供賬務(wù)系統(tǒng)后續(xù)處理。4. OCS計費實現(xiàn)四張表、三個扣費動作和一個最小接口閉環(huán)4.1 四張核心表的結(jié)構(gòu)定義OCS實現(xiàn)不管上層多花哨落庫基本離不開四張表賬戶表、余額表、配額記錄表、話單表。下面是我常用的一套MySQL風(fēng)格建表金額和流量都存整數(shù)避免浮點誤差。CREATE TABLE acc_account ( acct_id BIGINT PRIMARY KEY, brand_id INT NOT NULL, credit_class SMALLINT NOT NULL DEFAULT 0, status TINYINT NOT NULL DEFAULT 1, created_at DATETIME NOT NULL ) ENGINEInnoDB; CREATE TABLE acct_balance ( balance_id BIGINT PRIMARY KEY, acct_id BIGINT NOT NULL, balance_type TINYINT NOT NULL COMMENT 1現(xiàn)金 2贈送 3套餐, amount BIGINT NOT NULL DEFAULT 0 COMMENT 單位分, expire_date DATE NULL, status TINYINT NOT NULL DEFAULT 1, INDEX idx_acct (acct_id, status) ) ENGINEInnoDB; CREATE TABLE quota_record ( quota_id BIGINT PRIMARY KEY, session_id VARCHAR(64) NOT NULL, acct_id BIGINT NOT NULL, granted_units BIGINT NOT NULL COMMENT 本次授權(quán)量, used_units BIGINT NOT NULL DEFAULT 0, validity_time INT NOT NULL COMMENT 有效期秒, reserved_amount BIGINT NOT NULL COMMENT 預(yù)占金額分, status TINYINT NOT NULL COMMENT 1預(yù)占 2確認(rèn) 3釋放, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, UNIQUE KEY uk_session (session_id) ) ENGINEInnoDB; CREATE TABLE call_detail ( cdr_id BIGINT PRIMARY KEY, session_id VARCHAR(64) NOT NULL, acct_id BIGINT NOT NULL, rating_group INT NOT NULL, start_time DATETIME NOT NULL, end_time DATETIME NOT NULL, total_units BIGINT NOT NULL, total_amount BIGINT NOT NULL, UNIQUE KEY uk_session_start (session_id, start_time) ) ENGINEInnoDB;參數(shù)說明amount和total_amount都用“分”存儲不要用decimal也不要直接用元status字段的數(shù)字含義要在代碼里用枚舉類固化不能散落在業(yè)務(wù)邏輯里。quota_record里加了session_id唯一索引這是話單去重和配額防重放的第一道防線。call_detail表額外加了(session_id, start_time)唯一鍵后面對重復(fù)話單很管用。4.2 扣費代碼的落地順序預(yù)占、確認(rèn)、回沖扣費邏輯我一般拆成三個函數(shù)grant_quota做預(yù)占confirm_charge做確認(rèn)release_refund做回沖。下面是一段可讀性優(yōu)先的Python偽代碼重點看順序def grant_quota(acct_id, session_id, requested_units, tariff): with transaction() as tx: # 1. 鎖定余額行防止并發(fā)把同一筆錢批給兩個會話 bal tx.select_for_update( SELECT balance_id, amount FROM acct_balance WHERE acct_id%s AND balance_type1 AND status1 ORDER BY expire_date LIMIT 1, acct_id) # 2. 批價把請求的單位換算成預(yù)占金額 cost rating(tariff, requested_units) if bal.amount cost: granted bal.amount # 余額不足時按余額折算 cost rating(tariff, granted) else: granted requested_units # 3. 預(yù)占余額不是真的扣走而是先從余額里減掉 tx.update(UPDATE acct_balance SET amountamount-%s WHERE balance_id%s AND amount%s, cost, bal.balance_id, cost) # 4. 落配額記錄 tx.insert(INSERT INTO quota_record (session_id, acct_id, granted_units, reserved_amount, status) VALUES (%s,%s,%s,%s,1), session_id, acct_id, granted, cost) return granted, costconfirm_charge在會話結(jié)束時調(diào)用根據(jù)最終使用量重算費用把真實費用寫進(jìn)賬本再把預(yù)占差額回沖給余額def confirm_charge(session_id, used_units): with transaction() as tx: quota tx.select_for_update( SELECT * FROM quota_record WHERE session_id%s, session_id) actual_cost rating(quota.tariff, used_units) # 回沖差額預(yù)占的錢減掉實際用的錢退回余額 refund quota.reserved_amount - actual_cost if refund 0: tx.update(UPDATE acct_balance SET amountamount%s WHERE balance_id%s, refund, quota.balance_id) tx.update(UPDATE quota_record SET status2, used_units%s WHERE session_id%s, used_units, session_id) tx.insert(INSERT INTO call_detail (...) VALUES (...))注意grant_quota里第3步的UPDATE帶上了amount%s條件這是余額不被打穿的最后一道防線。第1步的select_for_update解決并發(fā)問題但即便鎖阻塞了條件更新的寫法也能兜住余額為負(fù)的情況。這段代碼里最關(guān)鍵的是第1步的select_for_update和第3步的“余額足夠才扣”條件。前者解決并發(fā)后者保證余額不會因為程序bug扣成負(fù)數(shù)。rating()函數(shù)在真實項目里會拿到資費表、優(yōu)惠疊加規(guī)則和周期用量邏輯會復(fù)雜得多但扣費的骨架不變。4.3 授權(quán)接口的字段設(shè)計與應(yīng)答碼OCS的對外接口在標(biāo)準(zhǔn)里是Diameter但在私有實現(xiàn)里很多團(tuán)隊會封裝成HTTP或Java接口。無論哪種字段都要貼近標(biāo)準(zhǔn)語義因為網(wǎng)元對接時是按標(biāo)準(zhǔn)字段來的。方向關(guān)鍵字段說明請求session_id網(wǎng)元生成的會話ID同一會話所有消息都帶請求cc_request_typeINITIAL/UPDATE/TERMINATION請求subscription_id用戶標(biāo)識常是MSISDN或IMSI請求requested_units本次申請的配額量請求used_units更新/結(jié)束時上報的上段使用量請求rating_group業(yè)務(wù)類型如語音/流量/短信應(yīng)答result_code2001成功4012余額不足4011用戶不存在應(yīng)答granted_units本次授權(quán)量應(yīng)答validity_time單位秒超過后配額失效應(yīng)答final_unit_indication標(biāo)記這是最后的配額應(yīng)答碼的設(shè)計對網(wǎng)元行為影響很大。4012BALANCE_NOT_ENOUGH應(yīng)答后網(wǎng)元應(yīng)該立即中斷會話而不是自己憑感覺繼續(xù)。如果把余額不足回成2001但granted_units0網(wǎng)元行為會不統(tǒng)一排障時到處燒香。這塊我建議在聯(lián)調(diào)階段就把每個應(yīng)答碼對應(yīng)的網(wǎng)元行為表簽死。5. OCS計費落地避坑指南五個讓賬實不符的典型坑5.1 并發(fā)扣費把余額扣成負(fù)數(shù)現(xiàn)象兩個會話同時請求配額第一個扣完余額還剩5元第二個也按5元批了出去結(jié)果余額變-3元。原因業(yè)務(wù)代碼先“查余額”再“扣余額”中間沒有加鎖兩個請求都讀到舊的余額值各自認(rèn)為自己那筆錢足夠。解決所有余額扣減必須走select_for_update或樂觀鎖版本號??蹨pSQL要帶余額條件例如UPDATE ... SET amountamount-5 WHERE balance_id1 AND amount5。余額不足返回4012不給配額。查當(dāng)前余額的SQL和扣減SQL之間不要留空隙鎖的粒度要鎖到余額行不是鎖賬戶。5.2 配額下發(fā)太大錢被預(yù)占壓了一整夜現(xiàn)象用戶充了50元一次性全被預(yù)占只打了一分鐘電話剩下49元多被鎖住其他業(yè)務(wù)都顯示余額不足。原因Initial時直接把賬戶余額當(dāng)作配額發(fā)出去沒有按單次會話上限和有效期控制。預(yù)占雖然是臨時的但預(yù)占期間這部分錢不能另作他用。解決配額下發(fā)達(dá)到一個上限比如單次會話最多預(yù)占10元或1GBValidity Time設(shè)600秒到期網(wǎng)元必須更新或釋放。配額給多還有一個副作用一旦用戶資金被管控過大的預(yù)占會讓余額凍結(jié)時間變長對賬時審計被問好幾輪。給配額記錄表加created_at和updated_at回沖時效性一目了然。5.3 話單重復(fù)上報同一筆通話扣了兩次現(xiàn)象用戶打了一次電話余額被扣兩筆查話單有兩條相同起止時間的記錄。原因網(wǎng)元超時重傳Termination CCR兩次都進(jìn)入confirm_charge而話單表沒有針對業(yè)務(wù)維度的唯一約束。解決call_detail表建唯一索引字段是(session_id, start_time)confirm_charge里在insert話單時捕獲duplicate插入如果發(fā)現(xiàn)同一session已經(jīng)結(jié)算過第二次直接返回成功不再次扣費。話單去重不能只靠業(yè)務(wù)流水號因為網(wǎng)元重傳時可能生成新的流水號。最可靠的是業(yè)務(wù)維度session_id配合start_time。如果還要防跨天就把start_time精確到秒并拼接成yyyyMMddHHmmss有UTC偏移量再加上偏移量。5.4 釋放請求先于更新請求到達(dá)回沖亂套現(xiàn)象用戶的配額還沒更新完會話就釋放了回沖金額按最終使用量算多退了幾塊錢。原因OCS沒有對請求做狀態(tài)機校驗。網(wǎng)絡(luò)里消息亂序是常態(tài)釋放和更新可能同時在路上。解決每個CCR請求帶Sequence NumberOCS側(cè)按sessionsequence排序只接受序號連續(xù)且狀態(tài)允許的消息。狀態(tài)機先判斷再執(zhí)行扣款避免舊請求覆蓋新狀態(tài)。這種坑最惡心的地方是它不報錯只把余額算錯對賬的時候才暴露。所以配額記錄表一定要留status和update_count字段每次更新都疊加上去最后用update_count判斷消息是否缺失。5.5 跨網(wǎng)元時鐘不一致扣費時長算錯現(xiàn)象一端記錄的通話時長是320秒另一端是350秒差價導(dǎo)致扣費不一致。原因OCS按會話開始/結(jié)束時間計算時長而這個時間是網(wǎng)元在各自本地時鐘下寫的。不同網(wǎng)元之間時鐘偏差可能達(dá)到秒級甚至分鐘級。解決OCS側(cè)統(tǒng)計時長以O(shè)CS接收Termination的時間減去OCS接收Initial的時間不依賴業(yè)務(wù)側(cè)上報的起止時間同時全網(wǎng)網(wǎng)元統(tǒng)一NTP同步。若無法統(tǒng)一話單里記錄時間偏移量由OCS校正。排查這類問題最簡單的方法是抓兩臺設(shè)備日志里的時間戳對比。讓網(wǎng)元在CCR里帶上接入網(wǎng)元的時間OCS回CCA時把這個時間回顯聯(lián)調(diào)階段一眼就能看到時差。6. 用模擬會話驗證OCS計費從配額下發(fā)到話單落庫的校驗方法最后把第4章的邏輯串成一個可跑通的模擬腳本適合在改完表結(jié)構(gòu)或扣費算法后快速驗證“余額變動對不對”。def simulate_call(acct_id, duration_seconds): session_id uuid4().hex # 1. 發(fā)起授權(quán)拿到配額 granted, reserved grant_quota(acct_id, session_id, duration_seconds, VOICE_TARIFF) print(授權(quán)配額:, granted, 預(yù)占金額:, reserved) # 2. 模擬業(yè)務(wù)跑了一半網(wǎng)元更新用量 used granted // 2 confirm_charge(session_id, used) # 3. 業(yè)務(wù)結(jié)束網(wǎng)元上報完整用量并釋放 confirm_charge(session_id, duration_seconds) # 4. 校驗余額 初始余額 - 實際費用 balance query_balance(acct_id) assert balance initial_balance - rating(duration_seconds)腳本的四個步驟對應(yīng)第3章的授權(quán)、更新、釋放第4章的三段偽代碼可以直接插入。輸出結(jié)果里重點看三處預(yù)占金額、回沖金額、最終余額是否與實際費用一致。如果中間某步結(jié)果和預(yù)期差一分錢先查是不是預(yù)占沒回沖再查是不是話單重復(fù)插入。我自己的習(xí)慣是每次改配額算法或資費規(guī)則先用這個腳本跑三組用例——正常用完、余額不足、中途主動釋放配額——每組跑完都對賬余額。三組都過了才提交代碼。這套模擬驗證擋住過不少黑匣子問題多數(shù)賬實不符的bug并不是資費算錯而是預(yù)占和回沖的時序問題。只要把“會話有狀態(tài)、扣費有鎖、話單有唯一鍵、配額有有效期”這四件事做到位OCS的實時扣費鏈路就立得住了。希望幫到你。本文還有配套的精品資源點擊獲取