Set up the WhatsApp Echo Bot

The WhatsApp Echo Bot is a sample webhook server application that echoes back to you whatever you send it. It can serve as a basic reference for how to set up webhooks and reply to incoming messages.

To test out the echo bot, we assume you have a Meta developer app with the WhatsApp product added already. Follow the getting started workflow to onboard as a developer and send your first test message.

After you send your test message, configure webhooks with the WhatsApp Echo Bot:

Configure the WhatsApp Echo Bot

Using Glitch

  1. Click Remix to edit. A new copy of the project will be created for you.

  1. Save it into the .env file in the Glitch app under WHATSAPP_TOKEN.

  2. Now, set the other .env variable called VERIFY_TOKEN. This can be any string you choose. In our case, we picked "blue_panda".

  3. Now, when you send a message to the API number on WhatsApp, it should send back your message in the following format "Ack: {your message}".

Before you start, make sure to register and sign into an AWS development account.

In AWS:

  1. Open the AWS Lambda console. AWS operates in several regional data centers and this example is set up in the US East (N. Virginia) us-east-1 region. So the actual link is https://us-east-1.console.aws.amazon.com/lambda/home.

  2. Click Create Function > Author from scratch and create your function. For this example, we have added and/or selected the following options:

    • Function name: cloudEcho

    • Runtime: Node.js 16.x, since we're implementing Javascript-based Lambda function

    • Execution role: Create a new role with basic Lambda permissions

    • Advanced Settings: Enable function URL has been checked and Auth type was set to None.

  3. Click Create Function.

  4. Once the function is created, you are redirected to the function page. There, you can see the following information:

    • The function's URL ending in .lambda-url.AWS_REGION.on.aws/. Save that for later use.

    • The Code source tab for that function.

  5. Inside your function's Code Source, you need to add code that does the following:

    • Only accepts GET and POST requests

    • Verifies using the GETrequest described here.

    • Replies to the message based on the message payload structure described here.

    The code sample to be copied and pasted is:

    const https = require("https");
    
    exports.handler = async (event)  => {
      const VERIFY_TOKEN = "Set_your_verify_token_value_here";
      const WHATSAPP_TOKEN = "Paste_whatsapp_access_token_here";
    
      let response;
      if (event?.requestContext?.http?.method === "GET") {
        // https://developers.facebook.com/docs/graph-api/webhooks/getting-started#verification-requests
        // to learn more about GET request for webhook verification
        let queryParams = event?.queryStringParameters;
        if (queryParams != null) {
          const mode = queryParams["hub.mode"];
          if (mode == "subscribe") {
            const verifyToken = queryParams["hub.verify_token"];
            if (verifyToken == VERIFY_TOKEN) {
              let challenge = queryParams["hub.challenge"];
              response = {
                  "statusCode": 200,
                  "body": parseInt(challenge),
                  "isBase64Encoded": false
              };
            } else {
              const responseBody = "Error, wrong validation token";
              response = {
                  "statusCode": 403,
                  "body": JSON.stringify(responseBody),
                  "isBase64Encoded": false
              };
            }
          } else {
              const responseBody = "Error, wrong mode";
              response = {
                  "statusCode": 403,
                  "body": JSON.stringify(responseBody),
                  "isBase64Encoded": false
            };
          }
        }
        else {
          const responseBody = "Error, no query parameters";
          response = {
              "statusCode": 403,
              "body": JSON.stringify(responseBody),
              "isBase64Encoded": false
          };
        }
      } else if (event?.requestContext?.http?.method === "POST") {
        // process POST request (WhatsApp chat messages)
        // https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/payload-examples#text-messages
        // to learn about WhatsApp text message payload structure
        let body = JSON.parse(event.body)
        let entries = body.entry;
        for (let entry of entries) {
          for (let change of entry.changes) {
            let value = change.value;
            if(value != null) {
              let phone_number_id = value.metadata.phone_number_id;
              if (value.messages != null) {
                for (let message of value.messages) {
                  if (message.type === 'text') {
                    let from = message.from;
                    let message_body = message.text.body;
                    let reply_message = "Ack from AWS lambda: " + message_body;
                    sendReply(phone_number_id, WHATSAPP_TOKEN, from, reply_message);
                    const responseBody = "Done";
                    response = {
                        "statusCode": 200,
                        "body": JSON.stringify(responseBody),
                        "isBase64Encoded": false
                    };
                  }
                }
              }
            }
          }
        }
      } else {
        const responseBody = "Unsupported method";
        response = {
            "statusCode": 403,
            "body": JSON.stringify(responseBody),
            "isBase64Encoded": false
        };
      }
      
      return response;
    }
    
    const sendReply = (phone_number_id, whatsapp_token, to, reply_message) => {
      let json = {
        messaging_product: "whatsapp",
        to: to,
        text: { body: reply_message },
      };
      let data = JSON.stringify(json);
      let path = "/v12.0/"+phone_number_id+"/messages?access_token="+whatsapp_token;
      let options = {
        host: "graph.facebook.com",
        path: path,
        method: "POST",
        headers: { "Content-Type": "application/json" }
      };
      let callback = (response) => {
        let str = "";
        response.on("data", (chunk) => {
          str += chunk;
        });
        response.on("end", () => {
        });
      };
      let req = https.request(options, callback);
      req.on("error", (e) => {});
      req.write(data);
      req.end();
    }

    Copy Code

  6. Once you paste the code, you will see the Changes not deployed banner pop up. Do not deploy your function yet! We need to set verify token and access token before that.

In Meta for Developers:

  1. Open Meta for Developers > My Apps and select the app you have created while following the getting started workflow. Click WhatsApp > Getting started.

In AWS:

  1. Click Deploy.

In Meta for Developers:

  1. Open Meta for Developers > My Apps and select the app you have created while following the getting started workflow. Click WhatsApp > Configuration > Configure a webhook.

  2. Click Verify and Save.

  3. You are done setting up the echo bot! Now, when you send a message to the API number on WhatsApp, it should send back your message in the following format "Ack from AWS lambda: {your message}".

Last updated