Facebook Messenger Bot中“Get Started”Postback事件重复接收问题
嘿,我之前也碰到过类似的糟心事,结合你提到的「返回空200就不会重复」这个关键信息,大概率是Webhook响应的时机或格式出了问题,下面给你拆解几个最可能的原因:
Webhook响应超时触发平台重试
Messenger平台要求Webhook必须在10秒内返回200 OK的确认响应。如果你的Node.js应用在收到Postback事件后,先忙着处理业务逻辑(比如调用外部API、写数据库),导致超过10秒才返回响应,平台会判定第一次请求失败,自动发起重试,这就会让你收到两次相同的Postback事件。而你测试返回空200时,因为响应速度极快,平台确认接收成功,自然不会重试。响应内容不符合平台要求
哪怕你返回了200状态码,如果响应体带了多余内容(比如错误日志、无关的JSON结构),或者Content-Type设置不对,Messenger平台可能不认为这是有效的确认,同样会触发重试。这也解释了为什么返回空200就能解决问题——空响应是平台认可的标准确认格式。Webhook事件重复订阅(可能性较低)
可以去Facebook开发者后台检查下你的Webhook订阅设置,有没有不小心重复勾选了postback事件类型?不过这种情况比较少见,而且如果是重复订阅,应该每次操作都会收到多次事件,结合你的测试结果,这个原因优先级相对低一些,但还是建议确认下。本地调试工具的代理重试
如果你用ngrok这类工具做本地开发调试,有时候网络不稳定或者代理本身的重试机制,可能会把同一个请求重复转发给你的Node.js应用。可以试试把代码部署到稳定的服务器上测试,看是否还会出现重复事件。
快速解决建议
- 先响应后处理:收到Postback事件后,第一时间返回空的200响应,再在后台异步处理业务逻辑,比如用队列或者async/await拆分逻辑:
app.post('/webhook', (req, res) => { // 先快速返回确认 res.status(200).send(''); // 后台异步处理业务 handlePostback(req.body); }); async function handlePostback(payload) { // 这里写你的业务逻辑:发送回复、更新用户数据等 } - 严格控制响应格式:确保响应只返回空字符串,不要附带任何额外内容,Content-Type可以设为
text/plain或者干脆不设置。 - 核对Webhook订阅列表:确认
postback事件只订阅了一次,避免重复推送。
内容的提问来源于stack exchange,提问作者Bubble Trouble

