Spring Boot如何获取Twilio Autopilot提交的POST数据
Twilio Autopilot Collect对接Spring Boot实现方案
场景说明
我正在使用Twilio Autopilot的Collect功能,通过电话或短信收集用户输入。收集任务执行结束后,会通过POST方法重定向到我Spring Boot应用的指定端点。需求是通过Spring Boot应用完成用户输入的校验,之后向Twilio返回符合要求的Action JSON,告知用户其数据已被成功记录并通过校验。
现有Collect任务配置
{ "actions": [ { "say": "Hello!" }, { "collect": { "name": "get_prices", "questions": [ { "question": " Please enter the current price for 100 low led using the dial pad. When you are finished, press pound.", "voice_digits": { "finish_on_key": "#" }, "name": "price_100ll", "type": "Twilio.NUMBER", "validate": { "on_failure": { "messages": [ { "say": "Sorry, I didn't quite get that." } ], "repeat_question": true }, "on_success": { "say": "Great, we have successfully recorded your 100 low led price." } } } ], "on_complete": { "redirect": { "method": "POST", "uri": "https://<ngrok url pointing at my Spring Boot app>/report" } } } } ] }
原有端点代码问题
原有实现代码如下,存在的核心问题是直接用Object类型接收请求体,无法获取Twilio POST过来的表单参数,且返回空响应不符合Twilio Autopilot的响应规范:
@PostMapping(value = "/report", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) public ResponseEntity<Void> report(Object body) { return ResponseEntity.ok().build(); }
具体问题点:
- Twilio向重定向地址发送的是
application/x-www-form-urlencoded格式的请求,用户输入的所有收集数据都存放在名为Memory的表单字段中,该字段值为JSON字符串 - 端点不能返回空响应,必须返回Autopilot规范的Action JSON结构,否则Twilio端会抛出流程错误
正确实现步骤
- 参数接收:使用
@RequestParam("Memory")直接接收表单中的Memory字段,不需要额外映射整个请求体 - 数据解析:将Memory字符串反序列化为JSON对象,按路径提取Collect任务收集到的用户输入
- 业务校验:实现自定义的输入校验逻辑
- 响应构建:构建符合Autopilot规范的Actions数组,设置正确的JSON响应头返回
可直接运行的端点代码示例
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @RestController public class AutopilotCollectController { private final ObjectMapper objectMapper = new ObjectMapper(); @PostMapping(value = "/report", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) public ResponseEntity<Map<String, Object>> handleCollectComplete( @RequestParam("Memory") String memoryJson ) throws Exception { // 解析收集到的用户输入 JsonNode memoryNode = objectMapper.readTree(memoryJson); String userInputPrice = memoryNode .path("twilio") .path("collected_data") .path("get_prices") .path("answers") .path("price_100ll") .path("answer") .asText(); double price = Double.parseDouble(userInputPrice); // 自定义校验逻辑,示例为判断价格为合法正数 Object[] actions; if (price <= 0) { actions = new Object[]{ Map.of("say", "输入的价格无效,请重新提交。") }; } else { actions = new Object[]{ Map.of("say", "您提交的价格已成功记录并通过校验,感谢配合。") }; } // 返回符合Twilio规范的响应 return ResponseEntity.ok() .contentType(MediaType.APPLICATION_JSON) .body(Map.of("actions", actions)); } }
补充说明
- 该实现不需要强制依赖Twilio SDK,核心逻辑仅用Spring Boot默认集成的Jackson即可完成,足够应对大部分场景
- 如果需要更复杂的流程控制,比如校验失败后跳转回收集任务、转接人工等,只需要在返回的
actions数组中添加对应的Autopilot动作指令即可 - 本地调试时确保ngrok映射地址可正常公网访问,Twilio端能收到200状态码响应,否则会触发超时重试
内容的提问来源于stack exchange,提问作者rsteilberg
相关产品推荐
相关产品推荐

