PAYATHON 2026

IVR 与 billing server 应如何集成?

支付老李

结论

IVR 可以在转接人工座席或提供付费服务前调用 billing server,检查用户的账户状态、余额或信用资格。至于是否要在呼叫刚进入 IVR 时检查,需要根据具体的计费规则决定。

一般可以采用以下流程:

  • 呼叫进入 IVR 后,先识别用户身份。
  • 用户选择付费业务或要求转接人工座席时,再检查 billing/credit eligibility。
  • 检查通过后继续处理呼叫;检查未通过时,播放对应提示,引导用户充值、改用免费服务或结束呼叫。
  • 通话结束后,按照实际使用情况扣费或结算。

IVR 不应直接读写 billing server 的数据库。两个系统之间应通过受控的 API 或计费网关进行集成。

为什么不建议一进入 IVR 就统一检查

如果 IVR 还提供余额查询、故障申报等免费功能,在入口处统一拦截会让欠费用户无法使用这些服务。更合适的方式是在具体的服务节点进行判断:

  1. 入口阶段:识别用户,但不一定马上检查余额。
  2. 业务选择阶段:判断用户选择的服务是否收费。
  3. 授权阶段:向 billing server 查询资格,必要时预留额度。
  4. 服务阶段:转接 agent 或进入相应业务。
  5. 结束阶段:提交实际用量并完成结算。

如果所有进入 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 在进入需要付费权限的业务节点时调用计费授权,通过后再执行转接;呼叫结束后,根据实际使用量结算。这样的职责划分也便于处理失败和重试。

备注:内容仅供参考。