Node.js/Express中ServiceM8 Webhook挑战验证始终返回‘Invalid callback challenge key returned’的问题求助
解决ServiceM8 Webhook订阅的"Invalid callback challenge key returned"错误
我之前在Node.js/Express环境里成功实现过ServiceM8的Webhook验证,刚好能帮你排查这个问题!
首先明确一个关键信息:ServiceM8的订阅挑战请求是通过GET方法发送的,不是POST。你的代码虽然兼容了两种请求方式,但可能就是这个兼容逻辑里藏了问题。
可能的问题点及修复方案
中间件干扰了GET请求参数
如果你在Express里使用了express.json()或express.urlencoded()这类中间件,虽然它们默认只处理POST请求,但有时候可能会因为配置问题影响到GET请求的query解析。建议你把GET和POST请求分开处理,让逻辑更清晰,也避免冲突。响应内容不符合要求
ServiceM8要求你原封不动返回challenge字符串,不能有任何额外字符(比如空格、换行、响应格式错误)。你的代码里用res.send(challenge)本身没问题,但最好显式指定响应类型为纯文本,避免Express默认添加的Content-Type导致问题。
经过验证的Express实现代码
const express = require('express'); const app = express(); // 仅处理POST请求的JSON body,不影响GET请求的query参数 app.use(express.json()); // 专门处理ServiceM8的订阅挑战(GET请求) app.get('/webhook/job-complete', (req, res) => { const { challenge, mode } = req.query; // 验证模式和挑战密钥是否存在 if (mode === 'subscribe' && challenge) { // 显式设置纯文本类型,原封不动返回挑战密钥 return res.type('text/plain').send(challenge); } // 非挑战请求返回200 res.sendStatus(200); }); // 处理实际的Webhook事件通知(POST请求) app.post('/webhook/job-complete', (req, res) => { // 这里处理收到的Webhook数据 console.log('收到ServiceM8 Webhook:', req.body); // 必须返回200确认收到 res.sendStatus(200); }); app.listen(3000, () => { console.log('服务器运行在端口3000'); });
额外排查步骤
- 确认你的服务器公网可访问(可以用ngrok这类工具临时暴露本地服务测试)
- 查看服务器日志,对比收到的
challenge和ServiceM8返回的错误里的Expected值是否完全一致,有没有被转义或修改 - 确保没有防火墙、反向代理(比如Nginx)修改了请求参数或响应内容
内容的提问来源于stack exchange,提问作者user32528474
相关产品推荐
相关产品推荐

