呼叫接入TwiML App无响应时如何捕获并重定向至实体电话
实现方案结论
- 纯静态TwiML Bin无法完整实现需求,核心原因是静态XML不支持条件分支判断,会出现接通后仍触发转接的逻辑错误。
- 不需要搭建独立后端服务,用Twilio Functions搭配基础TwiML逻辑即可完整覆盖两个目标场景,配置和改造成本极低。
核心逻辑说明
需要覆盖两类需要转接的触发场景:
- 浏览器未打开:对应Twilio Client未在线注册,执行Dial操作时会立刻返回失败状态,无振铃等待
- 浏览器已打开、客户端正常振铃但超时无人接听:Dial操作到达设定超时时间后返回无应答状态
<Dial>动词执行结束后(无论接通、未接、不在线、占线),都会向配置的action地址发送携带DialCallStatus参数的回调请求,只需要在回调处理层判断状态值:如果是未接通类状态就转实体手机号,如果是正常接通后挂断就直接结束呼叫即可。
纯TwiML Bin的缺陷:静态XML无法根据回调参数做分支判断,无论呼叫是否接通,都会执行固定的下一步逻辑,会出现「浏览器端接完电话挂断后,系统仍然自动呼叫实体手机号」的异常。
可直接修改的代码片段
你需要创建两个Twilio Function,将第一个Function的访问地址配置为当前TwiML App的语音请求Webhook地址。
1. 呼入入口Function
用来处理初始呼入请求,优先拨打浏览器端Client:
exports.handler = function(context, event, callback) { const twiml = new Twilio.twiml.VoiceResponse(); // -------------------------- // 以下参数请根据实际情况修改 const BROWSER_CLIENT_NAME = "your_crm_client_name"; // CRM中配置的Twilio Client端用户名 const FORWARD_PHONE = "+8613xxxxxxxxx"; // 待转接的实体手机号,必须使用E.164格式 const RING_TIMEOUT = 12; // 浏览器端最长振铃时长(秒),建议设置为10-15 const DIAL_CALLBACK_URL = "https://你的Twilio服务域名/handle-dial-end"; // 第二个Function的公网访问地址 // 参数修改结束 // -------------------------- const dialAction = twiml.dial({ action: DIAL_CALLBACK_URL, method: "POST", timeout: RING_TIMEOUT }); dialAction.client(BROWSER_CLIENT_NAME); callback(null, twiml); };
2. 呼叫结果回调处理Function
路径和上面DIAL_CALLBACK_URL配置的路径保持一致,用来判断呼叫结果决定是否转接:
exports.handler = function(context, event, callback) { const twiml = new Twilio.twiml.VoiceResponse(); const FORWARD_PHONE = "+8613xxxxxxxxx"; // 和入口Function中配置的转接手机号保持一致 // 所有未成功接通的状态都触发转接 const needForwardStatus = ["no-answer", "failed", "busy", "canceled"]; if (needForwardStatus.includes(event.DialCallStatus)) { twiml.dial(FORWARD_PHONE); } else { // 正常接通后挂断,直接结束呼叫流程 twiml.hangup(); } callback(null, twiml); };
配置注意事项
- 所有手机号必须使用E.164格式填写:带国家码、无特殊符号,例如国内手机号以
+86开头,美国手机号以+1开头 - Twilio Function需要配置为公开可访问,不要开启请求鉴权,避免Twilio侧回调被拦截
- 代码中填写的
BROWSER_CLIENT_NAME需要和浏览器端Twilio Client注册时使用的用户名完全一致,大小写敏感 - 振铃时长不要设置超过20秒,避免运营商侧提前中断呼叫流程
- 如果你已有可处理公网HTTP请求的自建后端,也可以把回调逻辑放在自有后端实现,逻辑和上述代码完全一致,不需要强制使用Twilio Functions
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

