+ Start a Discussion
joshQjoshQ 

PHP SoapServer and Outbound Messages - any complete samples?

Hi There,
I'm excited about the outbound messages and workflow, I was wondering if there is a complete example of creating a Service that will consume the outbound messages? I assume for PHP the use of SoapServer is the easiest.

Also (and maybe this is a feature request)... under monitoring outbound messages it would be great to actually "see" what the soap message looks like.

Thx in advance,
joshQ

joshQjoshQ

OK - two things going on here...
1) Use of SoapServer

2) "Complete" sample of (round trip) Outbound Messages

For number 1 I found this useful link: http://devzone.zend.com/node/view/id/689 this was more then enough to get me going... I recommend you use classes...

While I was at it, I decided to see if I can write a web service from scratch. Again, classes help... I used wsdl writer http://www.giffin.org/wsdlwriter.php. Remember to add the "hints" for data types in the doc area (you can read there about the issues of weakly typed languages and generating WSDL files from code).

To write your client, use wsdl2php  http://www.urdalen.no/wsdl2php/

 

For number 2 I leveraged the little bit of code Vorno posted on 1-15-07.

I created an Outbound Message and pointed it to the following php code (which I dubbed the Crude SOAP Responder for SFDC Outbound Messages):

a) The code will “log” the request to a log file… obviously; this is where you would process the message. Here you get to see what the message really looks like. Remember to change the location/file name...

b) If the file writing was successful, acknowledge True (accepted) else False (then SFDC will try to redeliver the message).

Code:

<?php
/* joshQ 
* Crude SOAP Responder for SFDC Outbound Messages
*
* THIS SOFTWARE IS PROVIDED "AS IS" Yadda yadda yadda…
*
*/ // Get raw post data $data = fopen('php://input', 'rb'); $content = fread($data,5000); // Write message to file $fh=fopen('../soap.txt','a'); // change location $stamp = "\n+++ " . date('r') . " : " . time() . " : +++\n"; fwrite($fh,$stamp); fwrite($fh,$content); fwrite($fh,"\n---------------------------------------------------\n"); $retVal = fclose($fh); // Respond if ($retVal) { respond('true'); }else{ respond('false'); } function respond($tf) { 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>' . $tf . '</Ack> </notifications> </soapenv:Body> </soapenv:Envelope>'; } ?>

And in color...
 

<?php

/* joshQ 
* Crude SOAP Responder for SFDC Outbound Messages
*
* THIS SOFTWARE IS PROVIDED "AS IS" Yadda yadda yadda…
*
*/

// Get raw post data

$data = fopen('php://input', 'rb');

$content = fread($data,5000);

 
// Write message to file

$fh=fopen('../soap.txt','a'); // change location

$stamp = "\n+++ " . date('r') . " : " . time() . " : +++\n";

fwrite($fh,$stamp);

fwrite($fh,$content);

fwrite($fh,"\n---------------------------------------------------\n");

$retVal = fclose($fh);


// Respond

if ($retVal) {

                respond('true');

}else{

                respond('false');

}


function respond($tf) {

                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>' . $tf . '</Ack>

                                                  </notifications>

                                                 </soapenv:Body>

                                                </soapenv:Envelope>';

}

?>

joshQjoshQ
visit: http://www.salesforce.com/us/developer/docs/api/index.htm
look for the outbound sections - joshQ
Ron WildRon Wild
Here's an expanded version of the example above that parses the SF outbound message notification
using DOM and returns an array containing the notification parameters (action id, session id, etc..) and
an sObject populated with the object type, id, and fields provided in the SOAP packet.

The sample code:


<?php
/* Handles SFDC Outbound Message notification.*/

require_once ('../soapclient/SforcePartnerClient.php');
require_once ('../includes/sforce_connection.php');


/* Parse a Salesforce.com Outbound Message notification SOAP packet 
   into an array of notification parms and an sObject.   */
function parseNotification( $domDoc) {
     // Parse Notification parameters into result array
     $result = Array("OrganizationId" => "", 
                    "ActionId" => "", 
                    "SessionId" => "",
                    "EnterpriseUrl" => "",
                    "PartnerUrl" => "",
                    "sObject" => null) ;
                    
     $result["OrganizationId"]      = $domDoc->getElementsByTagName("OrganizationId")->item(0)->textContent;
     $result["ActionId"]           = $domDoc->getElementsByTagName("ActionId")->item(0)->textContent;
     $result["SessionId"]           = $domDoc->getElementsByTagName("SessionId")->item(0)->textContent;
     $result["EnterpriseUrl"]      = $domDoc->getElementsByTagName("EnterpriseUrl")->item(0)->textContent;
     $result["PartnerUrl"]           = $domDoc->getElementsByTagName("PartnerUrl")->item(0)->textContent;

     // Create sObject and fill fields provided in notification
     $sObjectNode = $domDoc->getElementsByTagName("sObject")->item(0);
     $sObjType = $sObjectNode->getAttribute("type");
     if (substr_count($sObjType,"sf:")) $sObjType = substr($sObjType,3);
     $result["sObject"] = new SObject($sObjType);
     $result["sObject"]->type = $sObjType;

     $sObjectNodes = $domDoc->getElementsByTagNameNS('urn:sobject.enterprise.soap.sforce.com', '*');
     $result["sObject"]->fieldnames = array();
     foreach ($sObjectNodes as $node) {
       if ($node->localName=="Id") { // Id goes under sObject->Id
                  $result["sObject"]->Id = $node->textContent;
          } else { // ... the rest go under sObject->fields
          $fieldname = $node->localName;
          $result["sObject"]->fields->$fieldname = $node->nodeValue;
          array_push($result["sObject"]->fieldnames, $fieldname);
        }
     }
     
     return $result;
}  // end parseNotification


// Sends SOAP response to SFDC
function respond($tf) {
         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>' . $tf . '</Ack>
         </notifications>
         </soapenv:Body>
         </soapenv:Envelope>';
}


// Get raw post data
$data = fopen('php://input', 'rb');
$content = fread($data,5000);

// Parse values from soap string
$dom = new DOMDocument();
$dom->loadXML($content);
$resultArray = parseNotification($dom);
$sObject = $resultArray["sObject"];

// Output field names and values to file
$fields_string = "";
foreach ($sObject->fieldnames as $field) {
     $fields_string .= $field." => ".$sObject->fields->$field."\n";
}
          

// Write message and values to a file
$fh=fopen('../soap','a'); 
$stamp = "+++ " . date('r') . " : " . time() . " : +++\n";
fwrite($fh,$stamp);
fwrite($fh,$fields_string);
fwrite($fh,$content);
$ret = fclose($fh);


// Sends SOAP response to SFDC
if ($retVal) {
   respond('true');
}else{
   respond('false');
}

?>

You will probably want to beef up the error handling as you add the code to support your particular application.

Cheers,

Message Edited by Ron Wild on 02-27-2007 06:16 PM

AmigoAmigo

Dear joshQ,

 

A PHP SOAP Listerne for Salesforce Outbound Message is explained very detial in my Capture Salesforce Outbound Message with a PHP SOAP Listener. The key is to create a returned message to acknowledge Salesforce received successfully and create buffer and use fread('php://input', 'rb')  to read.

 

You may use SimpleXMLElement::children to parse the message with namespace

 

Parse XML with namespace by SimpleXML in PHP

 

Wish it helps!

 

Best regards,

 

Amigo