Categories
eBay Integration

eBay Integration – the eBay API

Integration with eBay is made possible by the eBay Application Program Interface (API) which is a collection of services that expose methods that can be called from your server to access information and to define notifications to be sent by eBay to your server.

What this means is that the eBay Integration plug-in for Zen Cart, running on your server, can access your account data at eBay. It can create listings, get notified of orders, update listings, and more.

In order to do all these neat things, the plug-in has to get permission to access the API and your data. The plug-in accesses the API by making RESTfull calls to eBay’s servers using the same HTTP protocol that your browser uses to get a web page from a web site or submit a form to it.

In order to use the API, the plug-in needs permission to access it. eBay uses three identifiers as keys – sort like a user ID and password – to let your plug-in call the API methods. The keys are assigned to your application (the plug-in). To create the keys, you have to create an account at eBay’s Developer web site and register your application.

The keys give the plug-in permission to call the eBay API methods, but only to get public information. To get access to your eBay account information, the plug-in needs to get a security token.

The security token grants permission to the plug-in allowing it to access the account information that it needs.

To talk to the eBay API, the plug-in uses a slightly-updated version of a PHP class written by eBay. The eBaySessionHandler class (called just eBaySession by eBay) encapsulates the code for sending a request to an eBay server and receiving the response.

/**
 *  eBay's PHP code for making API calls
 */
class eBaySessionHandler
 {
  var $devID;
  var $appID;
  var $certID;
  var $serverUrl;
  var $compatLevel;
  var $siteID;
  var $verb;

  /**
   * __construct
   * Constructor to make a new instance of eBaySessionHandler with the details needed to make a call
   * Note that authentication credentials (normally token, but could be username and password)
   * are assumed to come in the request body, and not in the constructor args
   * Input: $developerID - Developer key obtained when registered at http://developer.ebay.com
   * $applicationID - Application key obtained when registered at http://developer.ebay.com
   * $certificateID - Certificate key obtained when registered at http://developer.ebay.com
   * $severUrl - URL of the server to use
   * $compatabilityLevel - API version this is compatable with
   * $siteToUseID - the Id of the eBay site to associate the call iwht (0 = US, 2 = Canada, 3 = UK, ...)
   * $callName - The name of the call being made (e.g. 'GeteBayOfficialTime')
   * Output: Response string returned by the server
   */
  function __construct($developerID, $applicationID, $certificateID, $serverUrl, $compatabilityLevel, $siteToUseID, $callName)
   {
    // $this->requestToken = $userRequestToken;
    $this->devID = $developerID;
    $this->appID = $applicationID;
    $this->certID = $certificateID;
    $this->compatLevel = $compatabilityLevel;
    $this->siteID = $siteToUseID;
    $this->verb = $callName;
    $this->serverUrl = $serverUrl;
   }

  /**
   * sendHttpRequest
   * Sends a HTTP request to the server for this session
   * Input: $requestBody
   * Output: The HTTP Response as a String
   */
  function sendHttpRequest($requestBody)
   {
    // build eBay headers using variables passed via constructor
    $headers = $this->buildEbayHeaders ();

    // initialise a CURL session
    $connection = curl_init ();
    // set the server we are using (could be Sandbox or Production server)
    curl_setopt ( $connection, CURLOPT_URL, $this->serverUrl );

    curl_setopt ( $connection, CURLOPT_TIMEOUT, 30 );

    // stop CURL from verifying the peer's certificate
    curl_setopt ( $connection, CURLOPT_SSL_VERIFYPEER, 0 );
    curl_setopt ( $connection, CURLOPT_SSL_VERIFYHOST, 0 );

    // curl_setopt($connection, CURLOPT_HEADER, 1 ); // Uncomment these for debugging
    // curl_setopt($connection, CURLOPT_VERBOSE, true); // Display communication with serve

    curl_setopt ( $connection, CURLOPT_TIMEOUT, 360 );

    // set the headers using the array of headers
    curl_setopt ( $connection, CURLOPT_HTTPHEADER, $headers );

    // set method as POST
    curl_setopt ( $connection, CURLOPT_POST, 1 );

    // set the XML body of the request
    curl_setopt ( $connection, CURLOPT_POSTFIELDS, $requestBody );

    // set it to return the transfer as a string from curl_exec
    curl_setopt ( $connection, CURLOPT_RETURNTRANSFER, 1 );

    // Send the Request
    $response = curl_exec ( $connection );

    // print curl_error($connection) . ": " . $response;

    // close the connection
    curl_close ( $connection );

    // return the response
    return $response;
   }

  /**
   * buildEbayHeaders
   * Generates an array of string to be used as the headers for the HTTP request to eBay
   * Output: String Array of Headers applicable for this call
   */
  function buildEbayHeaders()
   {
    $headers = array ( // Regulates versioning of the XML interface for the API
      'X-EBAY-API-COMPATIBILITY-LEVEL: ' . $this->compatLevel,

      // set the keys
      'X-EBAY-API-DEV-NAME: ' . $this->devID,
      'X-EBAY-API-APP-NAME: ' . $this->appID,
      'X-EBAY-API-CERT-NAME: ' . $this->certID,

      // the name of the call we are requesting
      'X-EBAY-API-CALL-NAME: ' . $this->verb,

      // SiteID must also be set in the Request's XML
      // SiteID = 0 (US) - UK = 3, Canada = 2, Australia = 15, ....
      // SiteID Indicates the eBay site to associate the call with
      'X-EBAY-API-SITEID: ' . $this->siteID
    );

    return $headers;
   }
 }
