Node.js版Facebook Webhook无法接收测试POST请求求助
Facebook Webhook无法接收测试POST请求排查方案
问题概述
用Node.js搭建的Facebook Webhook,GET验证请求能正常接收,Postman发送相同JSON POST请求也能正常响应,但Facebook后台显示请求已发送,服务器却收不到测试POST请求,当前处于开发模式。
可能的原因及解决办法
1. 请求解析中间件缺失
Facebook发送的POST请求为application/json格式,若Express应用未配置express.json()中间件,会导致req.body为空,服务器直接返回400错误,而Facebook后台可能仅显示请求已发送,不提示错误状态。
- 解决:在路由配置前添加中间件:
app.use(express.json()); // 必须放在app.post('/webhook', ...)之前调用
2. 未验证请求签名
Facebook会对Webhook请求做签名验证,若服务器未验证签名,可能被判定为无效接收,或在部分环境下被拦截请求。
- 解决:添加签名验证逻辑:
const crypto = require('crypto'); app.post('/webhook', (req, res) => { // 验证请求签名 const signature = req.headers['x-hub-signature-256']; if (!signature) { console.log('请求缺失签名'); return res.sendStatus(403); } const hmac = crypto.createHmac('sha256', process.env.FB_APP_SECRET); const digest = `sha256=${hmac.update(JSON.stringify(req.body)).digest('hex')}`; if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest))) { console.log('签名验证失败'); return res.sendStatus(403); } // 原有业务逻辑 console.log(`收到${req.method}请求:${req.url}`); console.log(`请求体:${JSON.stringify(req.body)}`); if (!req.body || Object.keys(req.body).length === 0) { console.log('请求体为空'); res.status(400).send('Bad Request: Request body is empty'); return; } let body = req.body; if (body.object === 'page') { body.entry.forEach(entry => { const webhook_event = entry.messaging[0]; console.log(webhook_event); }); res.status(200).send('EVENT_RECEIVED'); } else { res.sendStatus(404); } });
3. 服务器响应超时
Facebook要求Webhook在10秒内返回响应,若服务器处理逻辑耗时过长或网络延迟,Facebook会判定请求失败,但后台仍可能显示“已发送”。
- 解决:先快速返回响应,再异步处理消息:
app.post('/webhook', (req, res) => { // 先返回响应避免超时 res.status(200).send('EVENT_RECEIVED'); // 异步处理消息逻辑 process.nextTick(() => { console.log(`收到${req.method}请求:${req.url}`); console.log(`请求体:${JSON.stringify(req.body)}`); if (!req.body || Object.keys(req.body).length === 0) { console.log('请求体为空'); return; } let body = req.body; if (body.object === 'page') { body.entry.forEach(entry => { const webhook_event = entry.messaging[0]; console.log(webhook_event); }); } }); });
4. 开发环境暴露问题
若服务器运行在本地,使用ngrok等工具暴露端口,可能存在隧道过期、连接不稳定的情况,导致Facebook请求无法到达。
- 解决:
- 检查ngrok隧道状态,重新生成隧道并更新Facebook后台的回调URL
- 确保本地防火墙未拦截外部请求
5. Webhook订阅字段未配置
Facebook后台Webhook订阅设置中,若未勾选所需的消息事件字段,不会发送测试请求。
- 解决:进入Facebook开发者后台,在Webhook设置中勾选
messages等需要的事件字段,重新完成订阅。
内容的提问来源于stack exchange,提问作者Chris Kariuki
相关产品推荐
相关产品推荐

