Creating a Lead via the Salesforce.com API

Creating a Lead via the Salesforce

Choosing the Right WSDL For You and Your Organization

Salesforce uses SOAP as its Web Services protocol, and SOAP uses an XML file called a WSDL (Web Services Definition Language) file that defines how a client (our code) can interact with a server (Salesforce). For our purposes, there are two different types of WSDL files, Enterprise and Partner. Here are the specifics:

Enterprise WSDL

  • Is strongly typed
  • Contains the metadata about all standard and custom fields and objects
  • Can only be used against your Salesforce instance

Partner WSDL

  • Is loosely typed
  • Takes an array of key-value pairs
  • Does not contain metadata about objects and fields
  • Can be used against many Salesforce.com organizations

In our organization, we use the Enterprise WSDL, and the main reason why is that we like having a reference of all custom fields and objects readily available in the XML. Having the type of every field right there next to the field name at hand is nice as well. This being said, if we had a need to interact with many Salesforce.com instances, we might choose to use the Partner WSDL instead.

For the purposes of this blog, we’re generally going to be writing against the Enterprise WSDL, but our first example will be presented at the end in an ‘Enterprise’ version and a ‘Partner’ version. Those of you who find you prefer the Partner WSDL should be able to take the Partner example and adapt it in the future very easily.

Generating the WSDL

Each instance of Salesforce (each sandbox and production instance) will have their own corresponding WSDL file. It can be generated by going to Setup > Develop > API > Generate Enterprise WSDL (or Generate Partner WSDL) and downloading the generated XML. I prefer to keep the default name and put each file in a dev/, staging/, and production/ folder, but you could just as easily call the files dev.enterprise.wsdl.xml, or something to that effect.

Taking a Look at the Lead Generation Code

Now that we’re set up with our WSDL, let’s take a look at the code at the bottom of the previous post. I have removed the logout() call, after I read (and subsequently validated) this absolutely terrific article that pointed out that a user’s API connections all get the same session ID! This means that logout() actually invalidates all of the concurrent connections for that user. This is somewhat of an edge case for us, as page load times are generally very short, but all the same, we won’t be using the logout() call going forward. If you’re wondering, logging out through the Salesforce API does not log the same user out of any API connections. At any rate, here is the code, slightly modified, and this time with some comments:

Configuration passages:

define('SALESFORCE_USER', 'integration@example.com.sbox1');
define('SALESFORCE_PASS', '*password here*');
define('SALESFORCE_TOKEN', '*security token here*');
define('SALESFORCE_WSDL', '/path/to/enterprise.wsdl.xml');

Code:

require_once('SforceEnterpriseClient.php');

/**
 * explicitly turn off WSDL caching
 * there is a bug in PHP with this setting in php.ini
 * http://bugs.php.net/bug.php?id=41665
 * so it's safest to set it in the PHP source
 *
 * This param should take an int, not a string like most examples use
 * see http://us3.php.net/manual/en/soap.configuration.php
*/
ini_set('soap.wsdl_cache_enabled', 0);

// instantiate a new Salesforce Enterprise object
$crmHandle = new SforceEnterpriseClient();

// instantiate a SOAP connection to Salesforce
try {
  $crmHandle->createConnection(SALESFORCE_WSDL);
} catch (Exception $e) {
  // handle exception - did you set the WSDL path above?
  // we may also be in a Salesforce outage right now
}

// log in to Salesforce
try {
  $crmHandle->login(SALESFORCE_USER, SALESFORCE_PASS . SALESFORCE_TOKEN);
} catch (Exception $e) {
  // handle exception - did you modify the credentials above to your own?
}

// create our lead
$lead = array();
$lead['FirstName'] = 'Joe';
$lead['LastName'] = 'Moke';
$lead['Email'] = 'jmoke@example.com';
$lead['Title'] = 'CEO';

// create the lead
// $lead must be wrapped in an array, as create() can create
// many objects with a single API call
$result = $crmHandle->create(array($lead), 'Lead');

But Wait, Where’s Our Lead?

In this case, there was no exception thrown, but a var_dump() of the $result object will reveal what went wrong:

  ["errors"]=>
  object(stdClass)#8 (3) {
    ["fields"]=>
    string(7) "Company"
    ["message"]=>
    string(38) "Required fields are missing: [Company]"
    ["statusCode"]=>
    string(22) "REQUIRED_FIELD_MISSING"
  }
  ["id"]=>
  NULL
  ["success"]=>
  bool(false)

Salesforce will usually throw an exception when things go haywire, but not always, as in our example. When there is an error, and no exception is thrown, $result->success will equal false, so always be prepared for both possibilities, and you can re-throw or create an exception as it applies to your situation.

The REQUIRED_FIELD_MISSING error is actually fairly unusual to see in the API. In nearly all cases, creating and updating via the API will exempt you from populating required fields, except where it would render the resulting object useless (omitting LastName from a lead, for instance). So, let’s set the company, and take another look at var_dump($result):

$lead['Company'] = 'Bob\'s Country Bunker';

object(stdClass)#7 (2) {
  ["id"]=>
  string(18) "00QS00000034zU4MAI"
  ["success"]=>
  bool(true)
}