Last active
January 1, 2018 07:37
-
-
Save shawn-crigger/53c431aabf81f8d9e12822302da977af to your computer and use it in GitHub Desktop.
Salesforce SOAP API Outbound Message Listener
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Salesforce Workflow Outboud message reciever sample in PHP | |
* | |
* requires: php-soap extension | |
* | |
* At 1st you should download WSDL of the message and put it besides this script. | |
*/ | |
//ini_set("soap.wsdl_cache_enabled", "0"); // clean WSDL for develop | |
ini_set('display_errors', 1); | |
/** | |
* Simple method to write string to a file | |
* | |
* @param string $log The log | |
*/ | |
function log_writeln( $log = '' ) | |
{ | |
$success = file_put_contents(__DIR__ . '/log/' . @date('Y-m-d') . '.log', $log . "\n", FILE_APPEND); | |
} | |
/** | |
* Salesforce Outbound Response type | |
*/ | |
class Response | |
{ | |
public $Ack; | |
function __construct($success) | |
{ | |
$this->Ack = $success; | |
} | |
public static function success() | |
{ | |
return new static(true); | |
} | |
public static function fail() | |
{ | |
return new static(false); | |
} | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Simple wrapper for success wrapper | |
*/ | |
class WSDL_Response { | |
/** | |
* Outputs XML response of true or false to SOAP server | |
* @static | |
* @param string $tf | |
* @return VOID | |
*/ | |
public static function respond( $response = true ) | |
{ | |
$response = ( true === $response ) ? 'true' : 'false'; | |
$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>{$response}</Ack> | |
</notifications> | |
</soapenv:Body> | |
</soapenv:Envelope> | |
ACK; | |
echo trim($ACK); | |
} | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Main class that listens for the server response and processes the data | |
* | |
*/ | |
class Listener { | |
/** | |
* WSDL file | |
* | |
* @var string | |
*/ | |
private $_wsdl = __DIR__ . '/' . 'wfoutbound.wsdl'; | |
/** | |
* MySQL holder | |
* @var object | |
*/ | |
private $_mysql = NULL; | |
/** | |
* MySQL config | |
* @var array | |
*/ | |
private $_config = array( | |
'user' => '', | |
'pass' => '', | |
'db' => '', | |
'table' => 'opportunity', | |
); | |
/** | |
* SOAP server holder | |
* @var SOAPServer | |
*/ | |
private $_server; | |
public function __construct($value='') | |
{ | |
//$this->_wsdl = 'http://35.197.164.194/s6.wsdl'; | |
$options = array( 'trace' => 1, 'exceptions' => 1, 'soap_version' => SOAP_1_2 ); | |
try { | |
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ''; | |
$this->_server = new SOAPServer( $this->_wsdl, $options ); | |
// xml_parser( $this->_wsdl, $this->_server ); | |
$this->_server->setClass( 'Listener' ); | |
$request = file_get_contents('php://input'); | |
// start buffer | |
ob_start(); | |
$this->_server->handle( $request ); | |
// collect response from buffer | |
$response = ob_get_clean(); | |
// $server = new SoapServer(null, array('uri' => 'https://website.com/services/SFService.php')); | |
} | |
catch(SOAPFault $e) { | |
error_log(print_r($e->getMessage(),1).' '.__FILE__.':'.__LINE__,0); | |
} | |
$this->_process( $response ); | |
// dump($resp); | |
return $response; | |
} | |
// ------------------------------------------------------------------------ | |
private function _connect_mysql() | |
{ | |
$this->_mysql = mysqli_connect( $this->_config['db'], $this->_config['user'], $this->_config['pass'] ); | |
// Check connection | |
if (!$this->_mysql) | |
{ | |
die("Connection failed: " . mysqli_connect_error() ); | |
} | |
return true; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Handles processing the response object | |
* | |
* @param object $data Response from the WSDL server | |
*/ | |
private function _process( $data ) | |
{ | |
log_writeln( $data ); | |
// test line to verify response is as expected. | |
if ( ! isset( $data->Notification ) ) return false; | |
log_writeln( '$data->Notification is set, need to loop then' ); | |
$array = $data->Notification; | |
// There should be the following object values inside of $row->sObject | |
// $row->Id | |
// $row->sObject->Notes__c | |
// $row->sObject->Telemarketer__c | |
// Will write the SQL to check against $row->Id, if exists UPDATE else CREATE | |
// temp response log, after a log has been run, the SQL query can be wrote. | |
foreach ($array as $row) | |
{ | |
log_writeln( 'NOTIFICATION ID = ' . $row->Id ); | |
foreach ($row->sObject as $key => $value) | |
{ | |
log_writeln( 'KEY = ' . $key ); | |
log_writeln( 'VALUE = ' . $value ); | |
} | |
} | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Handles MySQL INSERT of notification | |
* @access private | |
* @param array $values Array containing Id, telemarketer and notes | |
*/ | |
private function _create( $values ) | |
{ | |
$table = $this->_config['table']; | |
$db = $this->_config['db']; | |
$now = date('Y-m-d H:i:s'); | |
$close = $now; | |
$amount = '0.00'; | |
$probability = '0.00'; | |
$expected = '0.00'; | |
$isClosed = 0; | |
$isWon = 0; | |
$recordType = 0; | |
$id = mysql_real_escape_string( $values['Id'] ); | |
$telemarketer= mysql_real_escape_string( $values['telemarketer'] ); | |
$notes = mysql_real_escape_string( $values['notes'] ); | |
$sql = "INSERT INTO `{$db}`.`{$table}` | |
(`ID`, `RecordTypeId`, `Name`, `StageName`, `Amount`, `Probability`, `ExpectedRevenue`, | |
`CloseDate`, `IsClosed`, `IsWon`, `CreateDate`, `LastModifiedDate`, `LastActivityDate`, | |
`LastViewedDate`, `ActivityStage`, `Action`, `Phone`, `FirstName`, `LastName`, `Email`, | |
`Source`, `Telemarketer`, `Notes`) | |
VALUES | |
('{$id}', '{$recordType}', '', '', '{$amount}', '{$probability}', '{$expected}', '{$close}', '{$isClosed}', '{$isWon}', '{$now}', '{$now}', '{$now}', '{$now}', '', '', '', '', '', '', '', '{$telemarketer}', '{$notes}' ); | |
"; | |
$result = mysqli_query( $this->_mysql, $sql ); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Handles MySQL UPDATE of notification | |
* @access private | |
* @param array $values Array containing Id, telemarketer and notes | |
*/ | |
private function _update( $values ) | |
{ | |
$table = $this->_config['table']; | |
$db = $this->_config['db']; | |
$id = mysql_real_escape_string( $values['Id'] ); | |
$telemarketer = mysql_real_escape_string( $values['telemarketer'] ); | |
$notes = mysql_real_escape_string( $values['notes'] ); | |
$sql = "UPDATE `{$db}`.`{$table}` SET | |
`Telemarketer` = '{$telemarketer}', | |
`Notes` = '{$notes}' | |
WHERE `{$table}`.`ID` = '{$id}';"; | |
$result = mysqli_query( $this->_mysql, $sql ); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Queries database from record with ID returns true/false if record exists | |
* @access private | |
* @param string $id Notification ID | |
* @return boolean | |
*/ | |
private function _check_record( $id ) | |
{ | |
$table = $this->_config['table']; | |
$db = $this->_config['db']; | |
$id = mysql_real_escape_string( $id ); | |
$sql = "SELECT `ID` FROM `{$db}`.`{$table}` WHERE 1 = 1 AND `ID` = '{$id}' "; | |
$result = mysqli_query( $this->_mysql, $sql ); | |
if ( mysqli_num_rows( $result ) > 0 ) return TRUE; | |
return FALSE; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Notification request handler | |
*/ | |
public function notifications($args=null) | |
{ | |
log_writeln(date('Y-m-d H:i:s')); | |
log_writeln(print_r($args, true)); | |
// Success response | |
//echo WSDL_Response(true); | |
$response = '<Ack>true</Ack>'; | |
$response = new SoapVar($response,XSD_ANYXML); | |
return $response; | |
return Response::success(); | |
} | |
// ------------------------------------------------------------------------ | |
} | |
// ------------------------------------------------------------------------ | |
//require('./helpers.php'); | |
$notification = new Listener(); | |
// log_writeln($resp); | |
//echo $resp; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!-- | |
Salesforce.com Outbound Notification Web Services API Version 1.0 | |
Generated on 2017-12-31 06:17:19 +0000. | |
Copyright 2005-2017 Salesforce.com, Inc. | |
All Rights Reserved | |
--> | |
<definitions targetNamespace="http://soap.sforce.com/2005/09/outbound" | |
xmlns="http://schemas.xmlsoap.org/wsdl/" | |
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" | |
xmlns:tns="http://soap.sforce.com/2005/09/outbound" | |
xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
xmlns:ent="urn:enterprise.soap.sforce.com" | |
xmlns:ens="urn:sobject.enterprise.soap.sforce.com"> | |
<types> | |
<schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:enterprise.soap.sforce.com"> | |
<!-- Our simple ID Type --> | |
<simpleType name="ID"> | |
<restriction base="xsd:string"> | |
<length value="18"/> | |
<pattern value='[a-zA-Z0-9]{18}'/> | |
</restriction> | |
</simpleType> | |
</schema> | |
<schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:sobject.enterprise.soap.sforce.com"> | |
<import namespace="urn:enterprise.soap.sforce.com" /> | |
<!-- Base sObject (abstract) --> | |
<complexType name="sObject"> | |
<sequence> | |
<element name="fieldsToNull" type="xsd:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/> | |
<element name="Id" type="ent:ID" nillable="true" /> | |
</sequence> | |
</complexType> | |
<complexType name="AggregateResult"> | |
<complexContent> | |
<extension base="ens:sObject"> | |
<sequence> | |
<any namespace="##targetNamespace" minOccurs="0" maxOccurs="unbounded" processContents="lax"/> | |
</sequence> | |
</extension> | |
</complexContent> | |
</complexType> | |
<complexType name="Call_Attempt__c"> | |
<complexContent> | |
<extension base="ens:sObject"> | |
<sequence> | |
<element name="Notes__c" nillable="true" minOccurs="0" type="xsd:string"/> | |
<element name="Telemarketer__c" nillable="true" minOccurs="0" type="xsd:string"/> | |
</sequence> | |
</extension> | |
</complexContent> | |
</complexType> | |
</schema> | |
<schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://soap.sforce.com/2005/09/outbound"> | |
<import namespace="urn:enterprise.soap.sforce.com" /> | |
<import namespace="urn:sobject.enterprise.soap.sforce.com" /> | |
<element name="notifications"> | |
<complexType> | |
<sequence> | |
<element name="OrganizationId" type="ent:ID" /> | |
<element name="ActionId" type="ent:ID" /> | |
<element name="SessionId" type="xsd:string" nillable="true" /> | |
<element name="EnterpriseUrl" type="xsd:string" /> | |
<element name="PartnerUrl" type="xsd:string" /> | |
<element name="Notification" maxOccurs="100" type="tns:Call_Attempt__cNotification" /> | |
</sequence> | |
</complexType> | |
</element> | |
<complexType name="Call_Attempt__cNotification"> | |
<sequence> | |
<element name="Id" type="ent:ID" /> | |
<element name="sObject" type="ens:Call_Attempt__c" /> | |
</sequence> | |
</complexType> | |
<element name="notificationsResponse"> | |
<complexType> | |
<sequence> | |
<element name="Ack" type="xsd:boolean" /> | |
</sequence> | |
</complexType> | |
</element> | |
</schema> | |
</types> | |
<!-- Method Messages --> | |
<message name="notificationsRequest"> | |
<part element="tns:notifications" name="request"/> | |
</message> | |
<message name="notificationsResponse"> | |
<part element="tns:notificationsResponse" name="response"/> | |
</message> | |
<!-- PortType --> | |
<portType name="NotificationPort"> | |
<operation name="notifications"> | |
<documentation>Process a number of notifications.</documentation> | |
<input message="tns:notificationsRequest"/> | |
<output message="tns:notificationsResponse"/> | |
</operation> | |
</portType> | |
<!-- Binding | |
You need to write a service that implements this binding to receive the notifications | |
--> | |
<binding name="NotificationBinding" type="tns:NotificationPort"> | |
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> | |
<operation name="notifications"> | |
<soap:operation soapAction=""/> | |
<input> | |
<soap:body use="literal"/> | |
</input> | |
<output> | |
<soap:body use="literal"/> | |
</output> | |
</operation> | |
</binding> | |
<!-- Service Endpoint --> | |
<service name="NotificationService"> | |
<documentation>Notification Service Implementation</documentation> | |
<port binding="tns:NotificationBinding" name="Notification"> | |
<soap:address location="http://35.197.164.194/s6.wsdl"/> | |
</port> | |
</service> | |
</definitions> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment