☰
OCS在线计费系统:从业务用量到费用项链表的批价引擎设计
2026/10/16 17:42:09 网站建设 项目流程

简介:这份文档面向电信业务支撑系统与计费领域的开发、运维及系统设计人员,围绕OCS(在线计费系统)的计费原理与实现展开,帮助读者建立从概念到落地的完整认知。内容从计费系统由离线批量向实时处理的演进讲起,梳理TAG、业务用量、费用项、产品、订购、入帐关系等核心名词,再深入事件捕获、事件处理、账单生成与结算的计费流程,并介绍计费引擎、数据库、消息中间件等实现组件及安全机制。资源包内共1个doc文件,约1.87MB,为排版后的技术文档,结构清晰、便于按章节查阅。目前已有297人学习下载,适合需要理解实时计费业务逻辑、优化计费流程或进行系统设计参考的从业者阅读。

1. OCS计费:为什么一次通话能同时扣三种费用

你打了一通5分钟的电话,运营商怎么知道该从哪个账户扣钱?更诡异的是,同一通电话,可能同时产生本地通话费、长途费、漫游费三笔账目,分别从不同账户里扣除。这不是简单的“通话时长×费率”能解释的。

OCS(在线计费系统)要解决的核心问题是:在用户通话进行中,实时判断余额够不够、该从哪些账户扣、按什么费率扣、扣多少。它不像离线计费那样事后算总账,而是要在几百毫秒内完成一次“请求-计算-授权-扣费”的闭环。这套机制背后,是一套从“原始计费”演进到“事件驱动+模板化定价”的完整体系。搞懂它,你就理解了电信计费从“一张费率表打天下”到“多业务实时融合”的底层逻辑。

2. 从两张表到事件驱动:计费系统到底在演进什么

2.1 原始计费时代:反算时长与欠费风险控制

最早的计费系统只做一件事:根据主被叫号码查费率,然后扣钱。它用两张表就够了——用户表存余额,费率表根据主被叫归属地、拜访地号码头查费率。但预付费业务有个致命问题:用户打电话时余额不够怎么办?

这套系统用了一个叫“反算”的机制。用户发起呼叫前,计费系统先根据余额算出可通话时长,把时长返回给呼叫控制系统去监控。通话结束后,呼叫监控系统上报实际通话时长,再真正扣费。这就是最早的实时计费与欠费风险控制——先授权时长,后扣费。

这个阶段的问题很明显:一个地区多个号段,主被叫归属地、拜访地四个维度组合,费率表记录数爆炸。局方每改一次费率,要分析每个调整地区涉及的记录修改情况,极不直观,修改量大,容易出错。

2.2 简单计费时代:号码分析与计费矩阵的分离

为了解决费率表膨胀问题,系统把查找费率拆成三步。第一步号码分析:根据主被叫归属地、拜访地号码头,得到主被叫归属地区号、拜访地区号,把一个地区的多个号段归一。第二步计费矩阵:把一次呼叫分成基本费、漫游费、长途费三种消费,对应不同的费率索引(ChargeClass),根据地区号获得对应的消费类别费率列表。第三步费率表:专门描述费率,被计费矩阵引用。

这个设计的精妙之处在于“抽离”。费率从计费中抽离出来,局方改费率只需改费率表几条记录;号码分析抽离出来,新增号段只需在号码分析表配置。系统可维护性有了质的飞跃。

2.3 复杂计费时代:账户抽象与分档费率

移动用户增长到一定程度后,简单降价不能吸引入网。运营商开始用多元销售手段:消费积分、专款专销、充值优惠、越打越便宜。原来的系统撑不住了。

改造分三步。首先把计费系统一分为二:实时计费模块负责每次呼叫的费率计算,定期事务模块负责赠送和扣月租。其次把用户余额抽象成“账户”,单独建表,可以定义多种账户类型存放不同余额——长途免费通话时长、市话免费通话时长、充值赠送金额、累计消费金额。再次增强实时计费:ChargeClass从纯粹费率索引扩展为“消费类别”,定义消费类别只能在哪些账户上扣、入账优先级关系、费率。费率表扩展成多个分档,实现越打越便宜。

