WhatsApp Business API Webhook多次触发重复回复问题求助
解决WhatsApp Business API Webhook重复触发导致重复回复的问题
核心问题分析
- 响应不及时:你的代码要完成自有API调用和WhatsApp回复后才返回
200响应,WhatsApp服务器如果在10秒内没收到响应,会重复推送相同的Webhook事件,导致重复处理。 - 无去重机制:即使WhatsApp重复推送,代码没有判断消息是否已处理,会重复执行回复逻辑。
- 代码语法错误:现有axios请求存在语法问题(
END_POINT_URL后缺少逗号、Authorization行末尾缺少逗号),可能导致请求失败,进一步触发重试。
解决方案
1. 立即返回200响应
优先给WhatsApp服务器返回200 OK,告知已收到事件,再异步处理业务逻辑。
2. 添加消息去重机制
利用每个WhatsApp消息的唯一id字段,用缓存(比如Redis)记录已处理的消息ID,处理前先校验是否已处理过,避免重复执行。
3. 修复代码语法错误
修正axios请求中的语法问题,确保请求能正常执行。
修改后的代码示例
const redis = require('redis'); // 引入Redis客户端,需先执行npm install redis const client = redis.createClient(); // 根据你的Redis配置初始化客户端 client.connect().catch(console.error); app.post("/webhook", async (req, res) => { // 第一步:立即返回200响应,避免WhatsApp触发重试 res.status(200).end(); const body = req.body; console.log(JSON.stringify(body, null, 2)); if (body.object) { const messageEntry = body.entry[0]?.changes[0]?.value?.messages?.[0]; if (!messageEntry) return; const phone_number_id = body.entry[0].changes[0].value.metadata.phone_number_id; const from = messageEntry.from; const msg_body = messageEntry.text.body; const messageId = messageEntry.id; // 获取消息唯一标识ID // 第二步:检查消息是否已处理过 const isProcessed = await client.get(`processed:${messageId}`); if (isProcessed) { console.log(`消息${messageId}已处理,跳过执行`); return; } try { // 调用自有API const apiResponse = await axios({ method: "POST", url: API_URL, data: { id: phone_number_id, question: msg_body, email: "N/A", conversation: [], save: true, resolved: "N/A", ads: 0, }, headers: { "Content-Type": "application/json", "x-api-key": process.env.API_KEY, }, }); if (apiResponse.status !== 200) { throw new Error(`请求失败,状态码${apiResponse.status}`); } const responseData = apiResponse.data; console.log(responseData); // 发送WhatsApp回复消息 await axios({ method: "POST", url: END_POINT_URL, headers: { "Content-Type": "application/json", Authorization: TOKEN, }, data: { to: from, type: "text", text: { preview_url: false, body: responseData.answer, }, messaging_product: "whatsapp", recipient_type: "individual", }, }); // 标记消息为已处理,设置24小时过期时间,避免缓存无限增长 await client.setEx(`processed:${messageId}`, 86400, "true"); } catch (error) { console.error("业务处理出错:", error); } } });
额外注意事项
- 如果没有Redis,也可以用内存缓存(比如
Map),但重启服务后会丢失已处理记录,生产环境建议使用持久化缓存。 - 优化自有API的响应速度,避免业务逻辑耗时过长影响用户体验。
- 确认WhatsApp Webhook的重试规则,确保去重逻辑覆盖所有可能的重试场景。
内容的提问来源于stack exchange,提问作者callan george
相关产品推荐
相关产品推荐

