Contents

  1. Introduction
  2. Theory and tools
  3. Send a test message with Postman
  4. Send a message with code
  5. Connect a Workplace integration to our code
  6. Receive a message from Workplace
  7. Getting your bot online

Working with a webhook

In the last part of our bot-building tutorial, we took our test message from Postman and learned how to recreate it in an application using VS Code.

So far, we’ve been focused on a bot that can send a message to a user in Workplace.

But today, we’re going to work in the opposite direction: how to receive a message from a Workplace user.

Let’s start with a quick test. What happens when a user messages our bot in its current form?

Head over to Workplace and send a message to your bot.

Sending a message to the bot

Well, that was anticlimactic. But then, that’s what we should expect.

If you remember our bot theory from Part 2, we know that Workplace needs to be able to send a message from the user to our application. And then our application will decide what to do, gathering information from other third-party applications if it needs to.

In its current state, our application doesn’t know how to process the message from Workplace. And Workplace doesn’t know where our application lives – so it can’t forward the message to our bot.

So today, we’re going to fix part of that, and get our application available on the internet.

But first, we need to learn a bit about debugging.

 

1. Learning how to debug

Eventually, we’re going to place our application in a cloud host called AWS (through Heroku).

But for now, we’re going to keep it locally on our machine. Because once we put our app up on the cloud, we’ll lose a lot of debugging capability.

Debugging? What’s that?

Debugging is the art of removing bugs in your code. (De-bug-ging – get it?)

As we add to and grow our applications, they can often become huge and complex – with lots of moving parts. So when something goes wrong, it’s important to be able to figure out what the cause was and where the problem is.

In VS Code, we’re able to stop our code at any moment and see exactly what was happening at that point in time. But this won’t be easy once the application is on the cloud. So we’ll build the app locally and debug it first, and then upload it later.

Let’s run through a quick debugging exercise now in VS Code.

Open up your index.js file, and look for line 12. If you click just to the left of the line number, a little red circle should appear. This means you’ve added a breakpoint.

Debugging in VS Code

Breakpoint? What’s that?

A breakpoint tells VS Code to stop before running that line of code.

In this example (a breakpoint on line 12), VS Code will do all the preparation needed to send the message – but it’ll stop just before sending it. This means we can check that things are working properly (like whether Axios is loaded, whether our token is correct, and what the JSON looks like).

Debugging in VS Code

So with this breakpoint in place, VS Code should stop execution and highlight line 12 (before Axios sends the data to the graph API).

The debug panel on the left has loads of information – but for now, we only want to concentrate on the variables section.

We can see the values of the id and message variables that we passed in when calling the function. We can even change the value of those variables in the debug console, which means that VS Code will use the new versions of those variables for the rest of this session.

The action menu at the top of the screen allows you to run a line of code at a time. That means you can decide whether you want to dip your toes into Axios’ code – or just skip over that and concentrate on your own.

For now, tap F5 or the play icon to continue running the code to the end.

Play button

Great! We’ve learned the basics of how to debug using VS Code.

That’s going to be really useful later – but we still don’t have anything that can receive data from Workplace.

 

2. Receiving POSTs with the Express module

Remember our bot theory from Part 2 of this tutorial?

We talked about GET and POST requests. When someone sends a message to our bot, Workplace will make a POST to our application. And that means we need something that can receive a POST over HTTPS.

NodeJS has loads of ways to do this – but I’m going to show you the most popular one.

We’re going to use a module called Express. And we’re going to use NPM to download and install it.

So open up the terminal in VS Code and type the following command:

npm i express

Once we have Express installed, we can now load it in and configure it in our code.

First, we’ll need to comment out line 26 by placing “//” in front of it. This means we can keep the code for later reference, but it won’t be executed at the moment.

//sendMessage('100028418687930', 'hello, world! From NodeJS refactored')

