在线计费系统 (OCS) 集成
关于 OmniTAS 与在线计费系统通过 Diameter Ro 接口集成的综合指南,包括实时信用控制、AVP 提取和 FreeSWITCH 变量映射。
目录
架构概述
OmniTAS 根据 3GPP TS 32.299 实现了 Diameter Ro 接口以进行实时在线计费。该系统通过在呼叫设置之前向 OCS 请求信用来授权呼叫,在呼叫期间监控信用,并在终止时报告最终使用情况。
关键组件
信用控制请求 (CCR):
- CCR-Initial (类型 1): 在呼叫设置之前发送以请求初始信用授权
- CCR-Update (类型 2): 在活动呼叫期间发送以进行重新授权或临时更新
- CCR-Terminate (类型 3): 在呼叫终止时发送,报告最终使用情况
信用控制应答 (CCA):
- 包含授予的服务单位(以秒为单位的时间配额)
- 包括带有附加计费数据的供应商特定 AVP
- 提供路由信息、收费方详细信息和服务标识符
控制通话是否收费的因素
通话仅在以下三个条件 全部满足 时产生 Diameter CCR。这些条件在 OmniTAS 为呼叫构建移动发起 (MO) 拨号计划时进行评估:
- 在线计费已启用:
online_charging.enabled为true。当为false时,OmniTAS 会在本地授权每个呼叫,并且从不联系 OCS。 - 呼叫为移动发起 (MO): 仅对 MO 分支收费。移动终止 (MT) 呼叫从不收费: MT 路径不执行 OCS 授权,因此不会为其创建信用控制会话。
- 目的地不在豁免名单中: 拨打的号码与
skipped_regex中的任何模式不匹配(例如紧急号码、服务代码)。
如果全部满足,OmniTAS 会发送 CCR-Initial 并打开一个以 SIP Call-ID 为键的信用控制会话。从那时起,CCR-Update 和 CCR-Terminate 由应答/挂断事件驱动(请参见 应答和挂断通知),并且仅为具有开放会话的呼叫分支生成。MT 分支、桥接 B 分支和豁免呼叫因此不会产生 CCR。
注意: 到达 OCS 并不保证呼叫连接。成功授权 零 授予单位会阻止呼叫。请参见 信用耗尽和呼叫阻止。阻止发生在发送 CCR 之后;它与上述决定是否发送 CCR 的条件不同。
从拨号计划中零收费一个路线
skipped_regex 完全移除目的地的收费 - 没有会话,没有 CCR-I,因此没有信用检查。这对于紧急号码是正确的行为,但对于希望在不计费的情况下继续授权的路线(免费内部通话、免费电话范围、促销目的地、测试号码)则不是。
对于这些,请在拨号计划中设置通道变量 tas_zero_rate=true:
<action application="set" data="tas_zero_rate=true"/>
该变量在应答和挂断事件中从通道读取,因此可以从任何分机设置,针对任何条件 - 它不携带 为什么 路线是免费的知识。
在 FreeSWITCH 执行拨号计划时,CCR-Initial 已经发送(OmniTAS 在构建拨号计划时授权呼叫),因此订阅者仍然会进行信用检查,且信用不足的呼叫者仍然会被阻止。该标志抑制的是 使用报告:
| 正常路线 | tas_zero_rate=true | |
|---|---|---|
| CCR-Initial (授权) | 发送 | 发送 |
| CCR-Update 在应答时 | 发送 | 不发送 |
| 定期 CCR-Update | 发送 | 不发送 |
| 信用耗尽时的中途切断 | 适用 | 不适用 |
| CCR-Terminate | 发送,报告消耗的 CC-Time | 发送,报告 CC-Time 0 |
| 对余额的净影响 | 为通话扣费 | 未受影响 |
CCR-T 中的其他所有内容保持真实 - 时间戳、Cause-Code、Service-Information - 因此 OCS 仍然会记录该通话的准确 CDR,费用为零,并完全释放 CCR-Initial 预留。
注意: 由于未发送 CCR-Update,OCS 会在整个通话期间保留 CCR-Initial 预留,并仅在 CCR-Terminate 时释放它。在长时间的零收费通话中,这可能会使订阅者在并发呼叫中看起来信用不足,直到清除。
priv/templates/mo_dialplan.xml 提供了一个 Zero-Rated-Routes 扩展,其中包含注释示例(内部通话和目的地前缀)。零收费默认 关闭 - 取消注释或添加您想要的条件。例如,要使内部通话免费,使用 OmniTAS 从拨打号码的 Sh 查找中设置的 on_net_status 变量:
<extension name="Zero-Rated-Routes" continue="true">
<condition field="${on_net_status}" expression="^true$" break="never">
<action application="set" data="tas_zero_rate=true"/>
</condition>
</extension>
信用控制流程
呼叫授权序列
信用耗尽和呼叫阻止
呼叫设置时的阻止。 如果 OCS 返回成功的 CCA(结果代码 2001��,但授予的单位为 零(或显式拒绝,如 4012 (DIAMETER_CREDIT_LIMIT_REACHED) 或 4010 (DIAMETER_END_USER_SERVICE_DENIED)),OmniTAS 将该呼叫视为没有信用,并以挂断原因 OUTGOING_CALL_BARRED 阻止它。订阅者永远不会连接。这是未配置或信用不足的订阅者的预期结果。
通话中途耗尽。 如果在设置时授予信用,但后来耗尽(定期 CCR-Update 返回零单位或信用限制错误),OmniTAS 将终止进行中的呼叫。配置了 credit_exhaustion_announcement 时,它会在挂断之前将呼叫者转移到公告;否则,它会直接挂断。
CCR-Terminate 在耗尽时触发,在任何清理之前。 当余额耗尽时,OmniTAS 会 立即 发送 CCR-Terminate(收费应答→耗尽),然后 播放信用耗尽公告或挂断。这是故意的:订阅者花费在“您已余额不足”提示上花费的时间是 不收费的,因此 CDR 必须在信用耗尽时结束,而不是在用户从录音中挂断时结束。会话在那时终止,因此最终的 FreeSWITCH 挂断不会找到会话并且不会发送任何内容(幂等,不会有第二个 CCR-T)。这适用于无论清理是转移到公告还是直接挂断,因此不依赖于 FreeSWITCH 挂断原因。
OmniTAS 支持多种处理信用耗尽的机制,自动集成计划挂断和信用耗尽公告。
动态重新调度的计划挂断
当 schedule_hangup_auth 启用时,OmniTAS 会调度一个 FreeSWITCH 计时器,在授予的信用到期时自动终止呼叫。每次通过 CCR-Update 响应授予新信用时,该计时器会 动态重新调度。
工作原理:
缓冲逻辑:
OmniTAS 在授予的信用到期之前发送 CCR-Update 消息,以确保持续服务。缓冲时间可以通过 ccr_update_buffer_seconds 配置(默认:2 秒)。
示例时间线:
- T+0s: 呼叫应答,OCS 授予 10s,计时器调度到 T+10s
- T+8s: 发送 CCR-U(10s - 2s 缓冲)
- T+8.1s: OCS 授予 10s,计时器重新调度到 T+18.1s(从现在起 10s)
- T+16.1s: 发送 CCR-U
- T+16.2s: OCS 授予 10s,计时器重新调度到 T+26.2s
- 呼叫持续,只要 OCS 不断授予信用
需要关注的日志:
[OCS HANGUP RESCHEDULE] Found UUID <uuid> for call <id> - rescheduling timer to 10s from now
[SCHED TRANSFER] Scheduling transfer to credit_exhausted dialplan for <uuid> in 10s
[OCS HANGUP RESCHEDULE] Successfully rescheduled timer for call <id> (UUID: <uuid>)
集成:schedule_hangup_auth + credit_exhaustion_announcement
当 两个 功能都启用时,OmniTAS 会自动使用计划 转移 而不是直接挂断,允许呼叫者在呼叫终止之前听到公告。
未配置公告的情况:
config :tas, :online_charging,
schedule_hangup_auth: true,
credit_exhaustion_announcement: nil
→ 使用 sched_hangup - 当信用到期时直接挂断
配置公告的情况:
config :tas, :online_charging,
schedule_hangup_auth: true,
credit_exhaustion_announcement: "${base_dir}/sounds/en/us/callie/misc/8000/credit_exhausted.wav"
→ 使用 sched_transfer - 转移到 credit_exhausted 拨号计划,播放公告然后挂断
转移的工作原理:
- OmniTAS 设置
tas_call_reason=credit_exhausted通道变量 - 调度转移到
ims_as拨号计划上下文中的credit_exhausted扩展 - 当计时器触发时:
- FreeSWITCH 将 A-leg 转移到 credit_exhausted 拨号计划
- 桥接自动断开,B-leg 收到 BYE
- 拨号计划向 A-leg 播放公告
- 呼叫在公告后终止
好处:
- 呼叫者听到专业的公告,而不是突然断开
- B-leg(被叫方)不会听到公告
- CCR-T 仍然发送实际使用情况
- 公告路径:必须相对于 FreeSWITCH 基目录(使用
${base_dir}变量)
CCR-Update 期间的即时信用耗尽
如果 OCS 在 CCR-Update 期间 拒绝信用 或返回 零秒,OmniTAS 会立即触发信用耗尽处理,覆盖任何计划计时器。
OCS 响应场景:
处理的错误代码:
| OCS 响应 | 动作 | 日志 |
|---|---|---|
{:ok, 0} (零秒) | 立即信用耗尽挂断 | Credit exhausted (zero seconds allocated) - triggering immediate hangup |
{:error, 4012} (CREDIT_LIMIT_REACHED) | 立即信用耗尽挂断 | Credit exhausted (4012 CREDIT_LIMIT_REACHED) - triggering immediate hangup |
{:error, 4010} (END_USER_SERVICE_DENIED) | 立即信用耗尽挂断 | Service denied (4010 END_USER_SERVICE_DENIED) - triggering immediate hangup |
{:error, reason} (其他错误) | 停止定期 CCR 作业,计划计时器触发 | Periodic CCR failed with error <reason> - Stopping job |
{:ok, N} 其中 N > 0 | 重新调度计时器到 +N 秒 | Periodic CCA allocated Ns, will send next CCR-U in (N-buffer)s |
优先级: 立即信用耗尽处理 优先 于计划计时器。如果 OCS 在 T+8s 拒绝信用,但计时器计划在 T+10s,则在 T+8s 立即挂断发生,计划计时器变得无关紧要。
中途信用拒绝的示例时间线:
T+0s: 呼叫应答
T+0.1s: OCS 授予 10s → 计时器计划到 T+10.1s
T+8s: 发送 CCR-U(缓冲 = 2s)
T+8.1s: OCS 返回 0 秒 → 立即转移到 credit_exhausted 拨号计划
T+8.2s: 向呼叫者播放公告
T+10s: 呼叫终止(计划计时器无关紧要)
即时信用耗尽的日志:
[warning] Credit exhausted (zero seconds allocated) - triggering immediate hangup
[warning] Hanging up call <id> (UUID: <uuid>) due to credit exhaustion
[info] Credit exhaustion announcement config: "${base_dir}/sounds/..."
[info] Playing announcement before hangup: ...
[info] Setting tas_call_reason=credit_exhausted for <uuid>
[info] Transferring to credit exhausted dialplan: uuid_transfer <uuid> credit_exhausted XML ims_as
总结:信用耗尽机制
OmniTAS 提供两种互补机制:
-
计划计时器 (
schedule_hangup_auth):- 授予信用到期时自动���断/转移
- 在每个 CCR-U 响应时动态重新调度
- 使用缓冲逻辑在到期前发送 CCR-U
- 与公告功能集成
-
即时耗尽处理:
- 在 OCS 拒绝信用时触发 CCR-U
- 覆盖计划计时器
- 支持公告播放
- 处理特定的 Diameter 错误代码
这两种机制都尊重 credit_exhaustion_announcement 配置,并将在配置时播放配置的音频,然后终止呼叫。
AVP 解析和变量映射
概述
OmniTAS 自动从信用控制应答消息中提取属性值对 (AVP),并将其作为通道变量提供给 FreeSWITCH。这使得拨号计划逻辑可以使用 OCS 提供的数据进行路由决策、计费目的或呼叫处理。
支持的 AVP 类型:
- 简单值 (UTF8String, Unsigned32, Integer32)
- 带有嵌套结构的分组 AVP
- 供应商特定 AVP(例如,3GPP 服务信息)
变量命名约定:
AVP 被展平为带有前缀 CCA 的点表示法通道变量:
CCA.<AVP-Name>.<Nested-AVP-Name>.<Value-AVP-Name> = "value"
常见 AVP 映射
服务信息 AVP (3GPP)
服务信息分组 AVP (AVP 代码 873, 供应商 ID 10415) 包含 IMS 特定的计费详细信息:
示例 OCS 响应:
Service-Information
├── IMS-Information
│ ├── Carrier-Select-Routing-Information: "1408"
│ └── Node-Functionality: 6
└── Alternate-Charged-Party-Address: "NickTest"
结果 FreeSWITCH 变量:
CCA.Service-Information.Carrier-Select-Routing-Information = "1408"
CCA.Service-Information.Alternate-Charged-Party-Address = "NickTest"
在拨号计划中访问: 变量使用点表示法和连字符,如上所示:
<action application="log" data="INFO Carrier: ${CCA.Service-Information.Carrier-Select-Routing-Information}"/>
使用 uuid_dump 查看:
在 FreeSWITCH 控制台或 ESL 中,变量以 variable_ 前缀出现:
variable_CCA.Service-Information.Carrier-Select-Routing-Information: 1408
variable_CCA.Service-Information.Alternate-Charged-Party-Address: NickTest
注意: FreeSWITCH 在变量名称中保留点和连字符。这些变量在所有拨号计划上下文和应用程序中均有效。
授予服务单位 AVP
时间配额被提取并可用:
OCS 响应:
Granted-Service-Unit
└── CC-Time: 600
变量:
allocated_time = 600
AVP 处理逻辑
处理规则:
- 分组 AVP 为变量名称层次结构添加一个级别,但本身没有值
- 简单 AVP 映射到具有其完整点路径的变量
- 供应商特定 AVP 的处理与标准 AVP 相同
- 未知 AVP 安全跳过而不产生错误
示例:多级嵌套
OCS CCA 结构:
服务信息(分组)
├── IMS 信息(分组)
│ ├── 节点功能:6
│ ├── 节点角色:1
│ ├── 主叫方地址:"tel:+313380000000670"
│ └── 时间戳(分组)
│ ├── SIP 请求时间戳:"2026-01-24T22:40:18Z"
│ └── SIP 响应时间戳:"2026-01-24T22:40:18Z"
└── IN 信息(分组)
└── 实际被叫号码:"15551234567"
创建的 FreeSWITCH 变量:
CCA.Service-Information.IMS-Information.Node-Functionality = "6"
CCA.Service-Information.IMS-Information.Role-Of-Node = "1"
CCA.Service-Information.IMS-Information.Calling-Party-Address = "tel:+313380000000670"
CCA.Service-Information.IMS-Information.Time-Stamps.SIP-Request-Timestamp = "2026-01-24T22:40:18Z"
CCA.Service-Information.IMS-Information.Time-Stamps.SIP-Response-Timestamp = "2026-01-24T22:40:18Z"
CCA.Service-Information.IN-Information.Real-Called-Number = "15551234567"
配置
在线计费参数
| 参数 | 类型 | 必需 | 默认 | 描述 |
|---|---|---|---|---|
enabled | 布尔值 | 否 | false | 在线计费的主开关。当 false 时,所有 呼叫绕过 OCS 授权(不发送 CCR)。请参见 控制呼叫是否收费的因素。 |
requested_units_seconds | 整数 | 否 | 0 | 每次预留请求的通话时间(秒),在 CCR-Initial/Update 的 Requested-Service-Unit 中。0(默认)发送一个 空 RSU(AVP 存在但不携带 CC-Time),让 OCS 选择授予。这与诺基亚 TAS 对运营商的 CGRateS OCS 的匹配,后者忽略请求的单位并计算自己的授予。设置一个 正 值以根据 RFC 4006 为标准 OCS 预留特定的 CC-Time。 |
report_and_reserve | 布尔值 | 否 | false | 3GPP SCUR 使用报告,与诺基亚 TAS 匹配。当 true 时,每个 CCR-Update 和 CCR-Terminate 都携带一个 Used-Service-Unit,报告自上次报告以来消耗的 CC-Time(增量),加上 3GPP-Reporting-Reason:在答案更新时为 RATING_CONDITION_CHANGE (6),在定期更新时为 QUOTA_EXHAUSTED (3),在终止时为 FINAL (2)。OCS 扣除每个增量,并在终止时结算上次授予的未使用部分。当 false 时,仅 CCR-T 报告使用情况(从答案开始的累计,没有原因)。通话期间的增量 CC-Time 总和等于应答持续时间。 |
service_identifier | 整数 | 否 | 1 | 每个 CCR 中发送的稳定、预配置的 Service-Identifier(AVP 439)。OCS 根据 {Service-Context-Id + Service-Identifier} 键入计费,因此这必须是一个固定值,而不是随机值。 |
periodic_ccr_time_seconds | 整数 | 否 | 10 | 当 OCS 不返回可用授予时,CCR-Update 消息之间的回退间隔(秒)。在正常操作中,下一个 CCR-U 的时间是根据授予的信用动态计算的(allocated_time - ccr_update_buffer_seconds)。 |
ccr_update_buffer_seconds | 整数 | 否 | 2 | 授予的信用到期前的安全缓冲区(秒)。OmniTAS 在 (allocated_time - buffer) 时发送下一个 CCR-U,以便在信用用尽之前延长信用。建议:2-5 秒。 |
schedule_hangup_auth | 布尔值 | 否 | false | 当授予的信用到期时,启用自动呼叫挂断/转移。当 true 时,OmniTAS 根据每个 CCA 的 allocated_time 调度 FreeSWITCH 计时器,并在每个 CCR-U 响应时重新调度。与 credit_exhaustion_announcement 一起使用。 |
credit_exhaustion_announcement | 字符串 | 否 | nil | 信用耗尽公告的音频文件路径。当与 schedule_hangup_auth 配置时,使用计划的 转移 在挂断之前播放公告。当单独配置时,仅在立即信用耗尽时播放公告。路径必须使用 FreeSWITCH 变量形式:"${base_dir}/sounds/..."。设置为 nil 以直接挂断而不公告。 |
skipped_regex | 列表[字符串] | 否 | [] | 与 目标号码 匹配的正则表达式模式列表。匹配的目标完全绕过 OCS(没有会话,没有 CCR,没有信用检查)。对于紧急号码和服务代码(例如,"^911$","^000$")非常有用。要继续授权目标但不收费,请使用拨号计划的 tas_zero_rate 变量 - 请参见 从拨号计划中零费率路由。 |
Diameter 连接参数
| 参数 | 类型 | 必需 | 默认 | 描述 |
|---|---|---|---|---|
origin_host | 字符串 | 是 | - | OmniTAS Diameter 身份(FQDN)。在您的 Diameter 网络中必须是唯一的。示例:"tas01.epc.mnc123.mcc456.3gppnetwork.org"。 |
origin_realm | 字符串 | 是 | - | OmniTAS Diameter 领域。用于路由决策。示例:"epc.mnc123.mcc456.3gppnetwork.org"。 |
destination_realm | 字符串 | 是 | - | OCS Diameter 领域。请求路由到该领域的对等方。 |
destination_host | 字符串 | 否 | nil | 特定 OCS Diameter 身��。当 nil 时,仅根据 destination_realm 进行路由。当需要直接路由到特定 OCS 实例时使用。 |
配置示例
config :tas, :online_charging,
# 主开关
enabled: true,
# 0 = 空 RSU,让 OCS 决定授予(与诺基亚 TAS / CGRateS 匹配)。
# 仅为根据请求单位计费的标准 OCS 设置正值。
requested_units_seconds: 0,
# 稳定的预配置服务标识符
service_identifier: 1,
# 回退重新授权间隔(正常时间动态来自授予)
periodic_ccr_time_seconds: 10,
# 在授予的信用到期前 2 秒重新授权
ccr_update_buffer_seconds: 2,
# 根据授予的信用调度挂断
schedule_hangup_auth: true,
# 在信用耗尽挂断前播放公告
credit_exhaustion_announcement: "ivr/ivr-account_balance_low.wav",
# 跳过 OCS 的紧急呼叫和语音信箱
skipped_regex: [
"^911$", # 紧急(美国)
"^000$", # 紧急(澳大利亚)
"^\*86$" # 语音信箱访问
]
config :tas, :diameter,
# 服务身份
origin_host: "tas01.epc.mnc001.mcc001.3gppnetwork.org",
origin_realm: "epc.mnc001.mcc001.3gppnetwork.org",
# OCS 路由
destination_realm: "epc.mnc001.mcc001.3gppnetwork.org",
destination_host: nil # 基于领域的路由
工作原理:
当接收到呼叫时:
- 检查目标号码是否与
skipped_regex模式匹配 - 如果匹配,呼叫绕过 OCS(对紧急服务有用)
- 如果不匹配,CCR-Initial 发送到 OCS 的
destination_realm - 解析 CCA 响应以获取授予的单位和 AVP
- 将 AVP 映射到 FreeSWITCH 变量(请参见 AVP 映射)
- 呼叫继续进行,
allocated_time和 AVP 数据可用 - 在呼叫期间每
periodic_ccr_time_seconds发送 CCR-Update - 如果启用
schedule_hangup_auth,则在信用到期时自动挂断 - 呼叫完成时发送 CCR-Terminate
用例:
- 基本 OCS:使用默认值启用标准信用控制
- 高价值呼叫:将
periodic_ccr_time_seconds减少到 30 秒以进行频繁的重新授权 - 预付费服务:启用
schedule_hangup_auth并设置credit_exhaustion_announcement - 紧急合规:将紧急号码添加到
skipped_regex以确保始终连接
FreeSWITCH 集成
在拨号计划中访问 AVP 变量
从 CCA 消息中提取的 AVP 数据作为通道变量在 FreeSWITCH 拨号计划中可用:
<extension name="Route_with_OCS_Data">
<condition field="destination_number" expression="^(.+)$">
<!-- 从 OCS 访问运营商路由信息 -->
<action application="log"
data="INFO Carrier Code: ${CCA.Service-Information.Carrier-Select-Routing-Information}"/>
<!-- 从 OCS 访问收费方 -->
<action application="log"
data="INFO Charged Party: ${CCA.Service-Information.Alternate-Charged-Party-Address}"/>
<!-- 访问授予的时间 -->
<action application="log"
data="INFO Allocated Time: ${allocated_time} seconds"/>
<!-- 根据运营商代码路由 -->
<action application="set"
data="carrier_code=${CCA.Service-Information.Carrier-Select-Routing-Information}"/>
<action application="bridge"
data="sofia/external/$1@carrier-${carrier_code}.sip.example.com"/>
</condition>
</extension>
变量可用性
时机:
- 变量在 FreeSWITCH 呼叫设置 之前 设置
- 在整个呼叫持续期间可用
- 在呼叫转移和更新中保持不变
范围:
- 通道范围(特定于单个呼叫腿)
- 不会被桥接/转移的腿继承
- 在所有拨号计划应用中安全使用
示例用例
1. 基于 OCS 数据的运营商选择
使用 OCS 提供的运营商代码来路由呼叫:
<extension name="Carrier_Selection">
<condition field="${CCA.Service-Information.Carrier-Select-Routing-Information}" expression="^(.+)$">
<action application="bridge"
data="sofia/external/${destination_number}@carrier-$1.example.com"/>
</condition>
<!-- 如果未指定运营商则回退 -->
<condition field="${CCA.Service-Information.Carrier-Select-Routing-Information}" expression="^$">
<action application="bridge"
data="sofia/external/${destination_number}@default-carrier.example.com"/>
</condition>
</extension>
工作原理: OCS 在 Service-Information AVP 中返回运营商代码 "1408"。FreeSWITCH 根据此数据将呼叫路由到 carrier-1408.example.com 网关。
2. 替代计费方
根据 OCS 响应将计费路由到不同的方:
<extension name="Alternate_Billing">
<condition field="${CCA.Service-Information.Alternate-Charged-Party-Address}" expression="^(.+)$">
<!-- 记录计费方以用于 CDR -->
<action application="set"
data="billed_party=$1"/>
<action application="export"
data="billed_party=$1"/>
<!-- 包含在 SIP 头中 -->
<action application="set"
data="sip_h_X-Billed-Party=$1"/>
<action application="bridge"
data="sofia/external/${destination_number}@trunk.example.com"/>
</condition>
</extension>
工作原理: OCS 指定替代收费方(例如,企业账户)。OmniTAS 从 AVP 中提取 "NickTest",并使其在拨号计划中可用于 CDR 记录和 SIP 头插入。
3. 有时间限制的呼叫与警告
在信用到期之前提供警告:
<extension name="Credit_Warnings">
<condition field="destination_number" expression="^(.+)$">
<!-- 在挂断前 30 秒调度警告 -->
<action application="set"
data="warning_time=${expr(${allocated_time} - 30)}"/>
<action application="sched_hangup"
data="+${allocated_time} ALLOTTED_TIMEOUT"/>
<action application="sched_broadcast"
data="+${warning_time} playback::ivr/ivr-account_balance_low.wav"/>
<action application="bridge"
data="sofia/external/$1@trunk.example.com"/>
</condition>
</extension>
工作原理: 使用 OCS 的 allocated_time 来调度自动挂断,并在断开连接前 30 秒播放警告公告。
答复与挂断通知
在 CCR-Initial 授权呼叫后,OmniTAS 仍然需要知道 何时接听呼叫(以开始计量并发送 CCR-Update)和 何时结束(以发送 CCR-Terminate)。这些事件通过 FreeSWITCH 的事件套接字层(ESL)获取。
工作原理:
- OmniTAS 保持与本地 FreeSWITCH 的持久入站 ESL 连接,并订阅
CHANNEL_ANSWER和CHANNEL_HANGUP_COMPLETE。 - 在
CHANNEL_ANSWER上,它读取 SIP Call-ID 和实际应答时间戳,并发送开始计量的 CCR-Update。 - 在
CHANNEL_HANGUP_COMPLETE上,它读取 SIP Call-ID 和 FreeSWITCH 挂断原因,并发送带有最终使用时间的 CCR-Terminate。 - 事件通过 SIP Call-ID 匹配到信用控制会话。没有会话的呼叫腿(MT 腿、桥接 B 腿、豁免呼叫)的事件将被忽略。这就是防止未收费呼叫产生 CCR 的原因。
- 重复应答是幂等的。 桥接呼叫的两个腿都会触发
CHANNEL_ANSWER,并可能解析到相同的 Call-ID;只有第一个发送 CCR-Update 并启动周期发送器,其余的被忽略(否则会产生重复的 CCR-U ���双重周期发送器)。 - 转移结束收费会话。
BLIND_TRANSFER/ATTENDED_TRANSFER挂断被视为正常挂断 → CCR-Terminate(收费方已离开呼叫,或呼叫已转移到无信用公告)。一旦会话终止,任何后续的同一 Call-ID 的挂断将找不到会话并不发送任何内容。
CallEventListener 始终运行(真实部署总是有共置的 FreeSWITCH;仅在 test_mode 下跳过)。它不受单独开关的限制。是否发送 CCR 是由每个事件的 online_charging.enabled 决定的。关闭计费时,监听器仍然接收并记录 CHANNEL_ANSWER/CHANNEL_HANGUP_COMPLETE 的调试信息,但不发送 CCR。(早期版本有一个单独的 esl_notifications 切换;它被移除,因为它必须与 online_charging.enabled 一致,并且静默破坏了计费。它仅在计费开启但切换缺失时发送 CCR-Initial,而不发送 CCR-U/CCR-T。)
已弃用:/call_event HTTP 端点
早期版本通过 FreeSWITCH 拨号计划 curl 钩子检测应答/挂断,这些钩子 POST 到 OmniTAS 的 /call_event HTTP 端点。此机制已弃用。 拨号计划钩子已被移除,ESL 现在是通知源。
/call_event 端点仍然存在并返回 200 OK,以便任何残留的拨号计划引用不会出错,但它执行 没有计费操作。升级���旧版本的运营商应确保其拨号计划不再依赖于此。
Diameter 消息
CCR-Initial(请求类型 1)
在呼叫设置之前发送以请求授权和初始信用分配。
发送的关键 AVP:
| AVP | 代码 | 类型 | 描述 |
|---|---|---|---|
| Session-Id | 263 | UTF8String | 会话标识符,在整个信用控制会话中保持不变(CCR-I/U/T 共享它)。根据 SIP Call-ID 确定性派生。 |
| Auth-Application-Id | 258 | Unsigned32 | 根据 RFC 4006 的 Diameter 信用控制应用程序的值 4 |
| Service-Context-Id | 461 | UTF8String | 根据 TS 32.299 的 IMS 计费 "000.000.12.32260@3gpp.org" |
| CC-Request-Type | 416 | 枚举 | 值 1(INITIAL_REQUEST) |
| CC-Request-Number | 415 | Unsigned32 | 序列号:0 为 INITIAL_REQUEST,然后为会话中的后续请求 1,2,… RFC 4006 §8.2 |
| Service-Identifier | 439 | Unsigned32 | 稳定的预配置服务标识符(service_identifier 配置) |
| Subscription-Id | 443 | 分组 | 订阅者 MSISDN 或 IMSI |
| Requested-Service-Unit | 437 | 分组 | 预留请求:CC-Time = requested_units_seconds |
| Service-Information | 873 | 分组 | IMS 特定的呼叫细节(主叫/被叫方、节点角色、时间戳) |
示例 CCR-I:
Session-Id: "tas01.example.org;1463927445;1744753804"
Auth-Application-Id: 4
CC-Request-Type: 1 (INITIAL_REQUEST)
CC-Request-Number: 0
Subscription-Id:
- Subscription-ID-Type: 0 (END_USER_E164)
Subscription-ID-Data: "313380000000670"
Multiple-Services-Credit-Control:
- Service-Identifier: 1
Requested-Service-Unit:
- CC-Time: 300 (请求的预留)
Service-Information:
- IMS-Information:
- Role-Of-Node: 0 (ORIGINATING_ROLE)
- Node-Functionality: 6 (AS)
- Calling-Party-Address: "tel:+313380000000670"
- Called-Party-Address: "tel:+15551234567"
Requested-Service-Unit携带真实的预留(而不是零)。OCS 决定实际的授予,并在 CCA 的Granted-Service-Unit中返回。
CCA(信用控制应答)
来自 OCS 的响应,包含授权决策和授予的信用。
接收的关键 AVP:
| AVP | 代码 | 类型 | 描述 |
|---|---|---|---|
| Result-Code | 268 | Unsigned32 | 2001 表示成功。有关错误值,请参见 结果代码。 |
| Granted-Service-Unit | 431 | 分组 | 分配的信用(以秒为单位的时间) |
| Service-Information | 873 | 分组 | 额外的计费数据(运营商信息、收���方等) |
带 AVP 的示例 CCA:
Session-Id: "tas01.example.org;1769294418268;8a078232"
Result-Code: 2001 (DIAMETER_SUCCESS)
CC-Request-Type: 1
CC-Request-Number: 1
Granted-Service-Unit:
- CC-Time: 600 (授予 10 分钟)
Service-Information:
- IMS-Information:
- Carrier-Select-Routing-Information: "1408"
- Alternate-Charged-Party-Address: "NickTest"
结果变量:
allocated_time = 600
CCA.Service-Information.Carrier-Select-Routing-Information = "1408"
CCA.Service-Information.Alternate-Charged-Party-Address = "NickTest"
CCR-Update(请求类型 2)
在活动呼叫期间发送,用于定期重新授权或临时使用报告。
发送时机:
- 在呼叫应答时(来自 ESL 的
CHANNEL_ANSWER):CC-Request-Number=1,在SIP-Response-Timestamp中携带实际应答时间 - 在活动呼叫期间定期,动态定时为
allocated_time - ccr_update_buffer_seconds从每个授予(回退到periodic_ccr_time_seconds)
与 CCR-I 的关键区别:
CC-Request-Type:2(UPDATE_REQUEST)CC-Request-Number:应答时为1,然后在每次定期重新授权时递增Requested-Service-Unit:下一个预留(requested_units_seconds)- 与 CCR-Initial 相同的常量
Session-Id
消耗的时��在 CCR-Terminate 中报告(
Used-Service-Unit),而不是在临时 CCR-Update 中。临时更新延长预留;最终使用在终止时结算。
CCR-Terminate(请求类型 3)
在呼叫挂断时(来自 ESL 的 CHANNEL_HANGUP_COMPLETE)发送,并进行最终使用报告。
关键 AVP:
CC-Request-Type:3(TERMINATION_REQUEST)CC-Request-Number:序列中的下一个(例如2)Used-Service-Unit:总消耗通话时间(CC-Time,自应答以来的秒数)Termination-Cause:1(DIAMETER_LOGOUT)根据 RFC 6733 §8.15Cause-Code(AVP 861,IMS-信息):0表示正常应答并释放的呼叫,2表示会话设置不成功,依据 TS 32.299
结果代码
| 代码 | 名称 | 描述 | OmniTAS 操作 |
|---|---|---|---|
| 2001 | DIAMETER_SUCCESS | 请求批准 | 解析 AVP,设置呼叫 |
| 4010 | DIAMETER_END_USER_SERVICE_DENIED | 订阅者服务被拒绝 | 拒绝呼叫并返回 CALL_REJECTED |
| 4012 | DIAMETER_CREDIT_LIMIT_REACHED | 信用不足 | 拒绝呼叫并返回 OUTGOING_CALL_BARRED |
| 5003 | DIAMETER_AUTHORIZATION_REJECTED | OCS 策略拒绝 | 拒绝呼叫并返回 CALL_REJECTED |
| 5xxx | 永久性故障 | OCS 配置或系统错误 | 拒绝呼叫,记录错误 |
参考: RFC 6733 §7.1 和 3GPP TS 32.299
指标
请参阅 docs/metrics.md 获取完整的指标目录。以下指标与在线计费相关。
Diameter 请求 / 响应指标
CCRs 通过 command 标签按请求类型拆分,因此 CCR-Initial(设置),CCR-Update(临时重新认证)和 CCR-Terminate(拆除)可以独立跟踪。然后,失败的临时更新的峰值将单独可见。
指标: diameter_requests_total (计数器): 发送的 Diameter 请求
指标: diameter_responses_total (计数器): 接收到的 Diameter 响应
指标: diameter_response_duration_milliseconds (直方图): 请求往返时间
标签:
application-ro(在线计费) 或sh(用户数据)command-ccr_i,ccr_u,ccr_t(Ro) 或udr(Sh)result_code- (仅响应) Diameter 结果代码:2001,4012, 等;0= 超时 / 无法解析的回复result- (仅持续时间)success,nocredit,error
示例查询:
# 按请求类型的 CCR 速率
sum by (command) (rate(diameter_requests_total{application="ro"}[5m]))
# 每种请求类型的 CCR 错误率(任何不是 2001 的)
sum by (command) (rate(diameter_responses_total{application="ro", result_code!="2001"}[5m]))
# 信贷限制拒绝(4012)
rate(diameter_responses_total{application="ro", result_code="4012"}[5m])
# 按请求类型的第 95 百分位 CCR 延迟
histogram_quantile(0.95,
sum by (le, command) (rate(diameter_response_duration_milliseconds_bucket{application="ro"}[5m]))
)
信用控制配额指标
指标: ro_charging_quota_seconds
类型: 直方图
描述: 每个 CCR 观察到的配额(以秒为单位),用于验证计费的正确性
标签:
request_type-ccr_i,ccr_u,ccr_tkind-requested(请求服务单元中的 CC-Time),granted(授予的服务单元,0= 无信贷),used(终止时的已使用服务单元)
示例查询:
# 呼叫设置时授予的配额中位数
histogram_quantile(0.5, rate(ro_charging_quota_seconds_bucket{request_type="ccr_i", kind="granted"}[5m]))
# 每秒的无信贷授予(零秒分配)
rate(ro_charging_quota_seconds_bucket{kind="granted", le="0"}[5m])
# 每秒报告的终止时的总使用秒数(与计费分钟的合理性检查)
rate(ro_charging_quota_seconds_sum{kind="used"}[5m])
OCS 授权与事件指标
指标: ocs_authorization_attempts_total (计数器)
标签: result (success, nocredit, timeout, error), skipped (true 如果通过正则表达式跳过,否则为 false)
指标: online_charging_events_total (计数器): 生命周期事件
标签: event_type (authorize, answer, reauth, hangup, credit_exhaustion_hangup, hangup_rescheduled), result (success, nocredit, timeout, error, triggered)
示例查询:
# 授权成功率(不包括跳过的)
sum(rate(ocs_authorization_attempts_total{result="success", skipped="false"}[5m]))
/ sum(rate(ocs_authorization_attempts_total{skipped="false"}[5m]))
# 由于信贷耗尽而在通话中释放的呼叫
rate(online_charging_events_total{event_type="credit_exhaustion_hangup"}[5m])
故障排除
FreeSWITCH 中未提供 AVP 变量
症状:
- FreeSWITCH 拨号计划无法访问
${CCA.Service-Information.*}变量 - 变量显示为空或未定义
可能的原因:
- OCS 未在 CCA 中返回服务信息 AVP
- AVP 解析因意外结构而失败
- 变量未导出到 FreeSWITCH 通道
解决方案:
-
验证 OCS 响应���含 AVP
检查 OmniTAS 日志中的 CCA 消息:
[debug] Credit Control Answer: {:diameter_packet, ...}
[debug] Parsed AVP variables: %{
"CCA.Service-Information.Carrier-Select-Routing-Information" => "1408",
"CCA.Service-Information.Alternate-Charged-Party-Address" => "NickTest"
}如果 "Parsed AVP variables" 为空
%{},则 OCS 未返回预期的 AVP。 -
检查 AVP 解析错误
在日志中查找警告:
[warning] got back another type of reply: {...}这表明 AVP 结构与预期格式不匹配。检查 Diameter 数据包结构。
-
验证 FreeSWITCH 变量导出
在 FreeSWITCH 控制台或 ESL 中:
freeswitch> uuid_dump <call-uuid>查找带有
variable_前缀和CCA.的变量名称:variable_CCA.Service-Information.Carrier-Select-Routing-Information: 1408
variable_CCA.Service-Information.Alternate-Charged-Party-Address: NickTest
variable_CCA.Auth-Application-Id: 4
variable_CCA.Result-Code: 2001注意: FreeSWITCH 保留变量名称中的点和连字符。它们在拨号计划中正常工作:
<action application="log" data="Carrier: ${CCA.Service-Information.Carrier-Select-Routing-Information}"/>
呼叫被拒绝,错误为 "unhandled"
症状:
- 日志显示:
[warning] Could not authorize call: :unhandled - 有效的 CCA 响应 (结果代码 2001) 被拒绝
- 尽管 OCS 批准,呼叫仍然失败
可能的原因:
- CCA 消息结构与预期模式不匹配
- 供应商特定的 AVP 在意外位置
- AVP 位置索引不匹配
解决方案:
这是一个已知问题,在最近的版本中已修复。确保您正在运行当前版本。
以前的行为: 模式匹配要求:
- 授予的服务单元 AVP 必须准确位于第 7 位
- 空的供应商特定 AVP 列表
[]
当前行为: 模式匹配接受:
- 授予的服务单元 AVP 可以位于任何位置
- 非空的供应商特定 AVP 列表
如果问题仍然存在:
- 从日志中捕获 CCA 数据包结构
- 检查 AVP 是否符合预期的 Diameter 格式
- 验证结果代码是否为 2001
OCS 在所有请求上超时
症状:
- 所有 CCR 请求超时
- 日志显示:
[debug] Got back response for authorize: {:error, :timeout} - 5 秒内未收到 CCA
可能的原因:
- 与 OCS/DRA 的网络连接问题
- 防火墙阻止 Diameter 端口 (3868)
- 不正确的
destination_realm或destination_host - OCS 未对请求做出响应
解决方案:
-
验证网络连接
测试与 OCS 的 TCP 连接:
telnet ocs.example.com 3868应成功连接。如果连接被拒绝或超时,请检查防火墙规则。
-
检查 Diameter 配置
验证
destination_realm是否与 OCS 配置匹配:config :tas, :diameter,
destination_realm: "epc.mnc001.mcc001.3gppnetwork.org" # 必须与 OCS 领域匹配 -
查看 OCS 日志
检查 OCS 是否接收到 CCR 消息。如果 OCS 收到请求但未响应:
- 验证 OmniTAS 的
origin_host是否被 OCS 识别 - 检查 OCS 对等配置是否允许来自 OmniTAS 的连接
- 验证服务上下文 ID 和应用程序 ID 是否与 OCS 预期匹配
- 验证 OmniTAS 的
信贷耗尽未挂断呼叫
症状:
- 呼叫超出授予的信贷时间继续进行
- 当
allocated_time到期时没有自动挂断 schedule_hangup_auth已启用但未生效
可能的原因:
- FreeSWITCH 的计划挂断未配置
schedule_hangup_auth为false- 呼叫状态未正确跟踪
解决方案:
-
验证配置
确保
schedule_hangup_auth已启用:config :tas, :online_charging,
schedule_hangup_auth: true -
检查 FreeSWITCH ESL 连接
验证 OmniTAS 是否可以向 FreeSWITCH 发送命令:
[debug] Schedule Hangup Response: {:ok, "+OK"}如果出现错误或没有响应,请检查 FreeSWITCH 事件套接字配置。
-
监控呼叫状态
检查��叫 UUID 是否在呼叫状态中被跟踪:
[debug] Setting Scheduled Hangup for call in 600 seconds如果未找到 UUID,则呼叫状态跟踪可能存在问题。
跳过的正则表达式未绕过 OCS
症状:
- 紧急呼叫 (911, 000) 仍然经过 OCS 授权
- 匹配
skipped_regex模式的号码未被绕过 - 紧急呼叫延迟
可能的原因:
- 正则表达式模式语法错误
- 目标号码格式不匹配
- 正则表达式未正确转义
解决方案:
-
验证正则表达式模式
测试正则表达式编译:
Regex.compile("^911$") # 应返回 {:ok, ~r/^911$/}常见错误:
- 缺少锚点: 使用
^911$而不是911 - 转义: 使用
\*表示字面星号,而不是\*
- 缺少锚点: 使用
-
检查号码格式
验证目标号码格式是否与模式匹配:
[debug] Checking if dialled number "911" matches skipped regex...如果号码格式为 "+1911",但模式为 "^911$",则不会匹配。
-
示例模式
config :tas, :online_charging,
skipped_regex: [
"^911$", # 美国紧急
"^000$", # 澳大利亚紧急
"^112$", # 国际紧急
"^\*86$", # 语音信箱(转义星号)
"^1?800\d{7}$" # 免费电话
]
参考
3GPP 规范
| 规范 | 标题 | 相关章节 |
|---|---|---|
| TS 32.299 | Diameter 计费应用 | §6.3 (Ro 接口), §7.2 (AVP 定义) |
| TS 32.240 | 计费架构和原则 | §5 (在线计费) |
| TS 29.229 | Cx 和 Dx 接口 | IMS 中的服务信息 AVP 使用 |
IETF RFCs
| RFC | 标题 | 相关章节 |
|---|---|---|
| RFC 6733 | Diameter 基础协议 | §3 (协议概述), §7 (错误处理) |
| RFC 4006 | Diameter 信贷控制应用 | §8 (信贷控制消息) |
AVP 代码参考
供应商 ID 0 = IETF 基础 (RFC 6733 /
RFC 4006); 供应商 ID 10415 = 3GPP
(TS 32.299).
完整的 CCR 结构(语音呼叫)
每个 AVP OmniTAS 在呼叫 Credit-Control-Request 中包含,分组如下:
Credit-Control-Request (Command 272, App 4)
├─ Session-Id (263)
├─ Origin-Host (264)
├─ Origin-Realm (296)
├─ Destination-Realm (283)
├─ Destination-Host (293) [仅在配置时]
├─ Auth-Application-Id (258) = 4
├─ Service-Context-Id (461) = 000.000.12.32260@3gpp.org
├─ CC-Request-Type (416)
├─ CC-Request-Number (415)
├─ Event-Timestamp (55)
├─ User-Name (1) [仅在设置用户名时]
├─ Termination-Cause (295) [CCR-T 仅]
├─ Subscription-Id (443)
│ ├─ Subscription-Id-Type (450) = 0 (END_USER_E164)
│ └─ Subscription-Id-Data (444) = 用户的 MSISDN
├─ Multiple-Services-Credit-Control (456)
│ ├─ Service-Identifier (439)
│ ├─ Requested-Service-Unit (437) [CCR-I, CCR-U]
│ │ └─ CC-Time (420)
│ └─ Used-Service-Unit (446) [CCR-T]
│ └─ CC-Time (420)
└─ Service-Information (873, v10415)
├─ IN-Information [运营商扩展]
│ └─ Real-Called-Number
└─ IMS-Information (876, v10415)
├─ Role-Of-Node (829) = 0 (ORIGINATING_ROLE)
├─ Node-Functionality (862) = 6 (AS)
├─ User-Session-Id (830) = SIP Call-ID
├─ Calling-Party-Address (831)
├─ Called-Party-Address (832)
├─ Requested-Party-Address (1251)
├─ Time-Stamps (833)
│ ├─ SIP-Request-Timestamp (834)
│ ├─ SIP-Request-Timestamp-Fraction (2301)
│ ├─ SIP-Response-Timestamp (835) [一旦回答]
│ └─ SIP-Response-Timestamp-Fraction (2302) [一旦回答]
└─ Cause-Code (861) [CCR-T]
OmniTAS 发送的 AVP (CCR)
In 列显示哪些请求类型携带 AVP: I = CCR-Initial, U = CCR-Update, T = CCR-Terminate.
| AVP | 代码 | 供应商 | 类型 | In | 值 / 来源 |
|---|---|---|---|---|---|
| Session-Id | 263 | 0 | UTF8String | I U T | 每个呼叫的常量(源自 SIP Call-ID);在 I/U/T 中相同 |
| Origin-Host | 264 | 0 | DiameterIdentity | I U T | OmniTAS Diameter 身份 (origin_host.origin_realm) |
| Origin-Realm | 296 | 0 | DiameterIdentity | I U T | origin_realm |
| Destination-Realm | 283 | 0 | DiameterIdentity | I U T | OCS 领域 |
| Destination-Host | 293 | 0 | DiameterIdentity | I U T | 仅在配置特定 OCS 主机时存在 |
| Auth-Application-Id | 258 | 0 | Unsigned32 | I U T | 4 (Diameter 信贷控制应用) |
| Service-Context-Id | 461 | 0 | UTF8String | I U T | 000.000.12.32260@3gpp.org |
| CC-Request-Type | 416 | 0 | Enumerated | I U T | 1=初始, 2=更新, 3=终止 |
| CC-Request-Number | 415 | 0 | Unsigned32 | I U T | 初始为 0,然后为 1, 2, … |
| Event-Timestamp | 55 | 0 | Time | I U T | 请求生成的时间 |
| User-Name | 1 | 0 | UTF8String | I U T | 可选;仅在提供用户名/IMSI 时 |
| Termination-Cause | 295 | 0 | Enumerated | T | 1 (DIAMETER_LOGOUT) |
| Subscription-Id | 443 | 0 | Grouped | I U T | 订阅者身份(见子项) |
| → Subscription-Id-Type | 450 | 0 | Enumerated | I U T | 0 (END_USER_E164) |
| → Subscription-Id-Data | 444 | 0 | UTF8String | I U T | 订阅者 MSISDN |
| Multiple-Services-Credit-Control | 456 | 0 | Grouped | I U T | 信贷控制容器(见子项) |
| → Service-Identifier | 439 | 0 | Unsigned32 | I U T | service_identifier (稳定,已配置) |
| → Requested-Service-Unit | 437 | 0 | Grouped | I U | 预留请求 |
| → → CC-Time | 420 | 0 | Unsigned32 | I U | requested_units_seconds |
| → Used-Service-Unit | 446 | 0 | Grouped | T | 最终消耗 |
| → → CC-Time | 420 | 0 | Unsigned32 | T | 自回答以来消耗的秒数 |
| Service-Information | 873 | 10415 | Grouped | I U T | 3GPP 服务容器 |
| → IN-Information | - | 10415 | Grouped | I U T | 运营商扩展,携带真实拨打的号码 |
| → → Real-Called-Number | - | 10415 | UTF8String | I U T | 拨打(被叫)号码 |
| → IMS-Information | 876 | 10415 | Grouped | I U T | IMS 计费详情 |
| → → Role-Of-Node | 829 | 10415 | Enumerated | I U T | 0 (ORIGINATING_ROLE): MO 是被收费的腿 |
| → → Node-Functionality | 862 | 10415 | Enumerated | I U T | 6 (AS) |
| → → User-Session-Id | 830 | 10415 | UTF8String | I U T | SIP Call-ID (OCS 关联键) |
| → → Calling-Party-Address | 831 | 10415 | UTF8String | I U T | tel:+<calling MSISDN> |
| → → Called-Party-Address | 832 | 10415 | UTF8String | I U T | tel:+<called number> |
| → → Requested-Party-Address | 1251 | 10415 | UTF8String | I U T | tel:+<called number> |
| → → Time-Stamps | 833 | 10415 | Grouped | I U T | SIP 请求/响应时间 |
| → → → SIP-Request-Timestamp | 834 | 10415 | Time | I U T | INVITE 时间(整秒) |
| → → → SIP-Request-Timestamp-Fraction | 2301 | 10415 | Unsigned32 | I U T | INVITE 时间(毫秒) |
| → → → SIP-Response-Timestamp | 835 | 10415 | Time | U T | 回答(200 OK)时间: 仅在回答后 |
| → → → SIP-Response-Timestamp-Fraction | 2302 | 10415 | Unsigned32 | U T | 回答时间(毫秒): 仅在回答后 |
| → → Cause-Code | 861 | 10415 | Integer32 | T | 0 正常释放 / 2 设置失败 |
代码显示为
-的是运营商/供应商扩展,携带在Service-Information下;它们 没有 3GPP 分配的代码,并在 OmniTAS Diameter 字典中定义。
从 OCS 接收的 AVP (CCA)
| AVP | 代码 | 供应商 | 类型 | 描述 |
|---|---|---|---|---|
| Result-Code | 268 | 0 | Unsigned32 | 2001 = 成功;见 结果代码 |
| Granted-Service-Unit | 431 | 0 | Grouped | 分配的信贷 |
| → CC-Time | 420 | 0 | Unsigned32 | 授予的秒数 (allocated_time)。0 ⇒ 无信贷 ⇒ 拦截/挂断 |
| Service-Information | 873 | 10415 | Grouped | OCS 返回的可选计费数据 |
| → Carrier-Select-Routing-Information | 2023 | 10415 | UTF8String | 运营商路由代码(映射到 FreeSWITCH 变量) |
| → Alternate-Charged-Party-Address | 1280 | 10415 | UTF8String | 计费方标识符(映射到 FreeSWITCH 变量) |
所有在 CCA 中返回的 Service-Information 子 AVP 都被扁平化为 FreeSWITCH 通道
变量。请参阅 AVP 解析和变量映射 和
FreeSWITCH 通道变量。
FreeSWITCH 通道变量
所有提取的 AVP 数据作为 FreeSWITCH 通道变量可用:
| 变量名称 | 来源 | 示例值 | 描述 |
|---|---|---|---|
${allocated_time} | 授予的服务单元 / CC-Time | 600 | 分配的时间(秒) |
${CCA.Session-Id} | Session-Id AVP | omni-as01.epc...;1769299669873;325e2f2e | Diameter 会话标识符 |
${CCA.Result-Code} | Result-Code AVP | 2001 | CCA 结果 (2001 = 成功) |
${CCA.Auth-Application-Id} | Auth-Application-Id AVP | 4 | Diameter 应用程序 (4 = CC) |
${CCA.CC-Request-Type} | CC-Request-Type AVP | 1 | 请求类型 (1=初始) |
${CCA.CC-Request-Number} | CC-Request-Number AVP | 1 | 序列号 |
${CCA.CC-Time} | CC-Time AVP (如果存在) | 600 | 授予的时间配额 |
${CCA.Origin-Host} | Origin-Host AVP | ocs01.epc.mnc001.mcc001.3gppnetwork.org | OCS 主机标识符 |
${CCA.Origin-Realm} | Origin-Realm AVP | epc.mnc001.mcc001.3gppnetwork.org | OCS 领域 |
${CCA.Service-Information.Carrier-Select-Routing-Information} | Service-Information → Carrier-Select-Routing-Information | 1408 | OCS 的运营商路由代码 |
${CCA.Service-Information.Alternate-Charged-Party-Address} | Service-Information → Alternate-Charged-Party-Address | NickTest | 替代计费方 |
变量格式:
- 所有 CCA AVP 使用前缀
CCA. - 嵌套 AVP 使用点表示法:
CCA.Parent.Child - 变量名称中的点和连字符被保留
- 在 uuid_dump 中,变量以
variable_前缀出现
示例 uuid_dump 输出:
variable_allocated_time: 600
variable_CCA.Service-Information.Carrier-Select-Routing-Information: 1408
variable_CCA.Service-Information.Alternate-Charged-Party-Address: NickTest
variable_CCA.Result-Code: 2001