在Dialogflow V2中用Express获请求体参数及Google Action v1转v2迁移
嘿,针对你问的这两个Dialogflow + Express相关的问题,我给你整理了具体的解决方案,都是实战里常用的做法:
Dialogflow V2的Webhook请求以JSON格式发送到你的Express端点,核心是先确保请求体被正确解析,再根据参数的存储位置提取:
第一步:配置请求体解析
如果你用的是Express 4.16及以上版本,直接用内置的express.json()即可替代body-parser,配置方式如下:const express = require('express'); const app = express(); // 解析JSON请求体,strict: false兼容非严格格式的JSON请求 app.use(express.json({ strict: false }));提取Intent参数
用户触发Intent时携带的参数,会存在req.body.queryResult.parameters中,示例代码:app.post('/webhook', (req, res) => { // 获取Dialogflow返回的查询结果 const queryResult = req.body.queryResult; // 获取所有Intent参数 const allParams = queryResult.parameters; // 提取单个参数(比如用户说"预订明天的酒店",date就是参数之一) const bookingDate = allParams.date; const serviceType = allParams.service_type; console.log(`获取到的预订信息:日期${bookingDate},类型${serviceType}`); // 返回Dialogflow要求的响应格式 res.json({ fulfillmentText: `好的,我将帮你预订${bookingDate}的${serviceType}` }); });提取上下文参数
上下文里的参数需要从req.body.queryResult.outputContexts中查找,示例:app.post('/webhook', (req, res) => { const outputContexts = req.body.queryResult.outputContexts; // 筛选出名为"user_info"的上下文(需要替换成你实际的上下文名称) const userContext = outputContexts.find(ctx => ctx.name.includes('user_info')); if (userContext) { const userName = userContext.parameters.name; console.log(`上下文里的用户名:${userName}`); } });提取平台信息(如Google Assistant)
平台标识存于req.body.originalDetectIntentRequest.source,比如Google Assistant的标识是google:const platform = req.body.originalDetectIntentRequest?.source; if (platform === 'google') { // 针对Google Assistant的专属逻辑处理 }
你之前v1的代码通过URL路径参数(/:platform/:type/:publisher)区分不同的Fulfillment逻辑,迁移到v2后可以继续保留这个路由结构,只需结合V2的请求体结构调整处理逻辑:
方案1:保留原有URL路由结构
继续用路径参数区分,同时提取Dialogflow V2的请求体参数,示例:
const express = require('express'); const app = express(); app.use(express.json({ strict: false })); // 保留原来的路由路径 app.post('/:platform/:type/:publisher', function(req, res) { // 获取URL路径参数 const { platform, type, publisher } = req.params; console.log(`SENDING TO ${type.toUpperCase()} => ${platform.toUpperCase()} => ${publisher.toUpperCase()} FULFILLMENT`); // 同时提取Dialogflow V2的请求体参数 const queryResult = req.body.queryResult; const intentParams = queryResult.parameters; // 从请求体里获取真实的平台信息(比URL参数更可靠) const actualPlatform = req.body.originalDetectIntentRequest?.source; // 将两类参数传给Fulfillment处理函数 fulfillment.handleRequest({ platform, type, publisher, intentParams, actualPlatform }, res); });
方案2:依赖请求体替代URL参数(更推荐)
Dialogflow V2的请求体已经包含了平台、Intent等关键信息,无需再通过URL参数传递,这样更符合V2的设计逻辑:
app.post('/webhook', function(req, res) { // 从请求体获取平台标识 const platform = req.body.originalDetectIntentRequest?.source || 'dialogflow'; // 通过Intent名称区分业务类型(假设你用"BOOKING_Hotel"这类命名规则) const intentName = req.body.queryResult.intent.displayName; const type = intentName.split('_')[0]; console.log(`SENDING TO ${type.toUpperCase()} => ${platform.toUpperCase()} FULFILLMENT`); // 后续业务逻辑处理 });
注意:V2响应格式变更
迁移时要注意,Dialogflow V2的响应格式和V1不同,V1的speech字段要替换成fulfillmentText,如果是Google Assistant还可以添加富响应:
// V1响应写法 // res.json({ speech: 'Hello World' }); // V2响应写法 res.json({ fulfillmentText: 'Hello World', // 针对Google Assistant的富响应示例 fulfillmentMessages: [ { platform: 'ACTIONS_ON_GOOGLE', simpleResponses: { simpleResponses: [ { textToSpeech: 'Hello World on Google Assistant' } ] } } ] });
内容的提问来源于stack exchange,提问作者nealrs

