In this tutorial, we’ll be looking at how to build a simple WhatsApp Chat Bot using Node.js & Vonage. The Bot will be responsible for converting any given number of units in a base currency to the equivalent in the preferred currency.
The bot will be built using Vonage's Messages API along with Express, the Node Framework.
Here's an example of me chatting with the Bot:
Prerequisites
Ngrok which allows you to expose your local webserver to the internet. To learn more about how to set up your local environment with Ngrok, you can check out our documentation.
Either a WhatsApp business account or set up the Messages API sandbox as we’ll be doing in this tutorial to whitelist numbers.
Vonage API Account
To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.
Set Up Your Application
Start by cloning the repository to your local machine: https://github.com/Dotunj/vonage-whatsapp-bot.
Next cd
into the project's directory and run the following command to install the project's dependencies:
Building the Bot
Whenever our Bot receives a message on WhatsApp, Vonage will make an HTTP Post Request to an endpoint. The request will contain a message payload.
app.post("/webhooks/inbound-message", (req, res) => {
eventEmitter.emit("inbound-message", req.body);
return res.send("Received Webhook successfully");
});
Above, we defined a route at /webhooks/inbound-message
which emits the inbound-message
event using the Node.js Event module and then returns a 200 response to Vonage.
The Node.js Event module includes the EventEmitter
class which is used to raise and handle events. You can learn more about handling and dispatching events in Node.js here.
eventEmitter.on("inbound-message", (body) => {
performCurrencyConversion(body).catch((err) => console.log(err));
});
Everytime the inbound-message
event is emitted, the eventEmitter.on()
method is triggered as well. This function registers a listener function, which simply invokes the performCurrencyConversion()
method passing in the message payload.
function standardResponse() {
let response = "Welcome to the WhatsApp Bot For Currency Conversion \n";
response += "Please use the following format to chat with the Bot \n";
response += "Convert 5 USD to CAD \n";
response +=
"Where 5 is the number of units to convert, USD is the base currency and CAD is the currency you would like to convert to.";
return response;
}
The standardResponse
function is a generic response informing the user of how to communicate with the bot.
The performCurrencyConversion()
method is responsible for deciphering the content of the message that was sent to the Bot and sending a response back to the user.
The content of the message that was received is converted into an array using split()
. Based on our agreed messaging format, the number of items contained within the array should be 5.
If after the message content has been split into an array, and the items contained within that array is less than 5, a standard response is sent back to the user informing them of how to make use of the Bot.
If the length check of the message content is successful, we can now safely assume the items contained in the 1st, 2nd, and 4th index of the array will be the units, base currency, and the currency you would like to convert to.
Converting With Coinbase
Now that we have the base currency, and the currency you're converting to, we can do a check to ensure those currency codes are valid and are supported by Coinbase.
The Coinbase API provides endpoints for dealing with currencies as well as exchange rates. You can read more about the Coinbase API here.
async function getCurrencyCode(baseCurrency, toCurrency) {
try {
const currency = await axios.get(`${coinbaseUrl}/currencies`);
const currencyCode = currency.data.data;
const isSupportedCurrencyCodes = currencyCode.filter(
(c) => c.id === baseCurrency || c.id === toCurrency
);
if (isSupportedCurrencyCodes.length < 2) return;
return isSupportedCurrencyCodes;
} catch (error) {
console.error(error);
}
}
This is where the getCurrencyCode()
function comes in.
It accepts the baseCurrency
along with the toCurrency
and then makes an API call to https://api.coinbase.com/v2/currencies
to get a list of all the supported currencies. A check is then carried out to ensure both the baseCurrency
and the toCurrency
codes can be found within the list of supported currencies.
If none or either of them can be found, a response is sent back to the user informing them to Provide a valid currency code.
Next, after validating the currency codes with the getCurrencyCode()
function, the getBaseExchangeRate()
method is called.
async function getBaseExchangeRate(baseCurrency, toCurrency) {
try {
const response = await axios.get(
`${coinbaseUrl}/exchange-rates?currency=${baseCurrency}`
);
const rates = response.data.data.rates;
const baseRate = rates[toCurrency];
return baseRate;
} catch (error) {
console.error(error);
}
}
This method accepts the baseCurrency
along with the toCurrency
as well.
An API call is then made to the https://api.coinbase.com/v2/exchange-rates
endpoint passing the baseCurrency
code as the value of the currency
query parameter.
This endpoint returns the rates for one unit of the base currency. Next, all we have to do is return the equivalent rate for the toCurrency
.
Here’s an example of the response received from calling the endpoint using USD as the baseCurrency
:
"data": {
"currency": "USD",
"rates": {
"AED": "3.673015",
"AFN": "77.06341",
"ALGO": "1.5885623510722797",
"ALL": "104.873298",
"AMD": "481.616228",
"ANG": "1.794578",
"AOA": "589.0",
"ARS": "73.1365",
...
After obtaining the base rate, all we have to do is multiply the units by the base rate to obtain the equivalent amount in the currency the user is trying to convert to and then round the value to two decimal places. A response is then sent back to the user informing them of the exchange rate.
The sendWhatsAppMessage()
function sends a response back to the user via WhatsApp.
An HTTP POST request is made to the https://messages-sandbox.nexmo.com/v0.1/messages
endpoint specifying the from
, to
, and message
field.
The from
field is the WhatsApp API Sandbox number. I’ll be showing you how to obtain that shortly and we’ll be adding it as part of our environment variables. The to
field is the number that sent the initial message and it’s obtained from the message payload.
To authenticate with the API, we specify our Vonage API Key as well as Secret Key. Likewise, we’ll be obtaining these values shortly and adding them as part of our environment variables.
Setting Up Ngrok
Since our application is currently local, there’s no way for Vonage to be able to send POST requests to the endpoint we just created whenever our Bot receives a message. We can use Ngrok to set up a temporary public URL so that our app is accessible over the web.
To start the application, run the following command from the terminal:
With the application running, run the following command on a second terminal window to start ngrok:
In this command, 3000
refers to the port your Express application is currently listening on.
You should now be presented with a screen similar to the one below:
Take note of the second Forwarding URL, as this is what will be used to configure our Vonage Webhook.
Setting Up the WhatsApp Sandbox
We’ll be making use of the Vonage WhatsApp Sandbox for this demo since your business needs to be approved by WhatsApp before you’re able to use their API in production.
Head over to the Messages API Sandbox to whitelist your WhatsApp number so we can test the bot.
To add your WhatsApp Number so that you can start receiving and sending messages, you can scan the QR code via WhatsApp or click the link presented to you and hit send on the pre-filled message. Take note of the WhatsApp Sandbox number as we’ll be adding it to our environment variable shortly.
Next, on the same screen configure the URL for the Inbound Webhook by pasting the Ngrok URL we noted earlier. Don’t forget to append /webhooks/inbound-message
at the end of the URL.
Head over to your Dashboard Settings page, and take note of your API Key
and API Secret
.
Adding Environment Variables
Since we've noted all the environment variables our Bot will be needing along with their values, we can now add them to our project. From the root of your project’s directory, create a .env
file and add the following values:
VONAGE_API_KEY=xxxx
VONAGE_API_SECRET=xxxx
VONAGE_FROM_NUMBER=xxxx
Don’t forget to replace xxxx with the actual values we noted earlier.
Testing
You can try testing the functionality of the bot by sending messages to it from your smartphone using WhatsApp.
Conclusion
In this tutorial, we’ve seen how we can build a simple WhatsApp Chatbot for carrying out currency conversions using the exchange rates provided by Coinbase. This tutorial can serve as a starting guide for learning how to receive and send messages via WhatsApp using Vonage’s messages API.