Integration-Salesforce-outbound-messages

Salesforce Webhooks / Outbound Messages

To send an Outbound Message in Salesforce when an Opportunity changes, have to use Outbound Messages and Flows. Here is a step-by-step guide using a Flow:

Setup

1. Add an Outbound Message:

  • -  Go to "Setup"
  • -  Navigate to "Process Automation" -> "Workflow Actions" -> "Outbound Messages"
  • -  Click on "New Outbound Message".
  • -  Enter a name for the Outbound Message.
  • -  Enter the CustomJS Function URL of the function you want to execute.
  • -  Select the fields that should be included in the message.
  • -  Click "Save".

Create Outbound Message
Create Outbound Message

2. Send Outbound Message with Flows

Nowadays you have to use the Flow Builder to trigger outgoing messages:

  • -  Navigate to "Setup" -> "Process Automation" -> "Flows":
  • -  Click on "New Flow"
  • -  Define the Process
  • -  Activate the Flow
    Create Outbound Message
    Create Outbound Message

3. Now you receive Salesforce webhooks with CustomJS

Salesforce sends the data in the webhook as SOAP XML type. We use the NodeJS plugin xml-js to transform it into a JSON object. It will look like this:

{
  "_declaration": {
    "_attributes": {
      "version": "1.0",
      "encoding": "UTF-8"
    }
  },
  "soapenv:Envelope": {
    "_attributes": {
      "xmlns:soapenv": "http://schemas.xmlsoap.org/soap/envelope/",
      "xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
      "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance"
    },
    "soapenv:Body": {
      "notifications": {
        "_attributes": {
          "xmlns": "http://soap.sforce.com/2005/09/outbound"
        },
        "OrganizationId": {
          "_text": "00Dd20000013WE5EAM"
        },
        "ActionId": {
          "_text": "04kd20000000DoTAAU"
        },
        "SessionId": {
          "_attributes": {
            "xsi:nil": "true"
          }
        },
        "EnterpriseUrl": {
          "_text": "https://technologycirclegmbh-dev-ed.develop.my.salesforce.com/services/Soap/c/61.0/00Dd20000013WE5"
        },
        "PartnerUrl": {
          "_text": "https://technologycirclegmbh-dev-ed.develop.my.salesforce.com/services/Soap/u/61.0/00Dd20000013WE5"
        },
        "Notification": {
          "Id": {
            "_text": "04ld200000000HlAAI"
          },
          "sObject": {
            "_attributes": {
              "xsi:type": "sf:Opportunity",
              "xmlns:sf": "urn:sobject.enterprise.soap.sforce.com"
            },
            "sf:Id": {
              "_text": "006d2000000ftCLAAY"
            },
            "sf:Amount": {
              "_text": "40000.0"
            },
            "sf:CloseDate": {
              "_text": "2024-06-30"
            },
            "sf:CreatedById": {
              "_text": "005d2000000g0d9AAA"
            },
            "sf:CreatedDate": {
              "_text": "2024-06-27T11:29:16.000Z"
            },
            "sf:ExpectedRevenue": {
              "_text": "12000.0"
            },
            "sf:FiscalQuarter": {
              "_text": "2"
            },
            "sf:FiscalYear": {
              "_text": "2024"
            },
            "sf:ForecastCategory": {
              "_text": "Pipeline"
            },
            "sf:ForecastCategoryName": {
              "_text": "Pipeline"
            },
            "sf:HasOpenActivity": {
              "_text": "false"
            },
            "sf:HasOpportunityLineItem": {
              "_text": "false"
            },
            "sf:HasOverdueTask": {
              "_text": "false"
            },
            "sf:IsClosed": {
              "_text": "false"
            },
            "sf:IsDeleted": {
              "_text": "false"
            },
            "sf:IsPrivate": {
              "_text": "false"
            },
            "sf:IsWon": {
              "_text": "false"
            },
            "sf:LastAmountChangedHistoryId": {
              "_text": "008d2000000pjlhAAA"
            },
            "sf:LastModifiedById": {
              "_text": "005d2000000g0d9AAA"
            },
            "sf:LastModifiedDate": {
              "_text": "2024-06-28T21:16:06.000Z"
            },
            "sf:LastReferencedDate": {
              "_text": "2024-06-28T21:16:06.000Z"
            },
            "sf:LastViewedDate": {
              "_text": "2024-06-28T21:16:06.000Z"
            },
            "sf:Name": {
              "_text": "Tes Opp3"
            },
            "sf:NextStep": {
              "_text": "NewValue7"
            },
            "sf:OpportunityId__c": {
              "_text": "006d2000000ftCL"
            },
            "sf:OwnerId": {
              "_text": "005d2000000g0d9AAA"
            },
            "sf:Probability": {
              "_text": "30.0"
            },
            "sf:PushCount": {
              "_text": "0"
            },
            "sf:StageName": {
              "_text": "Needs Analysis"
            },
            "sf:SystemModstamp": {
              "_text": "2024-06-28T21:16:06.000Z"
            },
            "sf:Type": {
              "_text": "Existing Customer - Replacement"
            }
          }
        }
      }
    }
  }
}

With this helper you can easily read propeties from the JSON structure:
function getField(input, fieldName){
  try {
    return input["soapenv:Envelope"]["soapenv:Body"].notifications.Notification.sObject[`sf:${fieldName}`]._text;
  } catch(e) {
      throw new Error('Field not found');
  }
}

You also have to make sure that you send a proper repsonse back to Salesforce because otherwise the webhook will be executed over and over again.
return `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <notificationsResponse xmlns="http://soap.sforce.com/2005/09/outbound">
      <Ack>true</Ack>
    </notificationsResponse>
  </soapenv:Body>
</soapenv:Envelope>`;

Use Cases