I found this example on the official site of DialogFlow using Node.js and it is working fine, but I dont know how do I integrate this into my web application.
Is it
The below snippet explains how we can communicate from a webapp to dialogflow NLU. To get access token we can make use of Google cloud SDK to obtain the token, but it has one hour validity so having this in a different service and obtain it before making call to dialogflow will give a workaround.
$(document).ready(function(){
$("button").click(function(){
$.ajax({
type: "POST",
url: "https://dialogflow.googleapis.com/v2/projects/YOUR-PROJECT-NAME/agent/sessions/SESSIONIDOFYOURCHOICE:detectIntent",
contentType: "application/json; charset=utf-8",
dataType: "json",
headers: {
"Authorization": "Bearer " + "YOUR ACCESS TOKEN GOES HERE",
},
data: JSON.stringify({ "queryInput":{
"text":{
"text":"YOUR QUERY TO NLU",
"languageCode":"en-US"
}
} }),
success: function(data) {
$("#div").html(data.queryResult.fulfillmentText);
},
error: function() {
console.log("Internal Server Error");
}
});
});
});
This way it works for me.
const dialogflow = require('dialogflow');
var projectId = ""; // your dialogflow project id when you click on settings of the DF agent
var sessionId = ""; // session ID
var config = {
// use credentials or keyFilename i'm using keyFile
// credentials: {
// private_key: privateKey,
// client_email: clientEmail,
// }
keyFilename: './google.json'
};
var sessionClient = new dialogflow.SessionsClient(config);
async sendTextMessageToDialogFlow(textMessage) {
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: textMessage,
languageCode: 'en'
}
}
}
try {
let [responses] = await sessionClient.detectIntent(request)
console.log(responses);
} catch (err) {
console.error('DialogFlow.sendTextMessageToDialogFlow ERROR:', err);
throw err
}
};
I've found a way to get a valid access-token entirely from frontend (browser) JavaScript.
1) Install the npm package jsrsasign from npm.
2) Add the files in this Gist to your project: https://gist.github.com/Venryx/bfa9b69583638dfbf611a9f292721a75
3) Enter values for all of the constants at the start of DialogFlowExample.ts
.
Your service account information can be found at: https://console.cloud.google.com/iam-admin/serviceaccounts
The service account's email is listed in the table, and its private-key (if you've created one) is found within the downloaded key json file. If you don't remember where you placed the key json file (or you haven't created one yet), you can use "Actions->Create key" to create a new one.
4) Call GetAccessToken
with your claim set and private key (see Gist for example). It will return a promise.
5) Once the access-token is retrieved, the promise is resolved with the retrieved access-token. (The function caches the access-token for 60 minutes. After that period, the token is expired, so calling the function again will have it retrieve a new one.)
The linked Gist contains an almost-complete usage example for converting a segment of audio to text using DialogFlow. The only part it doesn't show is how to obtain the "segment of audio".
For that, see part 1 of my answer here: https://stackoverflow.com/a/57859776/2441655
You can easily call Dialogflow's V2 API detectIntent
endpoint from jQuery.
The API docs show the URL and request formats:
POST https://dialogflow.googleapis.com/v2/{session=projects/*/agent/sessions/*}:detectIntent
{
"queryParams": {
object(QueryParameters)
},
"queryInput": {
object(QueryInput)
},
"inputAudio": string
}
Authentication works slightly differently; instead of using an access token, you'll create a service account and key using the Cloud dashboard. This documentation page explains how.
https://dialogflow.com/docs/reference/v2-auth-setup
After following through the page above and created service keys, you must have a json file like this:
{
"type": "",
"project_id": "",
"private_key_id": "",
"private_key": "",
"client_email": "",
"client_id": "",
"auth_uri": "",
"token_uri": "",
"auth_provider_x509_cert_url": "",
"client_x509_cert_url": ""
}
With this file, execute these two commands (you need to install gcloud CLI if have not yet):
gcloud auth activate-service-account --key-file=<service-account-key-file.json>
gcloud auth print-access-token
After those, copy the access token and supply it to your program as an environment variable (or hardcode if you don't care). Then, you just make an HTTP post request. I use axios in my React project, here is a sample code for detectIntent:
import axios from "axios";
const DIALOG_FLOW_TOKEN = process.env.REACT_APP_DIALOG_FLOW_TOKEN;
const DIALOG_FLOW_API_ROOT_URL = "https://dialogflow.googleapis.com/v2";
const YOUR_PROJECT_ID = <YOUR_PROJECT_ID>;
const SESSION_ID = <SESSION_ID>;
const URL = `${DIALOG_FLOW_API_ROOT_URL}/projects/${YOUR_PROJECT_ID}/agent/sessions/${SESSION_ID}:detectIntent`;
var config = {
headers: {
"Authorization": "Bearer " + DIALOG_FLOW_TOKEN,
"Content-Type": "application/json"
}
};
export function sendText(text) {
var bodyParameters = {
"queryInput": { "text": { "text": text, "languageCode": "en" } },
};
const request = axios.post(
URL,
bodyParameters,
config
);
return request;
}
As others have said here before, the access token has a duration of one hour, after that time it becomes useless. So it's necessary to make a call (http call in my case) to the API in order to request an access token, one time each hour, and use it as explained by Satheesh thereafter. Instructions on how to generate the signature to make the call and use it later are given in https://developers.google.com/identity/protocols/OAuth2ServiceAccount.
Once you obtain the json file from the service account with the private key and the email you have to use (not your email, but the one generated by the service account), you can use the jsrsasign library (in pure javascript), that you can find in https://github.com/kjur/jsrsasign, to generate the JSON Web Signature (JWS) and thus the JSON Web Token (JWT), that will be needed to make the http call to get the access token.
Then you use it as described above by Satheesh to make the call to Dialogflow V2 via jQuery.
The code I have used to achieve this is the next one:
function _genJWS() {
var header = '{"alg":"RS256","typ":"JWT"}';
var claimSet = jwtClaimSet();
var privateKey = jwtPrivateKey();
var sHead = newline_toDos(header);
var head = KJUR.jws.JWS.readSafeJSONString(sHead);
var sPayload = newline_toDos(claimSet);
var sPemPrvKey = privateKey;
var jws = new KJUR.jws.JWS();
var sResult = null;
try {
prv = KEYUTIL.getKey(sPemPrvKey);
sResult = KJUR.jws.JWS.sign(head.alg, sHead, sPayload, prv);
} catch (ex) {
alert("Error: " + ex);
}
return sResult;
}
function _requestAccessToken() {
var access_token = accessToken;
var assertion = _genJWS();
console.log('Assertion: ' + assertion);
jQuery.ajax({
type: "POST",
url: "https://www.googleapis.com/oauth2/v4/token",
contentType: "application/x-www-form-urlencoded",
dataType: "json",
data: "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=" + assertion,
success: function(response) {
console.log("success");
console.log(response);
access_token = response.access_token;
console.log(access_token);
},
error: function() {
console.log("Error");
}
});
return access_token;
}
Then use that access token to make the HTTP call to Dialogflow.
Hope it helps.