Code language: PHP (php)

I added classes to encapsulate handling of the specific eBay requests that the plug-in uses. All are derived from a base class I called eBayRequest.

/**
 *  An eBay request
 */
abstract class eBayRequest
 {
  private $requestType;

  /**
    *  @brief Constructor
    *   
    *  @param string $requestType the eBay API request type
    *  @return void
    */
  function __construct($requestType)
   {
    $this->requestType = $requestType;
   }

  /**
    *  @brief getXML - return the XML used to make the API the call
    *  
    *  @return string the XML of the call
    */
  abstract protected function getXML();

  /**
   *  @brief addResults - add results to the list of results
   *  
   *  @param string $xml the output XML from the API call
   *  @param array $results the array to hold the $results
   *  @return array the array of results
   */
  abstract protected function addResults($xml, $results);

  /**
   *  @brief getServerURL - return the URL of the API call
   *  
   *  @return sting the URL
   */
  protected function getServerURL()
   {
    return "https://api.ebay.com/ws/api.dll";
   }

  /**
   *  @brief getResults - make the actual API call and return the results
   *
   *  @param boolean|array - if true, error messages are not logged.  If an array, 
   *                         messages are logged only for errors not in the array 
   *                         of error codes.
   *  
   *  @return array the results
   */
  public function getResults($suppressErrors = false)
   {
    $devID = ebayGetConfiguration ( 'PROD_DEVID' );
    $appID = ebayGetConfiguration ( 'PROD_APPID' );
    $certID = ebayGetConfiguration ( 'PROD_CERTID' );
    $serverUrl = $this->getServerURL ();
    $compatabilityLevel = 705;
    $siteID = 0;
    $verb = $this->requestType;

    $session = new eBaySessionHandler ( $devID, $appID, $certID, $serverUrl, $compatabilityLevel, $siteID, $verb );

    $xml = $this->getXML ();
    
    if (function_exists('eBayModifyRequest'))
      {
        $xml = eBayModifyRequest($verb, $xml);
      }

    $response = $session->sendHttpRequest ( $xml );

    $results = array ();

    $results ['count'] = 0;
    $results ['errorcode'] = '0';
    $results ['errormessage'] = '';
    if (stristr ( $response, 'HTTP 404' ) || $response == '')
     {
      $results ['count'] = 0;
      $results ['status'] = 'Failure';
      $results ['errorcode'] = '999';
      $results ['errorlink']  = 'https://jonrocket.com/zencart/errorcode-' . $results ['errorcode'];
      $results ['errormessage'] = 'HTTP Error';
      
      $message = $verb . ': ' . $results ['errormessage'] . ' {<a href="' . $results['errorlink'] . '">' . $results ['errorcode'] . '</a>)';
      eBayLog($message, true);

      return $results;
     }
      
    $simpleXML = simplexml_load_string ( $response );

    $results ['status'] = ( string ) $simpleXML->Ack;

    if ($results ['status'] != 'Success')
     {
      $results ['errors'] = array ();
      foreach ( $simpleXML->Errors as $error )
       {
        $results ['errorcode'] = ( string ) $error->ErrorCode;
        $results ['errorlink']  = 'https://jonrocket.com/zencart/errorcode-' . $results ['errorcode'];
        $results ['errormessage'] = ( string ) $error->LongMessage;
        
        if (!$suppressErrors) 
          {
            $message = $verb . ': ' . htmlentities($error->LongMessage) . ' {<a href="' . $results ['errorlink'] . '">' . $error->ErrorCode . '</a>)';
            eBayLog($message, true);
          }
        
        
        $results ['errors'] [] = array (
          'errorcode' => ( string ) $error->ErrorCode,
          'errormessage' => $error->LongMessage,
          'errorlink' => $results['errorlink']
        );
       }
      return $results;
     }

    $results = $this->addResults ( $simpleXML, $results );

    return $results;
   }
 }
 
