Twilio结合AppScript实现来电语音响应的代码故障排查
Twilio + AppScript 来电自动语音交互失效修复方案
核心问题汇总
当前代码和配置存在4类问题,逐一修复即可实现预期效果:
1. doGet返回内容格式非法
原代码使用HtmlService.createHtmlOutputFromFile加载twiml文件时,服务会自动给内容注入<!DOCTYPE html>、<html>、<body>等网页包装标签,最终返回的内容不是纯TwiML XML格式,Twilio无法解析,自然不会触发语音播放。
修复方案
两种实现方式二选一即可:
- 方式1(推荐,无需额外存twiml文件):直接在doGet中返回纯TwiML字符串,避免多余标签注入
function doGet(e) { // 注意替换下面action属性里的地址为你自己的AppScript Web应用部署地址 const twiml = ` <Response> <Gather timeout="10" numDigits="1" action="替换为你的AppScript Web应用部署链接"> <Say voice="man" language="en-us"> Welcome to John auto parts. To leave us a message, press 1. To cancel an appointment, press 2. </Say> </Gather> <Say voice="man" language="en-us">We didn't receive any input from you. Goodbye!</Say> <Hangup/> </Response> `; return ContentService.createTextOutput(twiml.trim()) .setMimeType(ContentService.MimeType.XML); }
- 方式2:保留独立twiml文件的话,加载后过滤掉自动注入的HTML标签
function doGet(e) { const rawContent = HtmlService.createHtmlOutputFromFile("twiml").getContent(); // 正则提取纯TwiML的Response节点内容 const validTwiml = rawContent.match(/<Response>[\s\S]*<\/Response>/)[0]; return ContentService.createTextOutput(validTwiml) .setMimeType(ContentService.MimeType.XML); }
2. TwiML语法不符合Twilio规范
原TwiML存在3个硬伤:
<Gather>标签缺少必填的action属性,用户按键后Twilio找不到结果提交地址,会直接触发兜底的无输入逻辑timeout="3"等待时间过短,用户往往还没听完完整提示就触发超时- 提示文案存在错误:电话场景是按键(press)不是点击(click),拼写错误
anwers应为input/answers,且未限制按键输入长度,容易出现识别异常
修复后的标准TwiML
参考上面代码块里的TwiML内容即可,核心调整点:
- 给
<Gather>加action属性指向你的AppScript地址,加numDigits="1"限制只接收1位按键输入 - 把超时时间调整为10秒,给用户足够的反应时间
- 修正文案错误,最后加
<Hangup/>标签明确结束通话
3. AppScript部署配置错误
这是最高发的失效原因,必须按以下要求配置部署:
- 部署类型选择「Web 应用」
- 执行身份选择「我」
- 访问权限必须选择任何人,如果选仅自己/仅组织内用户,Twilio的公网请求会被拦截返回403
- 每次修改代码后必须重新部署生成新版本,旧版本的链接不会同步更新代码
4. Twilio后台配置校验
- 进入Twilio控制台你购买的号码配置页,找到「A Call Comes In」配置项
- 回调类型选择Webhook,填入你部署完成拿到的AppScript Web应用链接
- 请求方式选择HTTP GET(和你实现的doGet方法对应,不要选POST)
- 保存后可以先用Twilio控制台内置的测试呼叫功能验证,查看Twilio请求日志返回200状态码、响应内容为纯TwiML XML即可正常使用。
内容的提问来源于stack exchange,提问作者Le Pirate Noir
相关产品推荐
相关产品推荐

