Capture Salesforce Outbound Message with a PHP SOAP Listener


To integrate Salesforce and other system, you need to make sure they may communicate with each other.

Web-to-lead is an example for Salesforce to capture message from others. Another example is a variant of “Get data through Salesforce REST API” section in my last post. You may change the Salesforce Object Query Language (SOQL) in Apex code into Salesforce Object Search Language (SOSL) for more flexible database operation in Salesforce.

Another case is when Salesforce need to pass data to other service. This is our focus. Here I am going to how to capture Salesforce Outbound Message with PHP.

Create Outbound Message in Salesforce

You need to create an Outbound Message, and a Workflow Rules or Approval Process to trigger it. The key is to put the url for your capture program in the Endpoint URL and Fields to Send in outbound message.

Below is an example for our outbound message:

An outbound message call http://labphp.ap01.aws.af.cm/capture.php and pass filed value CreatedDate, Id, and LastName to it.
An outbound message call http://labphp.ap01.aws.af.cm/capture.php and pass filed value CreatedDate, Id, and LastName to it.

 

Write a SOAP Listener

It looks like a socket program in Delphi with Indy. But it is easier to pass, convert, and parse the message, you have better tools with PHP.

First, you need to prepare a returned message to acknowledge Salesforce Outbound Message is successfully received. coling provide a sample code in salesforce Outbound message Listener. If it fails, the outbound message may be resent in Salesforce in the Outbound Messaging Delivery Status in [Administration Setup]→[Monitoring]→[Outbound Mesages]

Second, turn on the output buffering with ob_start, use fopen and php://input to create the handler doe  read-only data stream, and fread to read message into buffer.

Now, you may process the message. You might also being interested to read my Parse XML with namespace by SimpleXML in PHP to get the field value.

Last, respond and ob_end_clean to discard and turn off output buffering.

Here is an sample to capture Salesforce Output Message and save it as a file.

<?php
// Returned response to SFDC and to stop resend
function respond($returnedMsg) {
         print '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope 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 xmlns="http://soap.sforce.com/2005/09/outbound">
         <Ack>' . $returnedMsg . '</Ack>
         </notifications>
         </soapenv:Body>
         </soapenv:Envelope>';
}

header("Content-Type: text/xml\r\n");
ob_start();
 
$capturedData = fopen('php://input', 'rb');
$content = fread($capturedData,5000);

$outputFile = fopen("capturedData.txt", "a");
fwrite($outputFile, $content.PHP_EOL);
fclose($outputFile);

fclose($capturedData);

ob_end_clean();

respond('true');
?>

This is the content of capturedData.txt.

Content of capturedData.txt which is the captured message from Salesforce
Content of capturedData.txt which is the captured message from Salesforce

 

Reference

  1. How to get data in Salesforce from WordPress without authentication?
  2. Salesforce: Salesforce Object Query Language (SOQL)
  3. Salesforce: Salesforce Object Search Language (SOSL)
  4. Indy: Internet Socket
  5. Salesforce: salesforce Outbound message Listener
  6. PHP.net: ob_start
  7. Parse XML with namespace by SimpleXML in PHP
  8. PHP.net: fopen
  9. PHP.net: php://
  10. PHP.net: fread
  11. PHP.net: ob_end_clean

