如何等待Twilio IVR流程完成并获取用户响应以控制数据存储
可行实现方案
因为Twilio Studio的IVR流程是异步交互(需等待用户操作,耗时不确定),直接同步等待twilioIvrService返回结果会导致API超时,所以推荐采用临时存储+回调通知的方案,具体步骤如下:
1. 改造Twilio Studio流程,添加结果回调
在IVR流程的最后一步(结束流程前),新增「Make HTTP Request」组件,配置如下:
- 请求方法:POST
- 请求URL:你的后端回调接口地址(比如
https://your-domain.com/api/twilio-ivr-callback) - Body类型:Form-Encoded
- 添加参数:
value: 用户选择对应的布尔值(示例:{{widgets.choice_widget.parsed.Answer === '1' ? 'true' : 'false'}},根据你的流程变量逻辑调整)formId: 关联表单数据的唯一标识(从触发流程的参数中获取,即{{trigger.FormId}})
2. 调整后端主API逻辑,改用异步处理
原同步等待逻辑不适用,改成先临时存储表单、触发IVR后立即响应前端:
// 引入Redis客户端(或其他临时存储方案) const redisClient = require('./redis-client'); // 主API接口 async function handleFormSubmit(req, res) { try { const form = req.body; await validateForm(form); // 生成唯一formId关联表单数据 const formId = `form_${Date.now()}_${Math.random().toString(36).slice(2)}`; // 表单存入Redis,设置1小时过期时间(可按需调整) await redisClient.setEx(formId, 3600, JSON.stringify(form)); // 触发Twilio IVR并传递formId await twilioIvrService(form.phone, formId); // 立即返回响应告知用户IVR已启动 return res.json({ message: "IVR流程已启动,请等待后续处理结果" }); } catch (error) { console.error(error); return res.status(500).json({ message: "操作失败" }); } }
3. 改造twilioIvrService,传递formId参数
修改服务函数,触发Studio流程时携带formId,让流程能拿到该标识:
const twilioIvrService = async (phone, formId) => { try { const { data } = await axios.post( url, // 你的Twilio Studio REST API Trigger地址 new URLSearchParams({ To: phone, From: TWILIO_PHONE, FormId: formId, // 新增参数传递给Studio流程 }), { auth: { username: twilioAccountSid, password: twilioAuthToken, }, }, ); console.log("IVR流程触发成功", data); } catch (error) { console.error("IVR流程触发失败", error); throw error; // 抛出错误让上层处理 } };
4. 编写回调接口,处理IVR结果
新增接口接收Twilio的回调,根据返回的value决定是否存储数据:
async function handleTwilioCallback(req, res) { try { const { value, formId } = req.body; // 从Redis取出表单数据 const formStr = await redisClient.get(formId); if (!formStr) { return res.status(404).json({ message: "表单数据已过期或不存在" }); } const form = JSON.parse(formStr); // 仅当value为true时调用saveData if (value === 'true') { await saveData(form); // 可选:删除已处理的临时数据 await redisClient.del(formId); console.log("表单数据已成功存储"); } else { console.log("用户选择不存储数据"); } // 返回Twilio要求的200响应(否则Twilio会重试回调) return res.status(200).send("OK"); } catch (error) { console.error("回调处理失败", error); return res.status(500).send("Error"); } }
关键说明
- 临时存储选Redis是因为它支持键值对存储、过期时间设置,读写性能高,5KB表单数据完全适配;
- Twilio的「Make HTTP Request」组件必须在流程结束前执行,否则IVR结束后不会触发回调;
- 回调接口必须返回200状态码,否则Twilio会重复发送回调请求(默认重试4次);
- 若需通知用户处理结果,可在
saveData执行完成后通过WebSocket、短信或邮件等方式告知。
内容的提问来源于stack exchange,提问作者Fernando
相关产品推荐
相关产品推荐

