Webhooks, pizza, and order notifications via Twilio

10 min read
by Robbie Averill
April 9, 2020

Last week we launched webhooks (see announcement here), giving developers and merchants the ability to automate and streamline their eCommerce actions and processes. The functionality and automation that comes with webhooks is endless. It’s an exciting opportunity to think creatively about your integration and how you can make Chec and Commerce.js work for you even more.

In this article I wanted to take the time to first explain what webhooks are using a fun metaphor, and then walk through a simple webhooks example using Twilio notifications.

One pizza please

Imagine you’re the manager of a local pizza joint called Sizzling Pizzas. You and your team work diligently throughout the evening slinging dough for your customers. You all have your jobs in the production line and feel like it’s all pretty streamlined:

Kim stretches the dough and passes it to Sam → Sam gets saucy with it and hands off to Robin → Robin applies a decent measure of mozzarella and passes it to Leslie → Leslie sprinkles the appropriate toppings and finally throws it into the oven. After a few minutes, Nicky extracts the beautiful bubbling pizza from the oven, boxes it up and hands it over to the customer.

Like a well oiled machine, Sizzling Pizza has a high throughput, makes a quality product and delivers it on time, every time.

There is a problem though. Sizzling Pizza operates their production synchronously. Each staff member waits for the previous staff member to complete their part of the task before starting their own (except for Kim, who waits for the orders to come in). You might think this isn’t a problem, and it’s not if you don’t mind wasting your employees time.

Pizza time

Make that asynchronous please

What if Sizzling Pizza implemented some asynchronous touch points in their production line— that is to say, things get done when they can be done, rather than when they must be done.

This could work for some of the parts: if Kim predicts the demand of the store and attempts to keep the dough supply at around 120% of expected demand. Sam is now able to be the first touch point in the process, removing the time to stretch the base from the process. Pre-saucing and even pre-cheesing a few pizzas makes sense really - 95% of the pizzas sold at Sizzling Pizzas have a tomato and mozzarella base.

Now let’s look at Leslie. While there’s undoubtedly a ready supply of pre-stretched, sauced, and cheesed up bases, Leslie still needs to know when to actually assemble a pizza. There are a few options for how this could be achieved: Leslie could constantly ask whether there are any new orders, or just wait to be told when new orders arrive. Most of the time, the second option here is the winner. Neither Leslie nor whoever is being asked needs to constantly reply “yes” or “no” - when a new docket arrives, Leslie gets the mushrooms out.

Finally we get to Nicky. All stages of making a pizza are important, but arguably the most critical is removing the pizza from the oven at the appropriate time. Cooked, but not burnt. Like Leslie, Nicky doesn’t want to stand there watching grass grow - Sizzling Pizzas use timers to notify Nicky when a pizza is ready to be removed from the oven.

Hold my Pizza

Why am I unnecessarily making you crave pizza right now? Well, imagine Sizzling Pizza is an online web store, and each of the staff members are parts of the eCommerce system that drives its fulfilment process. At this point, the asynchronous parts are great examples of where “webhooks” can help. Instead of every step of the process relying on the output from the previous step, Sizzling Pizza can:

  • Reduce their time to first bite
  • Reduce the load on their employees
  • Scale individual parts of their process individually (maybe we need another Leslie at some point)
  • Allow further customisations, e.g. adding vegan routing to the cheesing service if requested

Smart Pizza

What are Webhooks

Webhooks are essentially a way for third-party systems to react to or modify data in a first-party system using callbacks, which are triggered when certain events happen in the first-party system. They generally communicate over the HTTP protocol via the internet.

With Commerce.js for example, your frontend website has the necessary touch points with the Chec Platform needed to list products, add to cart, and capture orders. You don’t build order management interfaces into your frontend website, because you’d need to publish your secret API keys to do that. But let’s say you do want to send yourself a text message when a new order is placed— the Chec Platform doesn’t offer this option for you, but you can register a webhook and implement it yourself with Twilio in about 10 minutes.

Intrigued? Let’s have a look

The main thing you need is a callback URL on the public internet. It will accept POST HTTP requests from the Chec Platform, verify the request signature and lifetime, then ask Twilio to message you with something encouraging.

For this example we’ll use a simple Node.js script. You’re also going to need the Twilio SDK for Node.js:

mkdir twilio-handler && cd twilio-handler
yarn add twilio
touch index.js 

Head over to Twilio and sign up for an account. Once you’re logged in, grab your “account SID” and “auth token”, open up your code editor and put them into in your index.js file. You’ll need to register a phone with Twilio when you sign up, and get a number for Twilio to send from - this can be done in the “Phone numbers > Active numbers” section. We’re also going to add signingKey with an empty value, which we’ll fill out when we register the webhook later on.

const http = require('http');
const crypto = require('crypto');
const twilio = require('twilio');

