如何在Twilio Studio(或无Studio)实现可遍历HTTP结果的电话树?
嘿,我来帮你捋清楚这个Twilio电话树的实现思路,不管用不用Studio都有可行的方案,咱一步步来:
你已经能通过got()获取JSON数据了,核心问题是缓存数据和流程跳转时传递参数,其实Studio自带的Flow Context就能解决缓存问题,再配合组件参数传递就能打通整个流程:
1. 初始化:缓存JSON数据到Flow Context
不管用HTTP Request组件还是Function组件获取数据,都把结果存在Flow全局上下文里:
- 用HTTP Request组件:在组件设置里,把「Save Response To」选成「Flow」,变量名设为
schedules,这样整个流程都能通过flow.data.schedules访问到JSON数组。 - 用Function组件:在Function里请求数据后,把结果赋值给
event.flow.data.schedules,比如:exports.handler = async function(context, event, callback) { const got = require('got'); const schedules = await got('你的API地址').json(); // 把数据存入Flow Context event.flow.data.schedules = schedules; // 初始化遍历索引 event.flow.data.current_index = 0; // 跳转到第一个Gather组件 callback(null, { next: 'gather_address_schedule' }); };
2. 初始化遍历指针
加一个「Set Variables」组件,设置变量current_index的值为0,存储位置选「Flow」,这样后续就能用flow.data.current_index跟踪当前遍历的位置。
3. Gather组件配置
在gather_address_schedule组件里,播放当前索引对应的内容(比如用Say组件拼接flow.data.schedules[flow.data.current_index].title),然后提示来电者:「按1选择,按2跳过,按3退出」。记得把Gather的「Digits Collected Variable」设好,后续能拿到按键值。
4. Function组件处理按键逻辑
在function_address_schedule里,直接从Flow Context和Gather组件取参数,不用再重复请求API:
exports.handler = async function(context, event, callback) { const schedules = event.flow.data.schedules; let currentIndex = parseInt(event.flow.data.current_index); const pressedDigit = event.widgets.gather_address_schedule.Digits; let nextWidget = 'gather_address_schedule'; switch(pressedDigit) { case '1': // 这里写选择后的逻辑:比如记录到数据库、发送通知等 console.log(`用户选择了:${schedules[currentIndex].id}`); currentIndex++; // 选完后自动跳到下一个 break; case '2': currentIndex++; // 直接跳转到下一个 break; case '3': nextWidget = 'end_call'; // 跳转到结束通话的组件 break; default: nextWidget = 'invalid_prompt'; // 跳转到无效按键提示组件 break; } // 检查是否还有更多选项 if(currentIndex >= schedules.length && pressedDigit !== '3') { nextWidget = 'no_more_schedules'; // 跳转到无更多选项的提示组件 } // 更新Flow Context里的索引 callback(null, { next: nextWidget, flow: { data: { current_index: currentIndex } } }); };
5. 流程跳转
你之前遇到的「Split跳转回Function失败」的问题,其实只要在Split组件里根据Gather的按键值,直接跳转到function_address_schedule即可——Studio会自动把Gather的按键参数和Flow Context的数据一起传给Function,不需要额外配置入参。
如果觉得Studio的可视化流程限制多,可以直接用Twilio Functions+Twiml实现,核心是用Twilio Session缓存数据:
1. 主入口Function(处理来电)
exports.handler = async function(context, event, callback) { const got = require('got'); const twiml = new Twilio.twiml.VoiceResponse(); // 获取JSON数据并存入Session const schedules = await got('你的API地址').json(); event.session.schedules = JSON.stringify(schedules); event.session.current_index = 0; // 播放第一个选项并收集按键 const gather = twiml.gather({ action: '/process-keypress', method: 'POST', numDigits: 1 }); gather.say(`当前选项:${schedules[0].title},按1选择,按2跳过,按3退出`); callback(null, twiml); };
2. 按键处理Function(/process-keypress)
exports.handler = async function(context, event, callback) { const twiml = new Twilio.twiml.VoiceResponse(); const schedules = JSON.parse(event.session.schedules); let currentIndex = parseInt(event.session.current_index); const pressedDigit = event.Digits; switch(pressedDigit) { case '1': // 处理选择逻辑 console.log(`用户选择了:${schedules[currentIndex].id}`); currentIndex++; break; case '2': currentIndex++; break; case '3': twiml.hangup(); callback(null, twiml); return; default: twiml.say('无效按键,请重新输入'); // 跳回主入口重新播放当前选项 twiml.redirect('/main-voice'); callback(null, twiml); return; } // 检查是否还有更多选项 if(currentIndex >= schedules.length) { twiml.say('没有更多选项了,感谢来电'); twiml.hangup(); } else { // 更新Session索引,继续播放下一个选项 event.session.current_index = currentIndex; const gather = twiml.gather({ action: '/process-keypress', method: 'POST', numDigits: 1 }); gather.say(`当前选项:${schedules[currentIndex].title},按1选择,按2跳过,按3退出`); } callback(null, twiml); };
内容的提问来源于stack exchange,提问作者Michael Niño

