Flask与Twilio集成问题:无法响应用户WhatsApp消息
问题排查与解决方案:Flask+Twilio WhatsApp巴士预订机器人
一、代码核心问题排查
1. 全局用户状态管理错误
- 新用户判断逻辑矛盾:当
sender_number not in user时直接返回纯文本,既不符合Twilio的XML响应要求,还会跳过后续状态初始化逻辑。 - 变量覆盖导致状态丢失:初始化单个用户状态后,错误地将全局
user字典覆盖为单个用户的状态字典,后续其他用户请求会触发KeyError,且原有状态全部丢失。
2. Twilio响应格式不规范
- 直接返回字符串(如
return "Welcome I see is your first time.")无法被Twilio正确解析,必须返回MessagingResponse生成的XML格式响应。 - 代码中错误地将
messaging_response对象替换为字符串(如messaging_response = "May i have your name:"),破坏了响应结构。
3. 条件分支逻辑混乱
incoming_msg in allowed_messages分支优先执行,会覆盖后续基于用户状态的响应内容,且allowed_messages未定义会触发NameError。user["state"] = "menu"直接写在if user["state"] == "start"分支外,无论当前状态如何都会强制修改状态,导致状态流转完全失效。- 多行字符串拼接存在语法错误,未正确处理换行和引号闭合。
4. 状态流转逻辑缺失
- 缺少对
ask_name等后续状态的处理逻辑,用户回复姓名后无响应。 - 取消预订的响应未使用
MessagingResponse对象,格式错误。
二、修复后的核心代码
from flask import Flask, request from twilio.twiml.messaging_response import MessagingResponse app = Flask(__name__) # 全局用户状态字典,生产环境建议用数据库替代 user_states = {} allowed_commands = {"start", "book", "cancel", "hi", "hello"} @app.route("/Teebot", methods=['POST']) def bot(): app.logger.info(f"Incoming request data: {request.data}") app.logger.info(f"Twilio Headers: {request.headers}") incoming_msg = request.values.get("Body", "").strip().lower() sender_number = request.values.get("From", None) # 初始化新用户状态 if sender_number not in user_states: user_states[sender_number] = {"state": "start"} current_state = user_states[sender_number]["state"] resp = MessagingResponse() msg = resp.message() # 优先处理初始命令,触发状态流转 if incoming_msg in allowed_commands and current_state == "start": user_states[sender_number]["state"] = "menu" # 根据用户状态处理响应 if current_state == "start": msg.body("Welcome to bus booking. How can I serve you?\nPlease select an option:\n1. Book a seat\n2. Cancel Booking") elif current_state == "menu": if incoming_msg == "1": user_states[sender_number]["state"] = "ask_name" msg.body("May I have your name?") elif incoming_msg == "2": msg.body("Please call 73409887 for cancellation") else: msg.body("Please select a valid option: 1 for booking, 2 for cancellation") elif current_state == "ask_name": # 保存用户姓名,进入下一步 user_states[sender_number]["name"] = incoming_msg user_states[sender_number]["state"] = "ask_contact" msg.body(f"Thanks {incoming_msg.title()}! Please provide your phone number.") elif current_state == "ask_contact": # 保存联系方式,进入班次选择 user_states[sender_number]["contact"] = incoming_msg user_states[sender_number]["state"] = "select_schedule" msg.body("Please select a bus schedule:\n1. 08:00 AM - City Center to Suburb\n2. 02:00 PM - Suburb to City Center") # 可继续扩展后续状态(如座位选择、确认等) return str(resp) if __name__ == "__main__": app.run(debug=True)
三、优化后的预订流程方案
1. 新用户引导
- 用户首次发送消息时,直接进入初始状态,展示欢迎语和功能菜单。
- 支持触发命令(start/book/cancel/hi/hello)快速进入菜单。
2. 预订流程闭环
- 菜单选择:用户选1进入预订流程
- 信息收集:依次收集姓名、联系方式
- 班次选择:展示可选巴士班次
- 座位确认:用户选择座位后,发送预订确认信息(含班次、座位号、联系方式)
- 完成反馈:告知用户预订成功,提供取消方式
3. 取消预订处理
- 用户选2时,引导拨打指定电话处理(或扩展为在线取消逻辑,需验证预订信息)
4. 生产环境优化建议
- 替换全局
user_states字典为数据库(如SQLite/Redis),避免重启服务丢失状态。 - 添加错误捕获与日志记录,便于排查Twilio请求异常。
- 增加输入验证(如联系方式格式检查),提升交互体验。
内容的提问来源于stack exchange,提问作者Karabo Mpedi
相关产品推荐
相关产品推荐