// Your Account SID from www.twilio.com/console
const accountSid = 'AC1234f0dd3r420024106c0576ee28abc';
// Your Auth Token from www.twilio.com/console
const authToken = '1a2b3c4d5e6f7g8habc123zyx987';
// Your Chec webhook signing key, from the Chec Dashboard webhooks view
const signingKey = 'todo';
// The phone numbers to send from and to
const phoneNumbers = {
  from: '+123456789', // A Twilio phone number you purchased at twilio.com/console
  to: '+1987654321',
};

const client = new twilio(accountSid, authToken);

const requestListener = (request, response) => {
  // Handle request body chunking
  const chunks = [];
  request.on('data', chunk => chunks.push(chunk));
  request.on('end', () => {
    // Get the request body/payload
    const data = JSON.parse(Buffer.concat(chunks));

    // Extract the signature
    const { signature } = data;
    delete data.signature;

    // Verify the signature
    const expectedSignature = crypto.createHmac('sha256', signingKey)
      .update(JSON.stringify(data))
      .digest('hex');
    if (expectedSignature !== signature) {
      console.error('Signature mismatch, skipping.');
    }

    // Verify the age of the request, to ensure it wasn't more than 5 minutes old
    if (new Date(data.created * 1000) < new Date() - 5 * 60 * 1000) {
      console.error('Webhook was sent too long ago, could be fake, ignoring.');
    }

    // All good, send to Twilio
    const orderId = data.payload.id || 'Test request';
    const orderValue = data.payload.order
      ? data.payload.order.total_with_tax.formatted_with_symbol
      : '$0.00';
    const messageBody = `Keep up the good work, order fu is strong! ${orderId} for ${orderValue}.`;

    client.messages.create({
      body: messageBody,
      to: phoneNumbers.to,
      from: phoneNumbers.from,
    })
      .then((message) => console.log(`Sent message: ${message.sid}`))
      .catch((error) => console.error(error));

    response.writeHead(200);
    response.end();

    console.log(`${data.response_code} for ${data.event}`);
  });
};

const server = http.createServer(requestListener);
server.listen(8080);

console.log('Listening for incoming webhooks...');

This callback performs the following tasks;

  • Extract the “signature” from the payload. The signature is a hash of the payload’s contents, which was generated using your Chec webhook “signing key”.
  • Verify the signature. Since we know our signing key, we can calculate what the signature should be, then compare it against what we were provided. It’s important to verify the signature of incoming webhooks so you can verify that they actually came from Chec, and not a man-in-the-middle attack.
  • Verify the age of the request. Another good thing to check is that the request was recently created. Chec will send you webhooks in near real-time, so requests are unlikely to be older than say 10-20 seconds. You can add some buffer in to account for network latency and Chec’s webhook queue processing time. This also helps to prevent replay attacks, where someone has intercepted your incoming webhook payload and decides to keep replaying it at your callback API until you start pulling your hair out.
  • Send an SMS using Twilio. This part’s pretty straight forward - we load up the Twilio SDK, tell it where to send the message, what the message should be, and which number it should come from (ensure both numbers you use are registered in the Twilio console).

Cool, so let’s give it a spin huh? Next we need to actually run this web server, and expose it to the world. You can easily spin up a local server by running node index.js in your terminal. You’ll also need to expose it to the world though, so we’d recommend using ngrok for this - a useful web proxy for exposing local servers to the world. Head over there, sign up for a free account and install ngrok.

cd twilio-handler
node index.js
 # Listening for incoming webhooks...

# Open a new console tab/window:
cd twilio-handler
ngrok http 8080
# Forwarding https://f3cb1bb6.ngrok.io -> http://localhost:8080

Now we’ve got a functioning callback handler, we can tell Chec about it! Head to the Chec Dashboard and go to Setup → Webhooks. Click “Add webhook”. Select orders.create from the events list, enter your ngrok URL, and save the webhook.

Adding a webhook

Now you can view the webhook, and you’ll see the signing key on the details panel here as well. Copy this key and put it into the signingKey variable in your project. You’ll need to restart your node index.js command so it picks up the new variable value.

At this point you can make a test request from the Chec Dashboard, and you should get a text message sent to your phone!

Test the full process by going and placing a test order on your account. You can disable the webhook if you start getting irritated by the frequency of messages (probably a good problem to have).

You’ll also see a history of the most recent delivery attempts to your webhook callback URL:

Webhook delivery history view

Back to pizza 🍕

We started this journey by talking about how a pizza shop might operate, then gave an example which was largely irrelevant to Italian food. If you want to, you could order yourself a pizza using the Domino’s Pizza API (see Node.js SDK). Sizzling Pizzas could build their own API which prints new order dockets out in their kitchen, piping their online web-store sales straight to Leslie. They could generate one-time-use discount codes using the Chec Discounts API and send them to new customers for their next order using Zapier - the possibilities are endless.

Webhooks give you the power to augment parts of your eCommerce business outside of the capabilities of the Chec Platform. You can set all of this up using our API as well, so check out the Chec webhooks API documentation and get started!

Have you recently built an integration with Chec webhooks? Send us a message and let us know what you’ve created!

You might also like