Serverless Salesforce Messaging with Azure Functions

Introduction

The new computing paradigm of serverless allows developers to quickly spin up, prototype, and build out applications using inexpensive usage based resources. In this article, we’re going to go over how to connect your Salesforce Outbound Messages to Azure Functions for processing. As of this writing, as far as I’m aware, there are no governor limits on Outbound Messages and also Azure Functions are priced at $0.20/million executions with 1 million in the free grant per month. If you’re not already comfortable working with Outbound Messages in .NET, I’ve got you covered with a post on this topic I did previously.

Pre-requisites

Some things you’ll want to be sure are setup before proceeding below, are to ensure that you have the Azure Functions Core Tools setup on your machine. The guide that walks through install steps for Windows, MacOS, and Linux is at the top of this document. These are command line tools you’ll use to execute your Azure Functions code. You’ll also want to ensure you have the Azure Functions extension for VSCode installed.

Initialize Your Azure Function

After ensuring you have the Azure Functions tooling setup and configured properly, create and navigate to an empty directory on your machine and run “code .” to begin VS Code from the current directory. Go ahead and run the command palette command (ctrl+shift+p on windows) in VS Code to run “Azure Functions: Create Function…” command. For the language, go ahead and select your favorite (I’m using Javascript), and select the trigger type as HttpTrigger.

Azure Function Code Sample

Update your index.js file (the one that holds your trigger code) to the example below:

let xmlParser = require("xml2json");

module.exports = async function(context, req) {
  let sfData = null;

  // convert incoming raw soap xml message to json.
  try {
    sfData = xmlParser.toJson(req.body, { object: true });
  } catch (ex) {
    console.log(ex);
    context.res = {
      status: 500,
      body:
        "An error occurred trying to parse the incoming xml.  Check the log."
    };
  }

  // for diagnostics output the actual message
  context.log(JSON.stringify(sfData["soapenv:Envelope"]["soapenv:Body"]));

  // Send the acknowledgement response back to Salesforce.
  var resXml =
    '<?xml version="1.0" encoding="UTF-8"?>' +
    ' <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">' +
    "  <soapenv:Body>" +
    '    <ns3:notificationResponse xmlns:ns3="http://soap.sforce.com/2005/09/outbound">' +
    "      <ns3:Ack>true</ns3:Ack>" +
    "    </ns3:notificationResponse>" +
    "  </soapenv:Body>" +
    " </soapenv:Envelope>";

  context.res = {
    status: 200,
    body: resXml,
    headers: { "content-type": "application/xml" } // be sure to denote content type
  };
};

The code above can be broken into three separate components. The first step is we are parsing the raw incoming XML (Salesforce uses SOAP messaging for it’s outbound messages). You’ll need to npm install the package xml2json. The second piece is we are logging the content of the soap message, which contains the actual message contents, the object’s id, the organization’s id, and some other details. The final step is we send the acknowledgement XML back to Salesforce so it recognizes we have confirmed receipt of the incoming message. Salesforce will continue to attempt to send the message over and over for up to 24 hours if it does not receive an acknowledgement.

Running Azure Functions Locally

To test our code locally, we are going to open the terminal window in VS Code (or open a command prompt and navigate to the project directory) and run two commands. The first command we will run is func start which will begin running our function code and it will begin listening (likely on localhost:7071). Using the tool ngrok, we’ll want to map that 7071 port on our machine to a public facing URL and also then update our Outbound Message definition so that it points to this URL. The specific command we will run is ngrok http 7071 and we’ll then see a screen like this:

From here, I know that I need to specify that my Outbound Message definition points to https://7655c914.ngrok.io/api/SalesforceMessageHandler [SalesforceMessageHandler is what I named my Azure Function when I created it].

Now, once we have triggered out Outbound Message, we will see in our output window for our func start command, that our message has been received, and we are properly logging the output to the console. You could always take this output and then process it immediately, but my recommendation would be to log the message somewhere (Azure SQL, Azure Service Bus, etc) and then process it on a separate thread. My rationale for this is because it makes your application more durable and allows you to recover easier from any errors since you may lose messages if you are unable to log them for a 24 hour period.

Conclusion

Wrapping up here, we’ve gone over one way you can use Azure to integrate with Salesforce. I plan to have some additional posts in the future, like Azure Logic Apps and other services that can be leveraged in tandem with Salesforce. I’ll also add here that Salesforce has recently introduced Salesforce Evergreen as a way to handle serverless code executions directly on the platform, so you’ll have plenty of options in the future.

 

Kyle Ballard

Kyle is a software developer with 15+ years of experience and holds Microsoft and Salesforce developer certifications. He is also a spouse, father, aspiring home chef, and technology enthusiast.