xml Salesforce SOAP API出站消息侦听器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xml Salesforce SOAP API出站消息侦听器相关的知识,希望对你有一定的参考价值。

<?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;
<?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>

以上是关于xml Salesforce SOAP API出站消息侦听器的主要内容,如果未能解决你的问题,请参考以下文章

Salesforce SOAP 接口集成服务

如何在不使用dotnet中的安全令牌(使用soap api)的情况下登录salesforce?

Apex 的 API 简介

Salesforce .net 集成

salesforce 零基础学习(五十五)java通过SOAP方式定时访问某个文件然后插入到sObject中

WSDL 的 SalesForce Web 服务 - 无效的登录 SOAP 错误