[SalesForce] Authentication Bearer in SOAP API

UPDATE

I created the below answer which allows you to use a REST application connection to (from there on) work on the SOAP API without needing to use SOAP's Login method, but instead relies completely on access_token and REST generated URLS to work.

/UPDATE

Hey guys I'm trying to switch gears from REST to SOAP after finding that the RESTful API isn't flexible enough to do exactly what I need to do with it, I am currently trying to migrate a few things into the SOAP request to get this going but am running up against a wall.

I currently have users authorizing an application via REST, and returning Bearer and Access tokens, the step to use those (and the Location URL) are evading me though. I'm hoping that I can use my initial REST request to fuel my SOAP api.

This would mean that there is NO Username/Password sequence from here on!

I've been trying to implement multiple things that I've seen in the Java service, but it looks like they aren't supported in the PHP distro? Here's the code, maybe someone can point me in the right direction.

<?php 
// clear wsdl cache
ini_set("soap.wsdl_cache_enabled", 0);
?>

<pre>
<?php
    define("SOAP_CLIENT_BASEDIR",   'soapclient');

#    define("SF_USERNAME",           'foo@foodomain.com');
#    define("SF_PASSWORD",           'password');
#    define("SF_SECURITY",           ''); // shouldn't be needed after Auth Bearer

#    define("SF_LOCATION",           'https://na15-api.salesforce.com/services/Soap/u/27.0/?????');
#    define("SF_SESSIONID",          '??????');

    define("SF_LOGINURL",         'http://login.salesforce.com');

require_once (SOAP_CLIENT_BASEDIR.'/SforcePartnerClient.php');
require_once (SOAP_CLIENT_BASEDIR.'/SforceHeaderOptions.php');

try {

/**
 *   This section should theoretically be taken over by REST Auth Bearer
 *   so we do not need to use a U/P sequence for clients after accepting 
 *   our application.
 *
 *   $mySforceConnection = new SforcePartnerClient();
 *   $mySoapClient       = $mySforceConnection->createConnection(SOAP_CLIENT_BASEDIR.'/partner.wsdl.xml');
 *   $loginResult        = $mySforceConnection->login(SF_USERNAME, SF_PASSWORD.SF_SECURITY);
 *
 *   $location    = $mySforceConnection->getLocation();
 *   $sessionId   = $mySforceConnection->getSessionId();
 */


    $mySforceConnection     = new SforcePartnerClient();
    $sforceSoapClient       = $mySforceConnection->createConnection(SOAP_CLIENT_BASEDIR.'/partner.wsdl.xml');


        // broken; is not available in PHP distro ??
        $mySforceConnection->setAuthEndpoint(SF_LOGINURL);      // does not exist....
        $mySforceConnection->setServiceEndpoint(SF_LOGINURL);   // does not exist....
        $mySforceConnection->setManualLogin(TRUE);              // does not exist....


    // try
    $globals = $mySforceConnection->describeGlobal();

    $query = "SELECT Id,Name FROM User";
    $response = $mySforceConnection->query($query);
    #    $queryResult = new QueryResult($response);
    #    print_r($queryResult);


    $sObject = new SObject($response->records[0]);
    print_r($sObject);

    /** Expected Output:
     *  Should be as follows

        SObject Object
        (
            [type] => User
            [fields] => stdClass Object
                (
                    [Id]    => ?????
                    [Name]  => foo bar 
                )
        )
    */

} catch (Exception $e) {
  echo $mySforceConnection->getLastRequest();
  echo $e->faultstring;
}

Best Answer

Your code shows you've really tried a lot of stuff - I gave it a go but it looks like it might be expecting a different version of the PHP toolkit, there are methods missing etc...

First, can you try this?

  1. download a brand new version of the Force.com Tookit for PHP,

  2. freshly generate your enterprise WSDL from Setup > Develop > API and save it alongside,

  3. put this minimal snippet in a test file (with your username, password, token) and run it:

    define('USERNAME',       'derp@example.com');
    define('PASSWORD',       'd123456h');
    define('SECURITY_TOKEN', 'fWyABCDQIC81ld5IiOR481234');
    
    require_once 'soapclient/SforceEnterpriseClient.php';
    $mySforceConnection = new SforceEnterpriseClient();
    $mySforceConnection->createConnection('enterprise.wsdl.xml');
    $mySforceConnection->login(USERNAME, PASSWORD . SECURITY_TOKEN);
    
    //extract the Server URL and Session ID (and don't EVER use regexp for this ;-)
    $server_pattern  = '#<serverUrl>(.+)</serverUrl>#';
    $session_pattern = '#<sessionId>(.+)</sessionId>#';
    preg_match($server_pattern,  $mySforceConnection->getLastResponse(), $servers);
    preg_match($session_pattern, $mySforceConnection->getLastResponse(), $sessions);
    var_dump('Server URL: ' . $servers[1]);
    var_dump('Session ID: ' . $sessions[1]);
    

Second, in a separate script:

  1. copy the above Server URL and Session ID into setEndPoint and setSessionHeader like so:

    require_once 'soapclient/SforceEnterpriseClient.php';
    $mySforceConnection = new SforceEnterpriseClient();
    $mySforceConnection->createConnection('enterprise.wsdl.xml');
    $mySforceConnection->setSessionHeader('00Dd0000000GHJK!12345678901z6c5Ghg...');
    $mySforceConnection->setEndPoint('https://na14-api.salesforce.com/...');
    
  2. now perform your query as normal

    $query = 'SELECT Id, Name FROM User ORDER BY ID DESC LIMIT 1 ';
    $response = $mySforceConnection->query($query);
    var_export($response->records[0]);
    
    /**
     * stdClass::__set_state(array(
     *   'Id'   => 005d0000001vfmqAAA,
     *   'Name' => 'Derp Herpinson',
     * ))
     */
    

At this point you are working with the Session ID and not the credentials.