Next, we’ll go back to the top of index.js, and use the following bit of code to do three things:

  • Load Express into memory
  • Call the express() function to instantiate it
  • And set a variable called ‘port’, which we’ll use in a moment.

Here’s the code you’ll need:

const express = require('express')
let app = express()
let port = 3000

Now, the next part is the most important:

We need to make sure Express knows where each request should go – which bit of our code should receive each request.

Imagine that we have an URL of https://www.coolrbots.com.

When someone visits https://www.coolrbots.com/sendMessage, we want our application to run the sendMessage() function.

But if someone visits https://www.coolrbots.com/showBots, we want our application to run the getBotsfromDatabase() function.

Here’s the code you’ll need to add:

app.get('/', (req, res) => {
    console.log('Workplace message received')
    res.send('Hello World!')
})

This code tells Express to run two commands if anyone performs a GET on the root of your domain (that’s the part that contains “/”).

The easiest way to do this would be to simply open our URL in a web browser.

First, it’ll put a message into our debug console (‘Workplace message received’) – and then it’ll send a response back to the browser (‘Hello World’).

We’re going to have lots of GET and POST routes defined in our application. This is just the beginning!

Finally, we need to tell Express to listen for HTTP traffic. We do this with the following line:

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

So, we’ve told Express to listen on port 3000. And then route any GET requests which are made to the root URL into our two commands above.

Let’s test it!

Start your application, and then load this URL in your browser http://127.0.0.1:3000/.

You should see the following in the browser and debug console:

'Hello World' in a browser

This address (127.0.0.1) is called the localhost.

Localhost? What’s that?

You’ve probably heard of IP addresses. These are addresses on the internet, and every machine has one – your laptop, your phone, and maybe even your refrigerator!

There are a few ‘special’ IP addresses, and 127.0.0.1 (the localhost) is one of them.

No matter which machine you’re on, this address always refers back to the same machine that made the request. So when you request it on your phone, it points to the phone. And when you use the same address on your laptop, it points to your laptop.

VS Code terminal

Here’s the complete code for everything we’ve done so far today. If you see an error when running your application, double check your code against what I have below:

const express = require('express')
let app = express()
let port = 3000
const axios = require('axios');

const workplaceAPI = axios.create({
    method: 'POST',
    baseURL: 'https://graph.facebook.com/me/messages',
    headers: {
        Authorization: 'Bearer <Your Integration Token>
    }
});

const sendMessage = (id, message) => {
    workplaceAPI({
        data: {
            recipient: {
                id: id
            },
            message: {
                text: message
            }
        }
    })
}

app.get('/', (req, res) => {
    console.log('Workplace message received')
    res.send('Hello World!')
})

app.listen(port, () => console.log(`Example app listening on port ${port}!`))
//sendMessage(<Your UUID>, 'hello, world! From NodeJS refactored')

3. Giving Workplace local access

At this point, our application is only available on our local machine. But we need Workplace to send us information – so we need to publish our code to somewhere that Workplace can get to.

Earlier, I said that we should hold off on pushing our code to AWS (the cloud) so that we can debug. So how can we keep our code local while still giving Workplace access?

We’re going to use a tool called Ngrok to achieve this. With Ngrok, we can create a tunnel from your machine to Ngrok’s servers in the cloud. These servers will then give you a public URL which Workplace will be able to send information to.

(You should have installed Ngrok in the shopping list section of Part 2 of this series. If you haven’t, go and grab it now!)

Since it’s a command line tool, we’ll be running Ngrok from the terminal.

Here’s a small pro-tip. Nrok will run forever if you don’t stop it, and so will block you from running any other commands through the terminal. Luckily VS Code can run multiple instances of the terminal for us.

Switch to the Terminal tab, and then click on the little plus symbol on the right.

You’ll notice that the drop-down changes from ‘1: bash’ to ‘2: bash’.

This shows you that you’re in a new bash window (Windows users will probably see ‘2: Powershell’). You can switch between sessions using that drop-down whenever you need to.

