Node.js/Express搭建Dialogflow Webhook遇错误及自定义Payload发送问题
解决Dialogflow Webhook "Invalid or unknown request type" 错误并实现自定义Payload发送
一、修复"Invalid or unknown request type"错误
1. 替换过时依赖
原dialogflow-fulfillment包已停止维护,迁移到官方新版@dialogflow/fulfillment,移除旧版actions-on-google(无需适配Google Assistant时)。更新后的package.json依赖:
"dependencies": { "@dialogflow/fulfillment": "^0.6.1", "axios": "^1.5.0", "body-parser": "^1.20.2", "cors": "^2.8.5", "express": "^4.18.2" }
执行npm install更新依赖。
2. 配置CORS中间件
Dialogflow Messenger的请求属于跨域请求,必须添加CORS支持:
const express = require("express"); const bodyParser = require("body-parser"); const cors = require("cors"); const { WebhookClient } = require("@dialogflow/fulfillment"); const app = express(); // 生产环境建议限制特定域名,此处允许所有来源测试 app.use(cors()); app.use(bodyParser.json());
3. 验证Dialogflow控制台配置
在Dialogflow控制台Fulfillment页面:
- 确认Webhook URL指向你的服务地址
- 选择Webhook version为V2(旧版库不支持V3)
- 勾选需要触发Webhook的目标意图(如
webhookDemo)
4. 强制指定请求版本(可选)
若自动版本检测失败,手动指定v2版本初始化WebhookClient:
const agent = new WebhookClient({ request: req, response: res, version: 'v2' });
二、实现Dialogflow Messenger自定义Payload发送
自定义Payload支持发送按钮、图片、卡片等富媒体消息,以下是常见示例:
1. 文本+自定义按钮示例
// 顶部导入Payload const { WebhookClient, Payload } = require("@dialogflow/fulfillment"); function demo(agent) { // 基础文本回复 agent.add("Message from webhook server"); // Dialogflow Messenger自定义Payload const payload = { "richContent": [ [ { "type": "button", "icon": { "type": "chevron_right", "color": "#FF9800" }, "text": "查看详情", "link": "https://example.com/details", "buttonText": "点击访问" } ] ] }; agent.add(new Payload(agent.UNSPECIFIED, payload, { rawPayload: true, sendAsMessage: true })); }
2. 图片卡片示例
function demo(agent) { const payload = { "richContent": [ [ { "type": "image", "rawUrl": "https://example.com/cover.jpg", "accessibilityText": "产品封面图" }, { "type": "info", "title": "产品名称", "subtitle": "产品简介" } ] ] }; agent.add(new Payload(agent.UNSPECIFIED, payload, { rawPayload: true })); }
3. 直接构造响应(无WebhookClient)
若WebhookClient仍有问题,可直接返回符合v2格式的响应:
app.post("/", (req, res) => { const intentName = req.body.queryResult.intent.displayName; if (intentName === "webhookDemo") { const responseJson = { fulfillmentMessages: [ { text: { text: ["Message from webhook server"] } }, { payload: { "richContent": [ [ { "type": "button", "text": "自定义按钮", "link": "https://example.com" } ] ] } } ] }; res.json(responseJson); } else { res.json({ fulfillmentText: "默认回复" }); } });
完整修复后server.js示例
const express = require("express"); const bodyParser = require("body-parser"); const cors = require("cors"); const { WebhookClient, Payload } = require("@dialogflow/fulfillment"); const app = express(); app.use(cors()); app.use(bodyParser.json()); app.post("/", (req, res) => { const agent = new WebhookClient({ request: req, response: res, version: 'v2' }); function demo(agent) { agent.add("Message from webhook server"); const dfMessengerPayload = { "richContent": [ [ { "type": "button", "text": "查看详情", "link": "https://example.com/details", "buttonText": "点击访问" }, { "type": "image", "rawUrl": "https://example.com/cover.jpg", "accessibilityText": "产品封面" } ] ] }; agent.add(new Payload(agent.UNSPECIFIED, dfMessengerPayload, { rawPayload: true })); } let intentMap = new Map(); intentMap.set("webhookDemo", demo); agent.handleRequest(intentMap); }); const port = process.env.PORT || 8000; app.listen(port, () => { console.log(`Server is running on port ${port}`); });
内容的提问来源于stack exchange,提问作者reverse_
相关产品推荐
相关产品推荐