这一步实现了专款专销和消费累积。但到了3G时代,业务内容越来越丰富,这套系统又吃力了。

2.4 OCS计费时代:业务用量、计费事件与定价计划

3G带来的挑战是根本性的。计费请求内容日趋复杂,需要“一卡多用”——同一用户同时支持多种业务消费,而原来的欠费风险机制一个账户同时只能被一个业务使用。计费请求单位不再只是呼叫时长,还有短信条数、GPRS流量、ADSL上网流量、直接扣款金额。一次计费请求中可能包含多种消费,既通话又视频。套餐推出越来越快,原有系统调整ChargeClass的方式极不直观。后付费和预付费需要融合。

OCS的改造思路是彻底抽象。把“消费类别”进一步抽象成“业务用量”,包含两方面意思:消费的业务是什么,消费的量是多少。20分钟长途费消费、2M的GPRS流量消费,都是业务用量。新增一种计费请求消费类别,很容易扩展。

把每种计费请求抽象成“计费事件”,影响计费的参量抽象成“计费要素”。每种计费事件包含不同的计费要素和求解过程。新增计费请求种类只需新加代码,不修改原有实现,修改是“线性”的。

把iUser-bill和iCharge融合,它们仅仅是实现不同的计费功能。定期事务实现的是定期事务的计费能力,iCharge实现的是根据业务用量进行批价的能力。这些计费能力抽象成可复用的功能模块,叫“模板”或“策略模板”。定期赠送话费的计费能力做成“赠送模板”,赠送内容做成参数;呼叫提供按业务用量的计费模板,费率和适配条件作为参数。

每一次优惠活动和新套餐抽象成“定价计划”。定价计划通过调用多个模板实现新的资费优惠数据。比如“20元套餐赠送300分钟市话通话时长、200条网内短信、所有省内漫游低至1毛/分钟”,可以调用赠送模板,赠送内容参数配置成300分钟市话通话时长、200条网内短信;调用呼叫计费模板,传入费率参数1毛/分钟,适配条件省内漫游。预先定义一系列不同计费能力的模板,局方推出活动时只需新定义一个定价计划来调用这些模板。

注意:要在现网快速推出活动,修改需要具有可测试性和兼容性。新增定价计划仅仅是新增数据,不影响现有特性。采用订购方式,用户只有订购上该定价计划才能享受优惠,测试时只需将测试用户订购上,不影响其他用户。

后付费和预付费的统一,靠的是业务用量类型划分:请求业务用量、已使用业务用量、授权业务用量。预付费用户使用前,业务控制系统发起计费请求,传入请求业务用量大小。如果账户余额足够,返回授权业务用量等于请求业务用量;不够则根据余额计算授权业务用量。业务控制系统根据授权业务用量控制消费。后付费使用完成后,将话单包含的业务使用量作为已使用业务用量,系统根据已使用业务用量批价入账。批价入账动作对预付费和后付费完全一致,局方推出的所有优惠资费及活动,对后付费预付费都可以适用。

通过预付费用户进行“请求”可使用消费量的方式,实现一卡多用。用户有10元钱,A业务发出呼叫5分钟请求,需要消费1元,还有9元可用,同时B业务发起200M流量请求可以被响应。不像原先系统一定要等A业务呼叫完成,B业务才能消费。

3. 批价引擎:一次呼叫如何算出三笔账

3.1 业务识别:从呼叫事件到业务用量

批价的第一步是业务识别。当计费事件到达,系统需要判断这次消费涉及哪些业务用量。以主叫呼叫为例,系统会分析主叫是否有漫游、是否拨打长途。如果主叫漫游时拨打被叫长途5分钟,那么基本费业务用量、长途费业务用量、漫游费业务用量都是300秒。如果用户没有漫游,漫游业务用量为0秒。