For now, stay in session 2 and type the following command:

ngrok http 3000

(In case you’ve forgotten: ‘3000’ is the port that we made Express listen to earlier.)

Ngrok

In the resulting output, Ngrok tells us that it has created a public URL. And that URL is being routed down to our machine.

So let’s try it. Grab the HTTPS version of your Ngrok URL (https://61be2582.ngrok.io in the above example) and paste it into the browser. You should see the same ‘Hello World’ response that we saw when we loaded the localhost address.

Now we have an address that Workplace can talk to. And the next thing we’ll need is an application that can understand what Workplace is telling us.

 

4. Getting ready for the webhook

Before we get into this next section, I want to dig into a little bit of theory.

Each time someone messages our bot, we want Workplace to send that information to our application. But there are lots of ways that people might choose to interact with our bot.

They might send a simple text message. But they might also send an image or a video. They might tag the bot in a post, or they might add it to an existing group chat.

On top of all that, we need to think about a few other things – like when our message was delivered, or when the user read it.

Workplace can tell us about each of these events (and lots more) via something called the webhook mechanism. Our integration (the wrapper around our bot) needs to subscribe to a webhook which knows how to process that type of event.

Once we’ve subscribed to the webhook, we can leave it alone and it’ll just ‘work’. But when we first subscribe, we’ll have to go through a few security hoops.

During subscription, Workplace will send a GET request to our webhook. This request includes two key pieces of information:

  • Verify token – We create this. We tell Workplace that it has to send us a special string when it messages us. This way we know that the message came from Workplace (and not from some hacker).
  • challenge – When Workplace messages us, it sends us a string that it has created. When our application replies, we have to send that same string back.

If both applications get the strings they expect back, they each know they’re talking to a trusted party.

So first, we need to handle the subscription event. The following code was adapted from one of Facebook’s example applications, ThanksBot.

Add the following line to the top of your index.js, just after you loaded Express:

const bodyParser = require('body-parser')

This is a special kind of module called a middleware. In this case, we’re going to use a module called body-parser.

Middleware? What’s that?

Most modules can exist on their own. But middleware adds functionality to another module.

When a request comes into an Express route, Express checks if it needs to apply a middleware to that request. It applies each middleware in the order they’re defined in the code, and then passes the request to your code.

Next, we’re going to tell Express to use body-parser.

Bodyparser will take the information that Workplace sends to us – and then parse it into an easy-to-use format. Basically, that means it’s going to make things a lot easier later on.

app.use(bodyParser.json());

And finally, we need to define that webhook listener. Let’s replace the existing route that we defined earlier:

app.get('/webhook', (req, res) => {
    if (req.query['hub.mode'] === 'subscribe' &&
    req.query['hub.verify_token'] === 'ThisIsARandomStringThatIJustMadeUpOnTheSpot') {
        console.log('Validated webhook');
        res.status(200).send(req.query['hub.challenge']);
    } else {
        console.error('Failed validation. Make sure the validation tokens match.');
        res.sendStatus(403);
    }
});

And here’s the current, complete code with everything we’ve done so far. Be sure to double-check yours against this for any errors!

const express = require('express')
const bodyParser = require('body-parser')
let app = express()
let port = 3000
const axios = require('axios'); 
app.use(bodyParser.json));

const workplaceAPI = axios.create({
    method: 'POST',
    baseURL: 'https://graph.facebook.com/me/messages',
    headers: {
        Authorization: 'Bearer <Your Integration Token>
    }
});

const sendMessage = (id, message) => {
    workplaceAPI({
        data: {
            recipient: {
                id: id
            },
            message: {
                text: message
            }
        }
    })
}

app.get('/webhook', (req, res) => {
    if (req.query['hub.mode'] === 'subscribe' &&
    req.query['hub.verify_token'] === 'ThisIsARandomStringThatIJustMadeUpOnTheSpot') {
        console.log('Validated webhook');
        res.status(200).send(req.query['hub.challenge']);
    } else {
        console.error('Failed validation. Make sure the validation tokens match.');
        res.sendStatus(403);
    }
});
 });

