How do you receive Whatsapp messages from Twilio using Node.JS?

Viewed 400

I am trying to build a Whatsapp chatbot using Node.JS and am running into a bit of trouble in receiving the Whatsapp message from Twilio. On checking the debugger, I get a Bad Gateway error, ie. Error 11200: HTTP Retrieval Failure. The message is getting sent, and ngrok shows the post request, however, dialogflow does not receive the request. On terminal, the error is showing UnhandledPromiseRejectionWarning: Error: 3 INVALID ARGUMENT: Input text not set. I'm not sure if it's because the message is not in JSON format. Please help!

This is the app.post function:

app.post('/api/whatsapp_query', async (req, res) =>{
        message = req.body;
        chatbot.textQuery(message.body, message.parameters).then(result => {
            twilio.sendMessage(message.from, message.to, result.fulfillmentText).then(result => {
                console.log(result);
            }).catch(error => {
                console.error("Error is: ", error);
            });
            return response.status(200).send("Success");
        })
    });

And this is the sendMessage function I've imported:

const config = require('./config/keys');

const twilioAccountID = config.twilioAccountID;
const twilioAuthToken = config.twilioAuthToken;
const myPhoneNumber = config.myPhoneNumber;

const client = require('twilio')(twilioAccountID,twilioAuthToken);

module.exports = {
    sendMessage: async function(to, from, body) {
        return new Promise((resolve, reject) => {
            client.messages.create({
                to,
                from,
                body
            }).then(message => {
                resolve(message.sid);
            }).catch(error => {
                reject(error);
            });
        });
    }
}

And this is the textQuery function I've imported:

textQuery: async function(text, parameters = {}) {
        let self = module.exports;
        const request = {
            session: sessionPath,
            queryInput: {
                text: {
                    text: text,
                    languageCode: config.dialogFlowSessionLanguageCode
                },
            },
            queryParams: {
                payload: {
                    date: parameters
                }
            }
        };
        let responses = await sessionClient.detectIntent(request);
        responses = await self.handleAction(responses)
        return responses[0].queryResult;
    },


1 Answers

Twilio developer evangelist here.

The issue is that you are not passing the correct message body from the incoming WhatsApp message to your textQuery function.

First, you should make sure that you are treating the incoming webhook from Twilio as application/x-www-form-urlencoded. If you are using body-parser, ensure you have urlencoded parsing turned on.

app.use(bodyParser.urlencoded());

Secondly, the parameters that Twilio sends start with a capital letter. So your code currently gets message = req.body and then uses message.body. But it should be message.Body.

Those two points should sort you out.

One final thing though. The Twilio Node.js library will return a Promise if you do not pass a callback function. So you don't need to create a Promise here:

module.exports = {
    sendMessage: async function(to, from, body) {
        return new Promise((resolve, reject) => {
            client.messages.create({
                to,
                from,
                body
            }).then(message => {
                resolve(message.sid);
            }).catch(error => {
                reject(error);
            });
        });
    }
}

You can just return the result of the call to client.messages.create

module.exports = {
    sendMessage: async function(to, from, body) {
        return client.messages.create({ to, from, body });
    }
}

Hope this helps.

Related