You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何等待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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:17:18