Azure Function to Read Incoming Message in Twilio

Introduction

In this tutorial, we will learn how to read incoming messages in Twilio and respond to webhooks using Azure Functions.

We will learn webhooks, how to set up an Azure Function, and then use the Azure Function app to respond to a Twilio SMS webhook and create a record in Dynamic 365 in case an entity receives a new message.

Prerequisites

  • A Twilio account.
  • An Azure account with an active subscription.
  • Dynamic365 subscription.

What is a webhook?

Webhook is an HTTP request triggered by an event in a source system and sent to a destination system. To enable this, you provide the source system with a URL where it can send the HTTP request.

A typical webhook setup involves the following.

  • A destination system that needs to be notified about a specific event.
  • A source system that sends a notification to the destination system when the event occurs. This system uses the provided webhook URL to make the HTTP request.

In your article, we will focus on responding to webhooks triggered by incoming SMS.

For Twilio SMS, two types of webhooks can be triggered.

  • Incoming Message: This webhook is triggered when your Twilio Phone Number receives a message. Twilio will send the details of this message to the webhook URL that you specify.
  • Status Callback: This webhook is triggered when the status changes of a message sent via Twilio. This webhook sends a message with the status of the message along with other details about the message.

Building the Azure Function

Open Visual Studio and create Azure function.

Create Azure function

Select the Azure function and click on Next.

Select Azure function

Configure Project

Additional Information

Once the function creates rename Function1.cs to TwilioReceiveMessage.cs.

.NET APIs, but the Twilio SDK for .NET has dedicated APIs to generate TwiML. Add the Twilio NuGet package using the .NET CLI.

Navigate to Tools in Visual Studio à NuGet Package Manager à Manage Nuget Packages for a solution and install below two packages below.

  • Package Twilio
  • Twilio.AspNet.Core
  • Microsoft.PowerPlatform.Dataverse.Client ( To connect CRM service)

CRM service

Solution Explorer

Now, update the TwilioReceiveMessage class with the following code.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Twilio.AspNet.Core;
using Twilio.TwiML;
using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk;
using System.Security.Cryptography;

namespace TwilioMessage
{
    public class TwilioReceiveMessage
    {
        private readonly ILogger<TwilioReceiveMessage> _logger;

        public TwilioReceiveMessage(ILogger<TwilioReceiveMessage> logger)
        {
            _logger = logger;
        }

        private static ServiceClient service { get; set; }

        public static ServiceClient Service
        {
            get
            {
                if (service == null)
                {
                    service = new ServiceClient(
                        new Uri(Environment.GetEnvironmentVariable("CRMIntegrationTargetEnvironment")),
                        Environment.GetEnvironmentVariable("CRMIntegrationClientId"),
                        Environment.GetEnvironmentVariable("CRMIntegrationClientSecret"),
                        true
                    );
                }

                return service;
            }
            set => service = value;
        }

        [Function("TwilioReceiveMessage")]
        public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
                                                     ILogger logger)
        {
            logger.LogInformation("C# HTTP trigger function processed a request.");

            var form = await req.ReadFormAsync();
            var body = form["Body"];
            logger.LogInformation("Message: " + body);

            var fromNumber = form["From"].ToString();
            logger.LogInformation("From Number: " + fromNumber);

            if (Service.IsReady)
            {
                CreateCase(fromNumber, body);
            }

            var response = new MessagingResponse();
            response.Message(
                $"You sent: {body}",
                action: new Uri("/api/MessageStatus", UriKind.Relative),
                method: Twilio.Http.HttpMethod.Post
            );

            return new TwiMLResult(response);
            //return new OkObjectResult("Welcome to Azure Functions!");
        }

        private static void CreateCase(string fromNumber, string body)
        {
            Entity caseEntity = new Entity("cases");
            caseEntity.Attributes.Add("title", body);
            caseEntity.Attributes.Add("mobilephone", fromNumber);
            Service.Create(caseEntity);
        }
    }
}

Now let's Implement the Status Callback Webhook, right click on project àAdd àNew Azure Function.

Give function name as MessageStatus.cs Select the Http trigger and click on Add as shown in the below screens.

Http trigger

Azure Function

HTTP

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Twilio.AspNet.Core;
using Twilio.TwiML;
using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk;

namespace TwilioMessage
{
    public class MessageStatus
    {
        private readonly ILogger<MessageStatus> _logger;

        public MessageStatus(ILogger<MessageStatus> logger)
        {
            _logger = logger;
        }

        [Function("MessageStatus")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
        {
            _logger.LogInformation("C# HTTP trigger function processed a request.");

            var form = await req.ReadFormAsync();
            string messageSid = form["MessageSid"];
            string messageStatus = form["MessageStatus"];

            _logger.LogInformation(
                "Status changed to {MessageStatus} for Message {MessageSid}",
                messageStatus,
                messageSid
            );

            return new OkResult();
        }
    }
}

Deploy the Azure Function to Azure.

Navigate to https://portal.azure.com/ and search for the function app.

Deploy the Azure Function

Consumption

Select the resource group in which you want to create the function app, give the function name, and click on Review + Create.

Select resource group

Note. Make sure you create your Environment Variables in the Azure function, whatever you are using in the app.cofig file.

 Environment Variables

The Azure function will be created.

Now, let’s publish the function app on Azure. Right-click on project and click on publish.

Publish function app

Publish

Publish in Azure

Subscription Name

Once the Azure function is published, get the URL.

Get URL

Configure the webhook URL in Twilio

Now that we have the Azure function app URL, let’s configure the webhook URL in twilo.

  1. Log in to the Twilio console and select your Account.
  2. Click on the Explore Products and select Phone Numbers. Then, in the left side navigation, click on Phone Numbers àManage àActive Numbers.
  3. Click the active number you'd like to use which will take you to the configuration page.
  4. On the configuration page, scroll down to the Messaging Section. Under ‘A MESSAGE COMES IN’, set the first dropdown to Webhook, then into the text box, enter the azure function app URL as the path, and lastly, set the second dropdown to HTTP POST.
    Messaging Section
    Active Numbers
    URL
  5. Click Save and then send an SMS to your Twilio Phone Number.
    Twilio Phone Number

Thank you!