You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。你的代码虽然兼容了两种请求方式,但可能就是这个兼容逻辑里藏了问题。

可能的问题点及修复方案

  1. 中间件干扰了GET请求参数
    如果你在Express里使用了express.json()或express.urlencoded()这类中间件,虽然它们默认只处理POST请求,但有时候可能会因为配置问题影响到GET请求的query解析。建议你把GET和POST请求分开处理,让逻辑更清晰,也避免冲突。

  2. 响应内容不符合要求
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 06:37:35