Code language: PHP (php)

The code for a specific request is derived from the eBayRequest class. For example, to get your recent eBay orders, a GetOrders request is made to eBay’s Trading API service.

/**
 *  GetOrders Request
 *  
 *  As a side-effect, executing this call will update the store
 *  quantities based on items sold on eBay.
 */
class eBayGetOrdersRequest extends eBayRequest
 {
  var $from;
  var $to;
  var $role;

  function __construct($from, $to, $role)
   {
    $this->from = eBayGetUTC8601 ( $from );
    $this->to = eBayGetUTC8601 ( $to );
    $this->role = $role;

    parent::__construct ( 'GetOrders' );
   }

  protected function getXML()
   {
    $authToken = ebayGetConfiguration ( 'AUTH_TOKEN' );

    $request = <<<XML
    
           <?xml version="1.0" encoding="utf-8" ?>
           <GetOrdersRequest xmlns="urn:ebay:apis:eBLBaseComponents">
             <RequesterCredentials>
                <eBayAuthToken>$authToken</eBayAuthToken>
             </RequesterCredentials>
             <CreateTimeFrom>{$this->from}</CreateTimeFrom>
             <CreateTimeTo>{$this->to}</CreateTimeTo>
             <OrderRole>{$this->role}</OrderRole>
             <OrderStatus>Completed</OrderStatus>
             <DetailLevel>ReturnAll</DetailLevel>
           </GetOrdersRequest>
    
XML;

    return $request;
   }

  function addResults($simpleXML, $results)
   {
    $results ['orders'] = array ();
    foreach ( $simpleXML->OrderArray->Order as $order )
     {
      $result = array ();
      $result ['orderid'] = ( string ) $order->OrderID;
      $result ['subtotal'] = floatval ( ( string ) $order->Subtotal );
      $result ['total'] = floatval ( ( string ) $order->Total );
      $result ['buyerid'] = ( string ) $order->BuyerUserID;
      $result ['paidtime'] = date_create ( ( string ) $order->PaidTime );
      $results ['orders'] [] = $result;
      foreach ( $order->TransactionArray->Transaction as $transaction )
       {
         $itemId = $transaction->Item->ItemID;
         $quantity = $transaction->QuantityPurchased;
         $transactionId = $transaction->TransactionID;
         eBayProcessItemSold($itemId, $transactionId, $quantity);
       }
     }
    $results ['count'] = count ( $results ['orders'] );

    return $results;
   }
 }
Code language: PHP (php)

The GetOrders request, like all of the eBay requests starts with creating XML which contains the information to send to eBay’s server. This includes the three IDs used as keys and the authorization token allowing access to the eBay store information.

The XML is sent to eBay’s server using the HTTP protocol. The eBay server returns a response in XML. The GetOrdersRequest class parses the returned XML to get information about the orders.

Leave a Reply

Your email address will not be published. Required fields are marked *