8 thoughts on “Capture Salesforce Outbound Message with a PHP SOAP Listener

  1. Hi Amigo, I hope your’re well.

    I was wondering if you could help – this post has been a really fantastic resource, along with your XML parsing post but, as you advised yourself, I went down the route of using Hisateru Tanaka’s code.

    I’m struggling to parse the $args object that it fills with the Salesforce information. I’m using the following code:

    ————-

    $object = $args->Notification;

    foreach($object as $item) {

    //send info to a pasteb.in endpoint for testing

    }

    ————–

    However, where more than one record is processed by Salesforce only one iteration is being passed to the endpoint, it doesn’t loop through each sObject. So, for example, if 3 records trigger the Outbound Message, only data from one sObject is being parsed and sent through to the paste.bin

    Any help would be very much appreciated.

    Cheers!

    Louis

    Liked by 1 person

    • Dear Louis,

      Yes, this is originally from Hisateru Tanaka’s questions to me via Facebook. I spend some days and share what I got with him. He did a great job to make it more usable!

      I am interested in your questions. I think you mean if you have 3 records. The first trigger the rule and send notification to target service. The target service got a notification and save it to $object which is an array type variable. If only the last is kept, it sounds like a syntax issue.

      But I am busy till 2015/4/10 and needs 48 hours to test. I will see what I got and reply here on 2015/4/12. Please check it again 2on 2015/4/13 Mon.

      Have a nice day!

      Best regards,

      Amigo

      Like

      • Thanks for taking a look!

        Just to clarify, I’m pulling in the outbound message data which, when there are multiple messages, Salesforce automatically combines into one message.

        Hisateru’s code pull in this message and outputs the information into an object named $args.

        When you print $args it looks like the code I’ve pasted below. I’m wondering how you loop through each sObject individually and post that data to an endpoint.

        I was expecting something like:

        foreach($args->Notifiaction->sObject as $item) { do stuff }

        would work, but it’s not.

        Cheers for the help! I’ll check back later in the month!

        If I find out the answer in the meantime I’ll post it here.

        ____________

        stdClass Object
        (
        [OrganizationId] => XXXXXXXXXXXXXXXX
        [ActionId] => XXXXXXXXXXXXXXXX
        [SessionId] =>
        [EnterpriseUrl] => https://darlston-dev-ed.my.salesforce.com/services/Soap/c/33.0/XXXXXXXXXXXXXXXX
        [PartnerUrl] => https://darlston-dev-ed.my.salesforce.com/services/Soap/u/33.0/XXXXXXXXXXXXXXXX
        [Notification] => Array
        (
        [0] => stdClass Object
        (
        [Id] => XXXXXXXXXXXXXXXX
        [sObject] => stdClass Object
        (
        [Id] => XXXXXXXXXXXXXXXX
        [Contact_Email__c] => test@testemail.com
        )

        )

        [1] => stdClass Object
        (
        [Id] => XXXXXXXXXXXXXXXX
        [sObject] => stdClass Object
        (
        [Id] => XXXXXXXXXXXXXXXX
        [Contact_Email__c] => test@testemail.com
        )

        )

        [2] => stdClass Object
        (
        [Id] => XXXXXXXXXXXXXXXX
        [sObject] => stdClass Object
        (
        [Id] => XXXXXXXXXXXXXXXX
        [Contact_Email__c] => test@testemail.com
        )

        )

        )

        )

        Liked by 1 person

  2. Hi Amigo, I managed to get this sorted.

    The problem was that I had this:

    $object = $args->Notification;

    foreach($object as $item) {

    $sf = $item->sObject;

    //Create variables for Salesforce fields
    $SalesforceField = $sf->SalesforceField__c

    //DO STUFF

    // Success response
    return Response::success();

    }

    So, my success response was inside the loop and was breaking it – this is why I was only getting the first response, not the rest. Doh!

    Moving the success response outside the foreach loop solved the problem.

    Thanks again for the post- wouldn’t have got this to work without it and the XML post. Will have to read the rest of your stuff!

    Cheers!

    Louis

    Liked by 1 person

    • Dear Louis,

      Thank you for sharing this with us! It’s very helpful!

      From your description, it seems Tanaka’s code is okay. I am glad to see your feedback and it must helps others!

      I am currently involved in a short-term project and has no time to feedback as usual. Let’s keep in touch! After this contract job, I want to create a post based on your experience to help others to use Tanaka’s code!

      Have a nice day and keep in touch!

      Best regards,

      Amigo

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s