这些业务用量类别是设计时规划好的。在广东OCS中,呼叫流程主叫子流程划分了5个业务用量:

用量名称TAG备注
基本费时长2003
长途费时长2005
漫游费时长2004
被叫漫游长途时长2311未用
附加费业务量2317未用

TAG即变量,可以理解为原先SER中的CID。和CID不一样的是,在CHG侧一般喜欢用数值来描述TAG,而不喜欢像CID变量一样用名称描述。我们常常称TAG 1080(存放SCP请求的呼叫时长)值是300,而不会说变量REQUIRED_CALL_DURATION值是300。

业务识别的本质是把一次原始计费事件,拆解成多个标准化的业务用量。每个业务用量有明确的TAG标识和数值。这个拆解过程由计费事件对应的计费要素求解过程完成。新增一种计费事件,只需要定义它的计费要素和求解过程,不需要修改已有事件的识别逻辑。

3.2 批价处理:费用项链表的生成

业务识别完成后,进入批价处理。批价的核心任务是:对每个业务用量,根据用户订购的定价计划,计算出对应的费用项。

费用项即消费明细,可以理解为消费清单。批价完成之后会输出一系列费用项条目,作为入账的输入。CBE依据此消费清单入到各种账户上,把相关金额扣除。

在广东版本中,针对主叫呼叫设计了如下费用项:1|本地通话费用项、2|漫游通话费用项、3|长途通话费用项。一次批价所输出的费用项采用链表方式实现,记录此次计费流程业务用量的消费明细。

假设主叫漫游时拨打被叫长途5分钟,市话费率1毛1分钟、长途费率2毛1分钟、漫游费率3毛1分钟。费用项链表如下:

业务用量数值金额(分)费用项
2003|基本费时长300501|本地通话费用项
2005|长途费时长3001003|长途通话费用项
2004|漫游费时长3001502|漫游通话费用项

这个链表结构的设计意图很明确:每个业务用量独立计算费用,生成独立的费用项。费用项之间没有耦合,可以分别入到不同的账户。入账关系说明消费明细应该在哪个账户上扣。比如本地通话费用项从基本账户扣,长途通话费用项从长途免费通话时长账户扣,漫游通话费用项从充值赠送金额账户扣。

批价处理的核心逻辑可以用伪代码表示:

def rating(event): # 业务识别:拆解计费事件为业务用量列表 usage_list = identify_usage(event) # 初始化费用项链表 charge_items = [] # 对每个业务用量独立批价 for usage in usage_list: # 查找用户订购的定价计划 pricing_plan = get_pricing_plan(event.user, usage.type) # 调用定价计划中的计费模板 # 模板包含费率、适配条件、分档规则 amount = pricing_plan.calculate(usage) # 生成费用项,挂入链表 charge_items.append({ 'usage_tag': usage.tag, 'usage_value': usage.value, 'amount': amount, 'item_type': pricing_plan.item_type }) return charge_items

这段逻辑的关键在于:每个业务用量的批价是独立的,但共享同一个定价计划体系。定价计划通过调用多个模板实现资费优惠。模板是可复用的计费能力模块,费率和适配条件作为参数传入。新增套餐时,只需新定义一个定价计划来调用已有模板,不需要修改批价引擎代码。

3.3 入账:从费用项到账户扣款

批价输出费用项链表后,进入入账环节。入账关系定义了消费明细应该在哪个账户上扣。系统根据费用项的类型,查找对应的入账关系,确定目标账户和扣款优先级。

入账的核心逻辑是:对每个费用项,按照入账关系找到目标账户列表,按优先级依次扣款。如果第一个账户余额不足,自动扣第二个,直到费用项金额扣完或所有账户余额耗尽。

