如何在Dialogflow Webhook中返回对会话的API响应

时间:2018-09-07 11:30:07

标签: javascript firebase google-cloud-functions dialogflow

我有一个Dialogflow Webhook实现集成,它对我已经设置的API进行GET请求。但是我似乎无法在对话中以文本形式获得API的响应。

API确实收到http GET请求,并返回状态码为200的响应。 如果我在浏览器中执行相同的请求,则结果如下:

{
    "avmid": "1011GZ 18",
    "straat": "Snoekjesgracht",
    "postcode": "1011GZ",
    "stad": "AMSTERDAM",
    "provincienaam": "Noord-Holland",
    "date": "2013-12-30",
    "koopsom": 199800,
    "koopsom2018q2": 333849
}

我已经尝试了几种方法,但似乎无法使它正常工作。 这是我的JavaScript:

'use strict';

const http = require('http');

const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

  function address_api_request (agent) {

    let postcode = agent.parameters.zipcode;
    let housenumber = agent.parameters.housenumber;

    let avmid = postcode.toString()+'+'+housenumber.toString();
    let url = 'http://XXX.XXX.XXX.XXX:XX/api/1011GZ+18';


    var http = require('http');
    http.get(url, function(response) {

            var body = '';
            response.on('data', function(d) {
                body += d;
            });
            response.on('end', function() {

                var parsed = JSON.parse(body);
                agent.add(parsed.toString());
            });
        });
    }


  function welcome (agent) {
    agent.add(`Welcome to my agent!`);
    agent.add(agent.request_.body.queryResult.fulfillmentText);
  }

  function fallback (agent) {
    agent.add(`I didn't understand`);
    agent.add(`I'm sorry, can you try again?`);
  }

  // Run the proper function handler based on the matched Dialogflow intent name
  let intentMap = new Map();
  intentMap.set('company.woningwaarde-get-address-api', address_api_request);
  intentMap.set('Default Welcome Intent', welcome);
  intentMap.set('Default Fallback Intent', fallback);
  agent.handleRequest(intentMap);
});

意图起作用,如果我用下面的代码替换address_api_request函数,它将返回“ test:

function address_api_request (agent) {
  agent.add('test');
  }

1 个答案:

答案 0 :(得分:0)

这里有两个问题。

第一个是,如果您使用的是Dialogflow的内置编辑器,则它是在幕后使用Firebase Cloud Functions。 Firebase Cloud Functions的默认级别不允许Google云端以外的网络访问。

您可以通过将项目升级到Firebase的Blaze Plan来解决此问题,该过程确实需要使用信用卡记录并按次计费,但是有免费层足以进行合理的测试,甚至正在生产中使用一些光。行动获得批准后,您就有资格获得可用于此目的的Google Cloud积分。

另一个问题是您有一个异步函数(http.get()),但是您没有使用Promise来处理该函数,而是让handleRequest()方法知道它需要等待返回结果前要解析的函数。如果您使用的是异步函数,则Dialogflow库要求您从函数中返回一个Promise。

您可以选择几种处理方式。首先,您可以将对http.get()的调用包装为creating a new Promise object的一部分,并在end处理程序中,按照指示发送消息,然后调用resolve参数您需要在Promise处理程序中接受。但是,更简单的方法是使用诸如request-promise-native之类的库,该库为您包装了很多内容,并使您可以将结果作为then()子句的一部分,然后在其中进行处理。

我还没有测试过,但是您的代码可能看起来像这样:

function address_api_request (agent) {

  let postcode = agent.parameters.zipcode;
  let housenumber = agent.parameters.housenumber;

  let avmid = postcode.toString()+'+'+housenumber.toString();
  let url = 'http://XXX.XXX.XXX.XXX:XX/api/1011GZ+18';

  const rp = require('request-promise-native');
  var options = {
    uri: url,
    json: true
  };
  return rp( options )
    .then( body => {
      // Since json was set true above, it parses it for you
      // You wouldn't really want to send back the whole body
      agent.add( body );
    })
    .catch( err => {
      console.log('Problem with request', err );
      agent.add( "Uh oh, something went wrong" );
    });
}