diff --git a/src/Bigcommerce/Api/Client.php b/src/Bigcommerce/Api/Client.php index f01e3152..e871c923 100644 --- a/src/Bigcommerce/Api/Client.php +++ b/src/Bigcommerce/Api/Client.php @@ -57,6 +57,58 @@ class Client * @var string */ static public $api_path; + static private $client_id; + static private $store_hash; + static private $auth_token; + static private $stores_prefix = '/stores/%s/v2'; + static private $api_url = 'https://api.bigcommerce.com'; + static private $login_url = 'https://login.bigcommerce.com'; + + /** + * Configure the API client with the required settings to access + * the API for a store. + * + * Accepts OAuth and (for now!) Basic Auth credentials + * + * @param array $settings + */ + public static function configure($settings) + { + if (isset($settings['client_id'])) { + self::configureOAuth($settings); + } else { + self::configureBasicAuth($settings); + } + } + + /** + * Configure the API client with the required OAuth credentials. + * + * Requires a settings array to be passed in with the following keys: + * + * - client_id + * - auth_token + * - store_hash + * + * @param array $settings + * @throws \Exception + */ + public static function configureOAuth($settings) + { + if (!isset($settings['auth_token'])) { + throw new Exception("'auth_token' must be provided"); + } + + if (!isset($settings['store_hash'])) { + throw new Exception("'store_hash' must be provided"); + } + + self::$client_id = $settings['client_id']; + self::$auth_token = $settings['auth_token']; + self::$store_hash = $settings['store_hash']; + self::$api_path = self::$api_url . sprintf(self::$stores_prefix, self::$store_hash); + self::$connection = false; + } /** * Configure the API client with the required credentials. @@ -70,7 +122,7 @@ class Client * @param array $settings * @throws \Exception */ - public static function configure(array $settings) + public static function configureBasicAuth(array $settings) { if (!isset($settings['store_url'])) { throw new Exception("'store_url' must be provided"); @@ -162,7 +214,11 @@ private static function connection() { if (!self::$connection) { self::$connection = new Connection(); - self::$connection->authenticate(self::$username, self::$api_key); + if (self::$client_id) { + self::$connection->authenticateOauth(self::$client_id, self::$auth_token); + } else { + self::$connection->authenticateBasic(self::$username, self::$api_key); + } } return self::$connection; @@ -342,6 +398,21 @@ private static function mapCount($object) return $object->count; } + /** + * Swaps a temporary access code for a long expiry auth token. + * + * @param \stdClass $object + * @return \stdClass + */ + public static function getAuthToken($object) + { + $context = array_merge(array('grant_type' => 'authorization_code'), (array)$object); + $connection = new Connection(); + $connection->useUrlEncoded(); + + return $connection->post(self::$login_url . '/oauth2/token', $context); + } + /** * Pings the time endpoint to test the connection to a store. * diff --git a/src/Bigcommerce/Api/Connection.php b/src/Bigcommerce/Api/Connection.php index 84bdb198..12fb659e 100644 --- a/src/Bigcommerce/Api/Connection.php +++ b/src/Bigcommerce/Api/Connection.php @@ -7,6 +7,18 @@ */ class Connection { + /** + * XML media type. + */ + const MEDIA_TYPE_XML = 'application/xml'; + /** + * JSON media type. + */ + const MEDIA_TYPE_JSON = 'application/json'; + /** + * Default urlencoded media type. + */ + const MEDIA_TYPE_WWW = 'application/x-www-form-urlencoded'; /** * @var resource cURL resource @@ -60,15 +72,19 @@ class Connection /** * Deal with failed requests if failOnError is not set. - * @var string | false + * @var string|false */ private $lastError = false; /** - * Determines whether requests and responses should be treated - * as XML. Defaults to false (using JSON). + * Determines whether the response body should be returned as a raw string. */ - private $useXml = false; + private $rawResponse = false; + + /** + * Determines the default content type to use with requests and responses. + */ + private $contentType; /** * Initializes the connection object. @@ -96,7 +112,23 @@ public function __construct() */ public function useXml($option = true) { - $this->useXml = $option; + if ($option) { + $this->contentType = self::MEDIA_TYPE_XML; + $this->rawResponse = true; + } + } + + /** + * Controls whether requests or responses should be treated + * as urlencoded form data. + * + * @param bool $option the new state of this feature + */ + public function useUrlEncoded($option = true) + { + if ($option) { + $this->contentType = self::MEDIA_TYPE_WWW; + } } /** @@ -125,11 +157,23 @@ public function failOnError($option = true) * @param string $username * @param string $password */ - public function authenticate($username, $password) + public function authenticateBasic($username, $password) { curl_setopt($this->curl, CURLOPT_USERPWD, "$username:$password"); } + /** + * Sets Oauth authentication headers + * + * @param string $clientId + * @param string $authToken + */ + public function authenticateOauth($clientId, $authToken) + { + $this->addHeader('X-Auth-Client', $clientId); + $this->addHeader('X-Auth-Token', $authToken); + } + /** * Set a default timeout for the request. The client will error if the * request takes longer than this to respond. @@ -168,6 +212,9 @@ public function verifyPeer($option = false) /** * Add a custom header to the request. + * + * @param string $header + * @param string $value */ public function addHeader($header, $value) { @@ -176,6 +223,7 @@ public function addHeader($header, $value) /** * Remove a header from the request. + * * @param string $header */ public function removeHeader($header) @@ -185,10 +233,12 @@ public function removeHeader($header) /** * Get the MIME type that should be used for this request. + * + * Defaults to application/json */ private function getContentType() { - return ($this->useXml) ? 'application/xml' : 'application/json'; + return ($this->contentType) ? $this->contentType : self::MEDIA_TYPE_JSON; } /** @@ -197,7 +247,6 @@ private function getContentType() */ private function initializeRequest() { - $this->isComplete = false; $this->responseBody = ''; $this->responseHeaders = array(); $this->lastError = false; @@ -222,7 +271,7 @@ private function handleResponse() throw new NetworkError(curl_error($this->curl), curl_errno($this->curl)); } - $body = ($this->useXml) ? $this->getBody() : json_decode($this->getBody()); + $body = ($this->rawResponse) ? $this->getBody() : json_decode($this->getBody()); $status = $this->getStatus(); @@ -481,6 +530,8 @@ public function getBody() /** * Access given header from the response. * + * @param string $header Header name to retrieve + * * @return string|void */ public function getHeader($header)