app.listen(port, () => console.log(`Example app listening on port ${port}!`))
//sendMessage(<Your UUID>, 'hello, world! From NodeJS refactored')

I know: there’s a lot going on in there.

So let me talk you though all of it:

Body-parser will take the information that Workplace has sent us and make it easily available to your code.

The Webhook GET route checks if this is a subscription request ( req.query[‘hub.mode’] === ‘subscribe’ ) and rejects it if it isn’t. (We don’t want random people making GET requests to our webhook!) It then checks the verify token ( req.query[‘hub.verify_token’] === ‘ThisIsARandomStringThatIJustMadeUpOnTheSpot’ ). If they match, it sends a 200 response back to Workplace – along with the hub.challenge value which we mentioned earlier.

And finally, the app.use() function tells Express to pass all requests through body-parser.

200 Response? What’s that?

Any HTTP request always expects some response.

Sometimes we send back information, and sometimes we just say ‘Got it – thank you’. At other times, we might reply with an error.

At a minimum, we should always send back a response code. If we don’t, Workplace will keep resending us information until it gets a successful response.

In general, you can tell the type of the response by its first digit:

  • A 2xx response means things went well
  • A 4xx response means there was a permissions-related issue
  • And a 5xx response is an error

Let’s give it a test and see what response we get.

Restart your application, and load the local webhook URL http://127.0.0.1:3000/webhook.

'Forbidden' error in the browser

Error in VS Code

Our route will return a 403 error if the verify token doesn’t match – or if it’s not a subscription request.

Loading the page in the browser sends a GET request but doesn’t send a verify token. So in this case, a forbidden error is completely fine.

Next, you should perform the same test with your Ngrok URL, and make sure you get the same error.

Great! We’re now ready to subscribe Workplace to our webhook.

 

5. Subscribing to the webhook

Head over to the admin panel in Workplace and go to the Integrations section.

Click into the ‘Coolr-Bot-Tutorial’ integration (we made this in Part 3 of this tutorial series).

Scroll down to the ‘Configure webhooks section’, where you’ll find all of the event types that Workplace can send to a webhook.

Right now, we just need to subscribe to the ‘message‘ event, so tick that box then add our Ngrok URL along with the verification token that you defined in your code.

(In the example above, I wrote “ThisIsARandomStringThatIJustMadeUpOnTheSpot”. But this could be anything – and you should make it as random as possible.)

Finally, you can scroll down to the bottom of the page and hit Save – and cross your fingers.

Setting webhook options in Workplace

With very little ceremony, Workplace should return you to the integrations page in the admin panel.

This is a good thing! It means that Workplace received a 200 response code from your application, and it’s now subscribed to your webhook.

If you did get an error, double-check your code against mine. Make sure you’re using the HTTPS Ngrok URL, and make sure that it generates a forbidden message if you open it in the browser. Double check that you’ve only subscribed to the ‘messages’ event – and that your verification token matches what’s in your code.

Good job! At this point in the tutorial, you should have:

  • Learned the basics of debugging
  • Used the Express module to receive POST requests from Workplace
  • Used ngrok to route Workplace to your application running on your computer
  • And set up and subscribed to a webhook.

In the next part of our tutorial series, we’re going to start to receive data from Workplace. We’ll create a route in Express which will receive the message, investigate what that message looks like – and then send a reply back to the user.

This is the last leg, guys – we’re nearly there. You’ve come so far, and you should know that you’re awesome.

Enjoyed this case study? Share!

Coolr thinking

Check out our latest news, blogs, cases studies and rants below.

more

Coolr story

We're doing things a little different at Coolr. We're part agency, part tech start-up, part consultancy - and we have big plans.

Learn more