Using SalesNet Web Services from PHP

I’ve been working on some projects recently where I’ve had to make heavy use of the SalesNet CRM API. I’ve written some code that makes basic access of the API easier and I thought I would write about it a little here. The SalesNet API is vast in scope (the documentation runs to 144 pages!) and very fully featured. However, it is not particularly easy to use at all and is somewhat frustrating. My aim in the code was to ease some of the basic frustrations in using the API. Full code and unit tests for the classes that I wrote can be found on GitHub.

API Format

The SalesNet API is SOAP based and consists of 8 separate endpoints, each of which allows you to operate on different parts of a companies data such as deals, accounts, contacts, etc. Before you can use any of these services it’s necessary to authenticate against a separate security endpoint. This returns a token which is valid for between 1-12 hours (depending on the account setup in SalesNet). This token must then be set in a SOAP header for use in requests to any of the main SalesNet endpoints. Each of the API methods accepts many arguments to control precisely the data that is returned and the only thing I can suggest to anyone looking to use the API is to refer to the documentation. One of the quirks of the API is that data is returned as XML, embedded in a stdClass object. For example, a call to the GetDeals method of the deals endpoint returns a stdClass object (say $obj), and to access the response data the following would be needed:


$response = $obj->GetDealsResult->any;

In the above example $response would now include the XML data ‘payload’, which can then be parsed. It’s often not that easy to parse the XML returned as it seems to be an XML representation of a Microsoft ADODB recordset, which in some cases is not even properly formed XML. I’ve had luck using SimpleXML and Xpath to extract the nodes I’m after however.

The Code

To work with the various SalesNet API’s I created two classes, one of which handles authentication and the other of which acts as a proxy to catch and pass SOAP calls through to the API. Both of the classes make use of ‘lazy loading’ and will only connect to SalesNet as and when a method is called that requires a SOAP call.

The Authentication Class

My goal in the authentication class was to simplify authenticating against the SalesNet security endpoint. The object accepts a company name, username and password and will retrieve a security token from SalesNet. This is then set in a PHP SoapHeader object and is returned for use whenever the doLogin() method is called. Internally the class will keep track of when the token expires and will automatically fetch a new token from SalesNet as and when required. My thought is that an object of this class can be serialized and cached to be stored and shared between many requests as a security token can be valid for up to 12 hours.

The SoapProxy Class

The SoapProxy class provides a proxy to trap calls to the many SalesNet API methods. Since there are so many methods cross so many endpoints it would be impossible to map these out to individual methods so I chose to use __call() instead to pass calls through to a PHP SoapClient object. The class stores the URL endpoints of the various services as constants and an API endpoint can be set when an object is instantiated or before any method is called. The object also accepts an instance of the Authentication class and uses this internally to set the security SoapHeader for API calls.

A Brief Example

So, enough talk! As I said earlier full code can be found on GitHub but here’s a brief example of how to use the classes to call the GetDeals method of the Deals endpoint.

<?php
use WebServices\Soap\SalesNet\Authentication, WebServices\Soap\SalesNet\SoapProxy;

try {
    $auth = new Authentication();
    $auth->setCompanyLogin('COMPANY LOGIN HERE')
         ->setUserName('USERNAME HERE')
         ->setPassword('PASSWORD HERE');

    $soap = new SoapProxy(SoapProxy::DEALS, $auth);
    $args = array(
        //Set up method arguments here
    );
    $response = $soap->GetDeals($args);
} catch (BadMethodCallException $e) {
    /**
     * Errors will be caught here.
     * The BadMethodCallException can have a previous exception of a SoapFault if there is one.
     */
}

That’s all there is to it. To use other endpoints simply change the constant passed to the SoapProxy constructor and call another Soap method, with the correct arguments of course. Let me know of any comments on this code or improvements people can see. Enhancements and fixes on GitHub are welcome.

Leave a Reply