这个机制实现了专款专销。长途通话费用项只能从长途免费通话时长、充值赠送金额、基本金额中扣取,优先级是先扣长途免费通话时长,扣完后从充值赠送金额、基本金额扣取。市话通话费用项只能从市话免费通话时长、基本金额中扣取。不同费用项的入账关系相互独立,互不干扰。

预付费和后付费在入账环节完全一致。区别只在于:预付费是实时请求-授权-扣费,后付费是事后话单批价入账。预付费批价入账之后只需要出话单,后付费需要出账单、账单邮寄、欠费自动催缴等特性。

4. 充值、月结与回赠:定期事务的计费能力复用

4.1 充值流程:预处理与模板说明

充值流程是OCS的另一类典型计费事件。用户充值100元,系统需要完成预处理、批价、入账。预处理部分负责校验充值请求的合法性,比如充值卡号是否有效、用户是否存在、充值金额是否在允许范围内。批价部分根据充值优惠策略计算实际到账金额。入账部分把金额加到用户账户。

充值优惠是常见的营销手段,比如充100送40,分几个月赠送。这个需求通过赠送模板实现。赠送模板是一种计费能力模块,赠送的内容做成参数。充值流程调用赠送模板,传入赠送金额、赠送时间、分月赠送规则等参数。模板负责生成定期事务,在指定时间把赠送金额入到指定账户。

模板的设计意图是复用。赠送话费、赠送流量、赠送短信条数,底层逻辑都是“在指定时间把指定资源入到指定账户”。把这些共性抽象成模板,新增赠送活动时只需配置参数,不需要开发新代码。

4.2 月结流程:定期事务的批量处理

月结是定期事务模块的典型场景。每天后台自动执行,检查需要赠送多少钱到哪个账户,如果是月结需要扣取月租。月结流程的核心是批量处理:扫描所有用户,根据用户订购的定价计划,判断是否需要执行月结操作。

月结流程与呼叫流程的区别在于触发方式。呼叫流程由用户行为触发,实时性要求高;月结流程由定时任务触发,批量处理,对实时性要求低。但两者共享同一套计费能力模块——模板。月结调用扣月租模板,传入月租金额、扣款账户、扣款优先级等参数。模板负责执行扣款动作。

4.3 回赠:消费累积与奖励发放

回赠是消费积分制度的实现。用户消费到一定程度,系统对用户进行奖励赠送,鼓励继续消费。回赠流程需要累计用户的消费金额或消费次数,达到阈值后触发赠送。

累计项处理是回赠的基础。系统需要记录用户的累计消费金额、累计通话时长、累计短信条数等。这些累计项存储在用户账户的扩展属性中。每次计费事件完成后,更新对应的累计项。当累计项达到阈值,触发回赠模板,生成赠送事务。

回赠模板与赠送模板类似,区别在于触发条件。赠送模板由充值或月结触发,回赠模板由累计项阈值触发。两者都调用相同的底层入账能力,把资源入到指定账户。

5. 避坑:OCS计费配置中容易翻车的几个点

5.1 业务用量TAG配错导致费用项缺失

现象:用户通话后,账单上只有本地通话费用项,没有长途费用项,但用户确实拨打了长途。

原因:业务识别阶段,长途费时长的TAG配置错误,或者计费事件的计费要素求解过程没有正确输出长途业务用量。系统在批价时找不到对应的业务用量,自然不会生成长途费用项。

解决:检查计费事件的计费要素配置,确认长途费时长的TAG与业务用量定义一致。用测试用户发起一次长途呼叫,抓取批价日志,确认业务用量列表中包含长途费时长。

5.2 入账关系优先级配反导致扣错账户

现象:用户有长途免费通话时长,但通话后基本账户被扣了钱,免费时长没动。

原因:入账关系中,长途通话费用项的扣款优先级配置错误,基本账户的优先级高于长途免费通话时长账户。

