HI Mike,
I have a way to dynamically read the incoming SOAP request instead of hard coding it.
You have:
New way:PHP Code://Reads SOAP incoming message from Salesforce/MAPS
$data = fopen('php://input','rb');
$content = fread($data,5000);
PHP Code:$data = fopen('php://input','rb');
$headers = getallheaders();
$content_length = $headers['Content-Length'];
$buffer_length = 100; // This can be set to a higher number like 1000 if need be
$fread_length = $content_length + $buffer_length;
$content = fread($data,$fread_length);
I would suggest using file_get_contants() instead of fread() as the fread() has a file size limitation of 8192 bytes.
Here is the respond()PHP Code:$data = 'php://input';
$content = file_get_contents($data);
if($content) {
respond('true');
} else {
// This means something might be wrong
mail(BAD_ACK_TO_EMAIL,BAD_ACK_EMAIL_SUBJECT,$content,BAD_ACK_EMAIL_HEADER_WITH_CC);
respond('false');
}
This is the SF error for the OBM:PHP Code:function respond($tf) {
$ACK = <<<ACK
<?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>
ACK;
print trim($ACK);
}
but as for the single ACK file for the bulk OBM, I can't seem to get this to work, any thoughts?Code:java.net.SocketTimeoutException: Read timed out
Please forgive my ignorance, but I've been having trouble with this wonderful, amazing guide of yours. I've had three days to teach myself SOAP and the PHP with it that I need to create a database, and this has been the most helpful thing I've found anywhere, so for that, thank you, but may I ask a few questions?
I've gotten the message to be emailed to me in full, but it's throwing errors in the outbound message monitoring area:What does it mean? I've tried googleing it, but I there are so many differing opinions, and many of them aren't relevant at all.Code:org.xml.sax.SAXParseException: The processing instruction target matching "[xX][mM][lL]" is not allowed.
I put all my SOAP related files (including index.php) in the SOAPclient folder, just because the site I'm working on is mostly static, and messy, so I wanted to keep them all together.
I'm pretty sure the email is formatted correctly, but incase it's not, here that is too:
I have a million more questions, but I don't want to bother you with them all, but if you could help with these things, I'd much appreciate it.Code:<pre>Array ( [Id] => a0AA0000001B48bMAC [Annual_Rent__c] => 258000.0 [Cap__c] => 9.0 [City__c] => Jackson [Metro_Area__c] => Nothrbrook [Options__c] => 32.0 [Price__c] => 3166000.0 [Remaining_Years__c] => 18.0 [State__c] => Mississippi [Status__c] => Available [Tenant__c] => Walgreens ) </pre>
Thank you so much
Are you echoing out or printing out any information before you send back the respond function (true/false) ?
That looks correct! Just to make sure this is the contents of the outbound message being sent to you?
In order to better understand what you are trying to do, can you post the top of your script (without any sensitive information) and let me see it. please make sure you use the PHP tags in your post like you did with the code tags
BTW, thanks for joining the site, I truly appreciate it!
~Mike
Yeah, that's being emailed to me. I have commented out the script I was planning on using to put the data into my data base (I named the database table headers exactly what they they were in salesforce, thus their formating). *EDIT* I was getting the error with the script commented out, as well as with it in, and with it in, I wasn't getting any data into my table. */EDIT*
Thanks so much.PHP Code:<?php
$hostname='xxxxx';
$username='xxxxx';
$password='xxxxx';
$dbname='xxxxx';
$con = mysql_connect($hostname,$username, $password);
mysql_select_db($dbname, $con);
/*Connect To Database
if (!$con)
{
die('Unable to connect to database! Please try again later.');
}
mysql_query("INSERT INTO basicInventory VALUES ($dwin_data['Id'], $dwin_data['Annual_Rent__c'], $dwin_data['Cap__c'], $dwin_data['City__c'], $dwin_data['Metro_Area__c'], $dwin_data['Options__c'], $dwin_data['Price__c'], $dwin_data['Remaining_Years__c'], $dwin_data['State__c'], $dwin_data['Status__c'], $dwin_data['Tenant__c'])");
*/
//Login
require_once('./salesforce_login_script.php');
error_reporting(0);
$data = fopen('php://input','rb');
$content = stream_get_contents($data);
if ($content)
{
respond('true');
}
else
{
respond('false');
}
//login script to salesforce for the $client variable ***change this path
require_once ('sfdc-client.cert');
// setup an array for the data coming in from the SOAP message
$dwin_data = array();
$dom = new DOMDocument();
$dom->loadXML($content);
$resultArray = parseNotification($dom);
unset($resultArray['sObject']);
// Data from SOAP message.
/*********************************************************
* This is where you do all your coding *
* and process the incomingin record as *
* need. use the code: *
* $temp = '<pre>' . print_r($dwin_data,true) . '</pre>'; *
* mail('youremail@address.com', 'Suject', $temp); *
* *
* To test to make sure you are getting the *
* data in an email, change the email address *
*********************************************************/
foreach ($resultArray['MapsRecords'] as $dwin_data)
{
$temp = '<pre>' . print_r($dwin_data,true) . '</pre>';
mail('myemail@gmail.com', 'Suject', $temp);
}
foreach ($resultArray['MapsRecords'] as $dwin_data)
{
$insert="INSERT INTO basicInventory ($resultArray) VALUES ('$dwin_data')";
mysql_query($insert) OR die(mysql_error());
}
//clean all the data and then exit
unset($client);
unset($dwin_data);
unset($dwin_create);
unset($records);
exit;
//functions
/* 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,"MapsRecords" => array());
$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();
$count = 0;
$tempMapRecord = array();
foreach ($sObjectNodes as $node)
{
if ($node->localName == "Id")
{
if ($count > 0)
{
$result["MapsRecords"][] = $tempMapRecord;
$tempMapRecord = array();
}
$tempMapRecord[$node->localName] = $node->textContent;
}
else
{
$tempMapRecord[$node->localName] = $node->textContent;
}
$count++;
}
// Finish last item
$result["MapsRecords"][] = $tempMapRecord;
return $result;
} // end parseNotification
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>';
}
//this is the funciton to query salesforce objects to gather data
//from different fields coming in from the SOAP message
function get_records(&$connection,&$query)
{
$queryOptions = new QueryOptions(2000);
$response = new QueryResult($connection->query($query));
// if the size is zero, where done
if ($response->size > 0)
{
$products = $response->records;
// Cycles through additional responses if the number of records
// exceeds the batch size
while (!$response->done)
{
set_time_limit(100);
$response = $connection->queryMore($response->queryLocator);
$products = array_merge($products,$response->records);
}
}
return $products;
}
?>
Last edited by Koibu0; 07-04-2010 at 02:59 AM. Reason: clarification
So, I've fixed the first error by moving every thing that was above the prolog below it, but now I'm getting this error instead
Still getting everything in the e-mail, and I've checked my documents to make sure there's nothing, including spaces or blank lines, after </root tag>Code:org.xml.sax.SAXParseException: Content is not allowed in trailing section.
Any help you could give would be great.
Just to re-iterate, the ONLY thing that your script can output in response to an outbound message is what comes from respond().
I suspect that your script is prepending or appending something in addition to this.
Have you hit your responder in a browser to debug?
You could also use curl to forge a POST to the responder, and debug even further.
In a browser, I get this:
which is the content of sfdc-client.certCode:false -----BEGIN CERTIFICATE----- MIIESzCCA7SgAwIBAgIQeLtGvqUwAwI+AbaKJ7IFwzANBgkqhkiG9w0BAQUFADCBujEfMB0 GA1UEChMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVyaVNpZ24sIEluYy 4xMzAxBgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gQ2xhc3MgM zFJMEcGA1UECxNAd3d3LnZlcmlzaWduLmNvbS9DUFMgSW5jb3JwLmJ5IFJlZi4gTElBQklM SVRZIExURC4oYyk5NyBWZXJpU2lnbjAeFw0wOTAxMDYwMDAwMDBaFw0xMTAxMDcyMzU5NTl aMIGOMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxQNU2FuIE ZyYW5jaXNjbzEdMBsGA1UEChQUU2FsZXNmb3JjZS5jb20sIEluYy4xFDASBgNVBAsUC0Fwc GxpY2F0aW9uMR0wGwYDVQQDFBRwcm94eS5zYWxlc2ZvcmNlLmNvbTCBnzANBgkqhkiG9w0B AQEFAAOBjQAwgYkCgYEAzKElluHQYlUnFm156Nwup9vqkf9DvnhOJc09GNYKOdz5PkpJ/bF LuN2frmfJTlw6pi4knE2geN3j26iAFGIpqgkfWmAi5knjcIbOvHbMXMg1apuVyK9jmbKy4p ITZCj56PtH7qMjlmwN+ZEcQRVy+urRGJRfBEyE+ht5KrewhlcCAwEAAaOCAXowggF2MAkGA 1UdEwQCMAAwCwYDVR0PBAQDAgWgMEYGA1UdHwQ/MD0wO6A5oDeGNWh0dHA6Ly9jcmwudmVy aXNpZ24uY29tL0NsYXNzM0ludGVybmF0aW9uYWxTZXJ2ZXIuY3JsMEQGA1UdIAQ9MDswOQY LYIZIAYb4RQEHFwMwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3 JwYTAoBgNVHSUEITAfBglghkgBhvhCBAEGCCsGAQUFBwMBBggrBgEFBQcDAjA0BggrBgEFB QcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnZlcmlzaWduLmNvbTBuBggrBgEF BQcBDARiMGChXqBcMFowWDBWFglpbWFnZS9naWYwITAfMAcGBSsOAwIaBBRLa7kolgYMu9B SOJsprEsHiyEFGDAmFiRodHRwOi8vbG9nby52ZXJpc2lnbi5jb20vdnNsb2dvMS5naWYwDQ YJKoZIhvcNAQEFBQADgYEAEFpxxlZKNpcHMKpJ8kR28A8MONmZujTSinMeDEBERS9CL6QyK 8yIrFr1ofe/qaffFgyCzoZs1MItxybOtSvVTloXLKZ+k6Xb1pLVAphbhaoFf4YV8u+Xn91g iot/h9NNkMSu78v7tnQeNfJOVMQB493AaGnbolIYkjTQ0nrU6HE= -----END CERTIFICATE-----
Do you mean that I can't push data into a database using this script? I understand if you don't want to walk a noob through what must be the basics of SOAP and salesforce, but how would I then get data into a data base? Would I use a POST?
Your script is almost there.
By the time you generate the response for SalesForce, you should have already stored the data into your database.
You're getting the outbound message errors because you're responding with unexpected data.
Like I said, your SOAP responder should not output any value other than that which comes from respond().
IE Don't include the cert at the end.
Thanks! It's no longer throwing errors anymore. I mean, the input functions aren't working either, but I'm not getting errors when I use the input functions, so it's progress. Again, thanks so much. I'm sure I can figure it out from here.
Bookmarks