IVR 与 billing server 应如何集成?
结论
IVR 可以在转接人工座席或提供付费服务前调用 billing server,检查用户的账户状态、余额或信用资格。至于是否要在呼叫刚进入 IVR 时检查,需要根据具体的计费规则决定。
一般可以采用以下流程:
- 呼叫进入 IVR 后,先识别用户身份。
- 用户选择付费业务或要求转接人工座席时,再检查 billing/credit eligibility。
- 检查通过后继续处理呼叫;检查未通过时,播放对应提示,引导用户充值、改用免费服务或结束呼叫。
- 通话结束后,按照实际使用情况扣费或结算。
IVR 不应直接读写 billing server 的数据库。两个系统之间应通过受控的 API 或计费网关进行集成。
为什么不建议一进入 IVR 就统一检查
如果 IVR 还提供余额查询、故障申报等免费功能,在入口处统一拦截会让欠费用户无法使用这些服务。更合适的方式是在具体的服务节点进行判断:
- 入口阶段:识别用户,但不一定马上检查余额。
- 业务选择阶段:判断用户选择的服务是否收费。
- 授权阶段:向 billing server 查询资格,必要时预留额度。
- 服务阶段:转接 agent 或进入相应业务。
- 结束阶段:提交实际用量并完成结算。
如果所有进入 IVR 的呼叫都需要收费,或者监管、风控规则要求预先验证信用,则可以在入口阶段进行检查。
推荐集成流程
1. 识别用户
IVR 可以通过以下信息识别账户:
- 主叫号码,即 ANI/CLI
- 用户输入的账号或客户编号
- PIN、OTP 等验证信息
- 可信上游写入 SIP Header 的标识
通常不能只凭主叫号码完成强身份认证,因为号码可能被隐藏、转移或伪造。
2. 查询计费资格
IVR 或呼叫控制服务可以向 billing server 发起同步授权请求,例如:
POST /api/v1/credit/authorize
Content-Type: application/json
Authorization: Bearer <access-token>
{
"accountId": "acct_12345",
"callId": "call_8f20c1",
"serviceCode": "AGENT_SUPPORT",
"estimatedAmount": 5.00,
"currency": "CNY"
}
billing server 可以返回结构化结果:
{
"eligible": true,
"authorizationId": "auth_72b91f",
"approvedAmount": 5.00,
"reasonCode": "APPROVED",
"expiresAt": "2026-08-29T10:15:00Z"
}
以上 API 路径和字段仅用于说明接口设计,实际名称应以现有 billing server 提供的能力为准。
3. 根据结果路由呼叫
伪代码如下:
identity = identifyCaller(call)
if identity is invalid:
routeToAuthenticationFlow()
return
service = collectServiceSelection()
if service.isFree:
continueService(service)
return
result = billing.authorize(
accountId = identity.accountId,
callId = call.id,
serviceCode = service.code
)
if result.eligible:
attachAuthorization(call, result.authorizationId)
transferToAgentOrService(service)
else:
playPrompt(mapReasonCode(result.reasonCode))
offerRechargeOrFreeService()
if noAlternativeSelected:
terminateCall()
billing server 应返回稳定且可供机器读取的 reasonCode,例如 INSUFFICIENT_CREDIT、ACCOUNT_SUSPENDED 或 ACCOUNT_NOT_FOUND。IVR 再将这些代码映射成适合用户收听的语音提示,不要根据错误消息文本判断后续流程。
4. 完成结算
授权通过并不代表已经完成最终扣费。通话结束后,应按照实际通话时长或服务结果提交结算请求:
POST /api/v1/credit/capture
Content-Type: application/json
Authorization: Bearer <access-token>
{
"authorizationId": "auth_72b91f",
"callId": "call_8f20c1",
"billableSeconds": 420,
"finalAmount": 3.50,
"currency": "CNY"
}
如果呼叫未能成功转接,或者服务并未实际发生,应释放预留额度:
POST /api/v1/credit/release
Content-Type: application/json
Authorization: Bearer <access-token>
{
"authorizationId": "auth_72b91f",
"callId": "call_8f20c1",
"reasonCode": "TRANSFER_FAILED"
}
究竟采用”只查询余额”、“预授权后结算”还是”实时扣费”,需要根据计费模型确定。对于按分钟收费且信用风险较高的场景,系统还可能需要周期性地重新授权。
超时和故障处理
billing server 是呼叫流程中的重要依赖,但 IVR 不能无限等待其响应。相关配置应明确包括:
- 请求超时时间
- 有限次数的重试
- billing server 不可用时的降级策略
- 重复请求的幂等规则
- 审计日志和告警机制
授权接口应支持幂等键,防止系统因网络超时而重试时重复冻结额度:
Idempotency-Key: call_8f20c1_AGENT_SUPPORT
billing server 超时后的处理方式必须由业务规则决定:
- Fail closed:拒绝提供付费服务,适用于高风险业务。
- Fail open:暂时提供服务,事后补记账,适用于风险较低且更看重可用性的业务。
- 受限降级:只开放免费菜单、紧急服务或指定座席队列。
IVR 开发人员不能自行假定应采用哪种策略,需要由计费、风控和业务负责人共同确认。
注意事项
- 使用
callId、accountId和authorizationId关联授权、转接与结算记录。 - 金额应使用定点小数或以最小货币单位表示的整数,不能用二进制浮点数进行财务计算。
- API 通信应使用 TLS,并通过 OAuth 2.0、mTLS 或同等机制完成服务间认证。
- 日志中不要记录 PIN、完整支付信息、访问令牌等敏感数据。
- 余额检查不能误拦截免费服务、紧急呼叫以及法规要求保留的服务。
- 系统必须处理转接失败、用户提前挂机、重复回调和结算通知乱序等情况。
- IVR 提示应区分余额不足、账户停用、身份无法确认和系统暂时不可用,不能统一播放”信用不足”。
- 如果 agent 通话由独立的 ACD、SIP 平台或媒体服务器控制,最终用量应由能够可靠接收呼叫开始、应答和结束事件的组件提交。
billing server 应负责授权和结算,IVR 则负责用户交互与呼叫路由。IVR 在进入需要付费权限的业务节点时调用计费授权,通过后再执行转接;呼叫结束后,根据实际使用量结算。这样的职责划分也便于处理失败和重试。
备注:内容仅供参考。
