Created
April 11, 2014 12:51
-
-
Save piwi91/10466101 to your computer and use it in GitHub Desktop.
ExactOnline PHP API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* | |
* This file contains a class which can be used to connect with the Exact Online API | |
*/ | |
namespace ExactOnlineApi; | |
use \ExactOnlineApi\ApiException; | |
class API | |
{ | |
/** | |
* @var string | |
*/ | |
private $baseurl; | |
/** | |
* @var string | |
*/ | |
private $username; | |
/** | |
* @var string | |
*/ | |
private $password; | |
/** | |
* @var string | |
*/ | |
private $applicationKey; | |
/** | |
* @var string | |
*/ | |
private $division; | |
/** | |
* @var string | |
*/ | |
private $cookiefile; | |
/** | |
* @var string | |
*/ | |
private $crtBundleFile; | |
/** | |
* @var string | |
*/ | |
private $endpoint; | |
/** | |
* @var string | |
*/ | |
private $xml; | |
/** | |
* @var array | |
*/ | |
private $endpointParameters = array(); | |
/** | |
* @var resource | |
*/ | |
private $curl; | |
/** | |
* @var string | |
*/ | |
private $curlData; | |
/** | |
* @var string | |
*/ | |
private $url; | |
/** | |
* Constructs the Exact Online API class | |
* If all parameters are given, the constructor initializes a Curl instance | |
* It's possible to do this manual to provide all parameters with the set methods and then call $this->init() | |
* | |
* @param string $baseUrl | |
* @param string $username | |
* @param string $password | |
* @param string $applicationKey | |
* @param string $division | |
* @param string $cookieFile | |
* @param string $crtBundleFile | |
*/ | |
function __construct( | |
$baseUrl = "https://start.exactonline.nl", | |
$username = "", | |
$password = "", | |
$applicationKey = "", | |
$division = "", | |
$cookieFile = "", | |
$crtBundleFile = "" | |
) | |
{ | |
// Set all properties if not empty | |
if (!empty($baseUrl)) { | |
$this->setBaseurl($baseUrl); | |
} | |
if (!empty($username)) { | |
$this->setUsername($username); | |
} | |
if (!empty($password)) { | |
$this->setPassword($password); | |
} | |
if (!empty($applicationKey)) { | |
$this->setApplicationKey($applicationKey); | |
} | |
if (!empty($division)) { | |
$this->setDivision($division); | |
} | |
if (!empty($cookieFile)) { | |
$this->setCookiefile($cookieFile); | |
} | |
if (!empty($crtBundleFile)) { | |
$this->setCrtBundleFile($crtBundleFile); | |
} | |
// Check if all properties exists | |
// If all properties exist, initialize Curl and set the division | |
if ( | |
!empty($baseUrl) && | |
!empty($username) && | |
!empty($password) && | |
!empty($applicationKey) && | |
!empty($division) && | |
!empty($cookieFile) && | |
!empty($crtBundleFile) | |
) { | |
$this->init(); | |
} | |
} | |
function __destruct() | |
{ | |
if ($this->isInit()) { | |
$ch = $this->getCurl(); | |
curl_close($ch); | |
} | |
} | |
/** | |
* Initialize the Exact Online API | |
* This method initializes a CURL instance and saves it in the private $curl variable. | |
* Other methods can retrieve this CURL instance by calling $this->getCurl(). | |
* This method should called only once | |
* | |
* @throws \ApiException | |
*/ | |
public function init() | |
{ | |
// Check if the curl object isn't set already | |
if ($this->isInit()) { | |
throw new \ExactOnlineApi\ApiException("A Curl instance is already initialized"); | |
} | |
// Check if all needed properties are set | |
if ($this->getCookiefile() == null || $this->getCrtBundleFile() == null || $this->getUsername() == null || $this->getPassword() == null) { | |
throw new \ExactOnlineApi\ApiException("Not all properties are set: cookieFile, crtBundleFile, username or password"); | |
} | |
// Define headers | |
$header[1] = "Cache-Control: private"; | |
$header[2] = "Connection: Keep-Alive"; | |
// Initialize Curl | |
$ch = curl_init(); | |
// Use POST instead of GET | |
curl_setopt($ch, CURLOPT_POST, 1); | |
// Set the HTTP header | |
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); | |
// Expect returndata | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
// Set cookiefile for sessiondata | |
curl_setopt($ch, CURLOPT_COOKIEJAR, $this->getCookiefile()); | |
// Set crtBundleFile (certificate) | |
curl_setopt($ch, CURLOPT_CAINFO, $this->getCrtBundleFile()); | |
// Define _UserName_ and _Password_ post fields | |
curl_setopt($ch, CURLOPT_POSTFIELDS, array ( | |
"_UserName_" => $this->getUsername(), | |
"_Password_" => $this->getPassword() | |
)); | |
// Save Curl object in the class so it can be used by other methods | |
$this->setCurl($ch); | |
} | |
/** | |
* Call the Exact Online API with an endpoint | |
*/ | |
public function callEndpoint($sendApplicationKey = true) | |
{ | |
$ch = $this->prepareCall($sendApplicationKey); | |
// Execute | |
$data = curl_exec($ch); | |
$this->finishCall($ch, $data); | |
} | |
/** | |
* Call the Exact Online API with an endpoint and upload XML data | |
*/ | |
public function callUploadEndpoint($sendApplicationKey = true) | |
{ | |
$ch = $this->prepareCall($sendApplicationKey); | |
// set XML in the postfields | |
curl_setopt($ch, CURLOPT_POSTFIELDS, utf8_encode($this->getXml())); | |
// Execute | |
$data = curl_exec($ch); | |
$this->finishCall($ch, $data); | |
} | |
public function getCurlDataAsObject() | |
{ | |
return new \SimpleXMLElement($this->getCurlData()); | |
} | |
/** | |
* Finishes the call and set the data or throws an exception if the request was not OK | |
* | |
* @param $ch | |
* @param $data | |
* @throws ApiException | |
*/ | |
private function finishCall($ch, $data) | |
{ | |
// Reset endpoint parameters | |
$this->setEndpointParameters(array()); | |
// Get HTTP status code from Curl | |
$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
// Check if the HTTP code is 200, else throw exception | |
if ($httpStatus == 200) { | |
// If HTTP code is 200, set the data in $this->curlData; | |
$this->setCurlData($data); | |
} else { | |
throw new \ExactOnlineApi\ApiException( | |
"HTTP status is not OK!<br />Url: " . | |
$this->getUrl() . | |
"<br />Status: " . $httpStatus, | |
$data, | |
$httpStatus | |
); | |
} | |
} | |
/** | |
* Prepares the call and sets the endpoint URL | |
* | |
* @return resource | |
*/ | |
private function prepareCall($sendApplicationKey) | |
{ | |
// Check if the curl object is set | |
if (!$this->isInit()) { | |
// If it isn't, we do it right now | |
$this->init(); | |
} | |
// Get Curl object | |
$ch = $this->getCurl(); | |
$parameters = $this->getEndpointParameters(); | |
if ($sendApplicationKey) { | |
$parameters = array("ApplicationKey" => $this->getApplicationKey()) + $parameters; | |
} | |
$url = vsprintf('%s/docs/%s?%s', array ( | |
$this->getBaseurl(), | |
$this->getEndpoint(), | |
http_build_query($parameters) | |
)); | |
$this->setUrl($url); | |
// Set full URL in Curl | |
curl_setopt($ch, CURLOPT_URL, $url); | |
return $ch; | |
} | |
/** | |
* Returns if Curl is initialized or not | |
* | |
* @return bool | |
*/ | |
private function isInit() | |
{ | |
if ($this->getCurl() != null) { | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Remove BOM from returned data | |
* | |
* @param string $xml | |
* @return string | |
*/ | |
private function removeBOM($xml) | |
{ | |
return preg_replace('/\x{EF}\x{BB}\x{BF}/', '', $xml); | |
} | |
// GETTERS AND SETTERS | |
/** | |
* @param string $applicationKey | |
*/ | |
public function setApplicationKey($applicationKey) | |
{ | |
$this->applicationKey = $applicationKey; | |
} | |
/** | |
* @return string | |
*/ | |
public function getApplicationKey() | |
{ | |
return $this->applicationKey; | |
} | |
/** | |
* @param string $baseurl | |
*/ | |
public function setBaseurl($baseurl) | |
{ | |
$this->baseurl = $baseurl; | |
} | |
/** | |
* @return string | |
*/ | |
public function getBaseurl() | |
{ | |
return $this->baseurl; | |
} | |
/** | |
* @param string $cookiefile | |
*/ | |
public function setCookiefile($cookiefile) | |
{ | |
$this->cookiefile = $cookiefile; | |
} | |
/** | |
* @return string | |
*/ | |
public function getCookiefile() | |
{ | |
return $this->cookiefile; | |
} | |
/** | |
* @param string $crtBundleFile | |
*/ | |
public function setCrtBundleFile($crtBundleFile) | |
{ | |
$this->crtBundleFile = $crtBundleFile; | |
} | |
/** | |
* @return string | |
*/ | |
public function getCrtBundleFile() | |
{ | |
return $this->crtBundleFile; | |
} | |
/** | |
* @param string $division | |
*/ | |
public function setDivision($division) | |
{ | |
$this->division = $division; | |
} | |
/** | |
* @return string | |
*/ | |
public function getDivision() | |
{ | |
return $this->division; | |
} | |
/** | |
* @param string $password | |
*/ | |
public function setPassword($password) | |
{ | |
$this->password = $password; | |
} | |
/** | |
* @return string | |
*/ | |
public function getPassword() | |
{ | |
return $this->password; | |
} | |
/** | |
* @param string $username | |
*/ | |
public function setUsername($username) | |
{ | |
$this->username = $username; | |
} | |
/** | |
* @return string | |
*/ | |
public function getUsername() | |
{ | |
return $this->username; | |
} | |
/** | |
* @param resource $curl | |
*/ | |
public function setCurl($curl) | |
{ | |
$this->curl = $curl; | |
} | |
/** | |
* @return resource | |
*/ | |
public function getCurl() | |
{ | |
return $this->curl; | |
} | |
/** | |
* @param string $curlData | |
*/ | |
public function setCurlData($curlData) | |
{ | |
$this->curlData = $this->removeBOM($curlData); | |
} | |
/** | |
* @return string | |
*/ | |
public function getCurlData() | |
{ | |
return $this->curlData; | |
} | |
/** | |
* @param string $endpoint | |
*/ | |
public function setEndpoint($endpoint) | |
{ | |
$this->endpoint = $endpoint; | |
} | |
/** | |
* @return string | |
*/ | |
public function getEndpoint() | |
{ | |
return $this->endpoint; | |
} | |
/** | |
* @param string $xml | |
*/ | |
public function setXml($xml) | |
{ | |
$this->xml = $xml; | |
} | |
/** | |
* @return string | |
*/ | |
public function getXml() | |
{ | |
return $this->xml; | |
} | |
/** | |
* @param array $endpointParameters | |
*/ | |
public function setEndpointParameters($endpointParameters) | |
{ | |
$this->endpointParameters = $endpointParameters; | |
} | |
/** | |
* @return array | |
*/ | |
public function getEndpointParameters() | |
{ | |
return $this->endpointParameters; | |
} | |
/** | |
* @param string $url | |
*/ | |
public function setUrl($url) | |
{ | |
$this->url = $url; | |
} | |
/** | |
* @return string | |
*/ | |
public function getUrl() | |
{ | |
return $this->url; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* | |
* This file contains a custom exception for ExactOnlineAPI | |
*/ | |
namespace ExactOnlineApi; | |
class ApiException extends \Exception | |
{ | |
/** | |
* @var string | |
*/ | |
protected $apiData; | |
function __construct($message = "", $apiData = "", $code = 0, Exception $previous = null) | |
{ | |
$this->apiData = $apiData; | |
parent::__construct($message, $code, $previous); | |
} | |
/** | |
* @return string | |
*/ | |
public function getApiData() | |
{ | |
return $this->apiData; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace ExactOnlineApi; | |
try { | |
// Init ExactOnlineApi class and provide all properties | |
// The constructor will init a Curl instance and set the divison | |
$exactOnlineApi = new \ExactOnlineApi\API( | |
$baseurl, | |
$username, | |
$password, | |
$applicationkey, | |
$division, | |
$cookiefile, | |
$crtbundlefile | |
); | |
// First set the division | |
$exactOnlineApi->setEndpoint("ClearSession.aspx"); | |
$exactOnlineApi->setEndpointParameters(array( | |
"Division" => $division, | |
"Remember" => 3 | |
)); | |
$exactOnlineApi->callEndpoint(false); | |
// Retrieve item | |
$exactOnlineApi->setEndpoint("XMLDownload.aspx"); | |
$exactOnlineApi->setEndpointParameters(array( | |
"Topic" => "Items", | |
"Params_AssortmentCode" => "01" | |
)); | |
$exactOnlineApi->callEndpoint(); | |
$xmlObject = $exactOnlineApi->getCurlDataAsObject(); | |
} catch (\ExactOnlineApi\ApiException $e) { | |
echo "<h3>ApiException occurred</h3>"; | |
echo "<div class=\"message\">" . $e->getMessage() . "</div>"; | |
echo "<pre class='prettyprint lang-xml linenums'>".htmlentities($e->getApiData())."</pre>"; | |
die; | |
} |
Based on the older XML version..... I have a working version....
Do you have something with the new Oauth Rest API ?
I'm sorry I didn't reply earlier but I didn't received any notifications on your replies. @MHermsen I don't have a REST API implementation for Exact online yet. Maybe in the near future :-) PM me if your interested to contribute.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, these examples are not working but i'm very interested in a PHP Class for exact online to connect our websites with exact online software.
Can you help me with this? (contact me at info at xis.be to negotiate agreement/price)