解决:检查入账关系配置,确认长途通话费用项的目标账户列表中,长途免费通话时长账户的优先级最高。修改后,用测试用户验证扣款顺序。

5.3 定价计划未订购导致批价失败

现象:用户通话后没有产生费用项,批价日志显示“未找到匹配的定价计划”。

原因:用户没有订购对应的定价计划。OCS采用订购方式,用户只有订购上该定价计划才能享受优惠资费。测试时如果忘记给测试用户订购,批价就会失败。

解决:检查用户的订购关系,确认已订购对应的定价计划。测试新套餐时,先将测试用户订购上,再发起呼叫验证。

5.4 分档费率边界条件配错导致越打越贵

现象:用户通话头3分钟4毛/分钟,后10分钟应该2毛/分钟,但实际后10分钟还是4毛/分钟。

原因:费率表的分档配置中,分档的边界条件设置错误。比如第一档的结束时间配置成了0秒,或者第二档的起始时间配置成了0秒,导致分档逻辑没有正确切换。

解决:检查费率表的分档配置,确认第一档的结束时间等于第二档的起始时间,且时间单位一致。用测试用户发起一次超过第一档时长的呼叫,验证分档费率是否正确切换。

5.5 累计项未更新导致回赠不触发

现象:用户消费金额已达到回赠阈值,但没有收到赠送。

原因:累计项处理逻辑没有正确更新用户的累计消费金额。可能是计费事件完成后,更新累计项的步骤被跳过,或者累计项的更新条件配置错误。

解决:检查累计项处理配置,确认每次计费事件完成后都会更新对应的累计项。用测试用户发起多次消费,观察累计项数值是否递增,达到阈值后是否触发回赠。

6. 设计取舍:为什么OCS选择模板化定价而不是硬编码

OCS的模板化定价体系,本质上是在“灵活性”和“性能”之间做了一次取舍。硬编码费率逻辑,性能最好,但每次推出新套餐都要改代码、测试、上线,周期长,风险高。模板化定价把计费能力抽象成可复用的模块,新增套餐只需配置数据,不改代码。代价是批价时需要动态查找定价计划、匹配模板、解析参数,性能开销比硬编码大。

这个取舍在电信计费场景下是合理的。电信套餐变化频繁,推出速度是核心竞争力。硬编码的交付周期以月计,模板化配置以天计。性能开销可以通过缓存定价计划、预编译模板参数来优化。而且OCS的计费请求量虽然大,但单次批价的计算复杂度可控,模板化带来的额外开销在可接受范围内。

另一个取舍是业务用量与费用项的分离。业务用量描述“消费了什么、消费了多少”,费用项描述“该收多少钱、从哪个账户扣”。两者分离的好处是:业务识别和批价处理可以独立演进。新增一种业务用量,不影响已有费用项的计算逻辑;新增一种费用项,不影响已有业务用量的识别逻辑。代价是系统需要维护两套映射关系——业务用量到费用项的映射、费用项到账户的映射。映射关系配置错误,就会出现前面提到的避坑场景。

从源码实现角度看,OCS的批价引擎通常采用责任链模式。计费事件到达后,依次经过业务识别链、批价处理链、入账处理链。每个链由多个处理器组成,每个处理器负责一个具体的计费能力。新增计费能力时,只需在对应链上添加一个处理器,不修改已有处理器。这种设计实现了“线性修改”——新增功能不影响已有功能,符合OCS对兼容性和可测试性的要求。

我一般会这么理解OCS的模板化定价:它把计费系统从“写死的逻辑”变成了“可编排的规则”。模板是积木,定价计划是图纸,批价引擎是装配线。局方推出新套餐,就是画一张新图纸,用已有的积木拼出新组合。装配线不用改,积木不用改,只改图纸。这就是OCS能快速响应市场变化的底层原因。

从那以后我每次看计费系统的配置,都强制走一遍“业务用量→费用项→入账关系”的链路,确认每一环的映射都正确。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询