├── .gitignore ├── LICENSE ├── README.md ├── composer.json └── src └── Foxy └── FoxyClient └── FoxyClient.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | vendor/ 3 | 4 | # Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file 5 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 6 | # composer.lock 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 FoxyCart, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FoxyClient PHP 2 | FoxyClient - a PHP Guzzle based API Client for working with the Foxy Hypermedia API 3 | 4 | Please see the Foxy Hypermedia API documentation for more information. 5 | 6 | ## Installation 7 | 8 | The best way to get started with FoxyClient is to run the foxyclient-php-example code. 9 | 10 | Once you're familiar with how it works, you can add it as a composer package to your application as the example code does or via Packagist: 11 | 12 | * Install Composer 13 | 14 | `curl -sS https://getcomposer.org/installer | php` 15 | 16 | * Add to your project 17 | 18 | `php composer.phar require foxycart/foxyclient:~1.0` 19 | 20 | If you need Guzzle 6 instead of Guzzle 5, use: 21 | 22 | `php composer.phar require foxycart/foxyclient:~2.0` 23 | 24 | ## Usage 25 | 26 | As mentioned above, begin by getting familiar with the example code. The bootstrap.php file in particular is useful for configuring FoxyClient within your application. Please note how it takes advantage of HTTP caching and CSRF protection which are important for the performance and security of your application. 27 | 28 | FoxyClient supports all HTTP methods for our Hypermedia API. It also automatically handles OAuth token refreshes and handles authorization code grants. It does not specify a persistance layer for storing OAuth tokens so you can implement that however you want. You can also support a static service with no database which would only use the client_id, client_secret, and refresh_token to obtain a new access_token as needed. 29 | 30 | ## Tests 31 | 32 | For Behat tests, please see the the example code. 33 | 34 | ### Config Options 35 | * use_sandbox: Set to true to work with https://api-sandbox.foxycart.com. This is highly recomended when first getting familiar with the system (defaults to false). 36 | * client_id: Your OAuth Client id. 37 | * client_secret: Your OAuth Client Secret. 38 | * access_token: Your OAuth Acccess Token. 39 | * access_token_expires: A timestamp for when the access_token needs to be refreshed. If you happen to already have a stored token, you can set this here. It will be maintained via time() + expires_in. 40 | * refresh_token: OAuth Refresh Token. 41 | * handle_exceptions: Defaults to true. Set to false to let Guzzle exceptions bubble up to your application so you can handle them directly. 42 | * api_home: Used internally for Foxy testing. 43 | * authorization_endpoint: Used internally for Foxy testing. 44 | 45 | ### HTTP methods 46 | * get($uri, $post = null) 47 | * post($uri, $post = null) 48 | * patch($uri, $post = null) 49 | * put($uri, $post = null) 50 | * delete($uri, $post = null) 51 | * options($uri, $post = null) 52 | * head($uri, $post = null) 53 | 54 | ### API Methods 55 | * updateFromConfig($config): Update configuration options via an array 56 | * clearCredentials(): Clear all credentials so you can connect to the API with no OAuth 57 | * getLink($link_rel_string): Used to get the href of a given link relationship such as "self" or "fx:store". It also supports the short version of just "store". 58 | * getLinks(): Returns an array of link relationships the client has seen so far in the rel => href format. Each request stores the links in the links array. 59 | * clearLinks(): Clear saved links from previous API calls. Helpful for link relationships like "checkout_types" which can be returned from both a store resource and as a property helper. 60 | * setAccessToken($access_token) / getAccessToken(): OAuth access token 61 | * setAccessTokenExpires($access_token_expires) / getAccessTokenExpires(): OAuth expiration times 62 | * setRefreshToken($refresh_token) / getRefreshToken(): OAuth refresh token 63 | * setClientId($client_id) / getClientId(): OAuth client id 64 | * setClientSecret($client_secret) / getClientSecret(): OAuth client secret 65 | * setUseSandbox($use_sandbox) / getUseSandbox(): boolean for connecting to the API sandbox 66 | * getApiHome(): the API starting homepage 67 | * getErrors($data): Given a response payload, it will normalize errors and return an array of them (or any empty array). 68 | * getLastStatusCode(): Returns the last HTTP status code. 69 | * getLastResponseHeader($header): Get a header (such as "Location") from the previous response. 70 | * setAcceptContentType($accept_content_type): Set the Accept header content type used for the all future requests. All supported json content types on the FoxyCart API are supported such as application/hal+json and application/vnd.siren+json. 71 | * getAcceptContentType(): get the Accept header content type 72 | * getAuthorizationEndpoint(): The Authorization Code Grant server endpoint url. You'll need to forward users to this to let them grant your application access to their store or user. 73 | * getOAuthTokenEndpoint(): The OAuth token endpoint. Note: you shouldn't have to use this as the library takes care of all OAuth functionality for you. 74 | * getAccessTokenFromAuthorizationCode($code): Used when returning from our Authorization server in order to obtain an access_token and refresh_token. 75 | * getAccessTokenFromClientCredentials(): If we don't have a refresh token, we can use this method to obtain an access_token using just the client credentials. 76 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foxycart/foxyclient", 3 | "description": "FoxyClient - a PHP Guzzle based API Client for working with the Foxy Hypermedia API ", 4 | "type": "library", 5 | "homepage": "https://github.com/FoxyCart/foxyclient-php", 6 | "license": "MIT", 7 | "keywords": ["foxy","foxycart","hypermedia"], 8 | "authors": [ 9 | { 10 | "name": "Luke Stokes", 11 | "email": "luke.stokes@foxy.io", 12 | "homepage": "http://www.foxy.io/", 13 | "role": "Developer" 14 | } 15 | ], 16 | "require": { 17 | "guzzlehttp/guzzle": "~5.2", 18 | "guzzlehttp/cache-subscriber": "0.1.*@dev", 19 | "php": ">=5.3.3" 20 | }, 21 | "autoload": { 22 | "psr-0": {"Foxy\\FoxyClient": "src/"} 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Foxy/FoxyClient/FoxyClient.php: -------------------------------------------------------------------------------- 1 | get(); 17 | die("
" . print_r($result, 1) . ""); 18 | 19 | //Get Authenticated Store 20 | $fc = new FoxyClient($guzzle, array( 21 | 'client_id' => $client_id, 22 | 'client_secret' => $client_secret, 23 | 'refresh_token' => $refresh_token, 24 | 'access_token' => $access_token, // optional 25 | 'access_token_expires' => $access_token_expires // optional 26 | ) 27 | ); 28 | $fc->get(); 29 | $result = $fc->get($fc->getLink("fx:store")); 30 | die("
" . print_r($result, 1) . ""); 31 | 32 | Credits: David Hollander of https://foxytools.com/ got this project going and is awesome. 33 | */ 34 | class FoxyClient 35 | { 36 | const PRODUCTION_API_HOME = 'https://api.foxycart.com'; 37 | const SANDBOX_API_HOME = 'https://api-sandbox.foxycart.com'; 38 | const LINK_RELATIONSHIPS_BASE_URI = 'https://api.foxycart.com/rels/'; 39 | const PRODUCTION_AUTHORIZATION_ENDPOINT = 'https://my.foxycart.com/authorize'; 40 | const SANDBOX_AUTHORIZATION_ENDPOINT = 'https://my-sandbox.foxycart.com/authorize'; 41 | const DEFAULT_ACCEPT_CONTENT_TYPE = 'application/hal+json'; 42 | 43 | /** 44 | * OAuth Access Token (can have various scopes such as client_full_access, user_full_access, store_full_access) 45 | */ 46 | private $access_token = ''; 47 | /** 48 | * The timestamp for when the access token expires 49 | */ 50 | private $access_token_expires = 0; 51 | /** 52 | * OAuth Refresh token used to obtain a new Access Token 53 | */ 54 | private $refresh_token = ''; 55 | /** 56 | * OAuth endpoint for getting a new Access Token 57 | */ 58 | private $oauth_token_endpoint = ''; 59 | /** 60 | * Used by OAuth for getting a new Access Token 61 | */ 62 | private $client_id = ''; 63 | /** 64 | * Used by OAuth for getting a new Access Token 65 | */ 66 | private $client_secret = ''; 67 | 68 | private $guzzle; 69 | private $last_response = ''; 70 | private $registered_link_relations = array('self', 'first', 'prev', 'next', 'last'); 71 | private $links = array(); 72 | private $use_sandbox = false; 73 | private $obtaining_updated_access_token = false; 74 | private $include_auth_header = true; 75 | private $handle_exceptions = true; 76 | private $accept_content_type = ''; 77 | private $api_home = ''; 78 | private $authorization_endpoint = ''; 79 | 80 | public function __construct(\GuzzleHttp\Client $guzzle, array $config = array()) 81 | { 82 | $this->guzzle = $guzzle; 83 | $this->api_home = static::PRODUCTION_API_HOME; 84 | $this->authorization_endpoint = static::PRODUCTION_AUTHORIZATION_ENDPOINT; 85 | $this->updateFromConfig($config); 86 | } 87 | 88 | public function updateFromConfig($config) 89 | { 90 | $valid_config_options = array( 91 | 'api_home', 92 | 'authorization_endpoint', 93 | 'use_sandbox', 94 | 'access_token', 95 | 'access_token_expires', 96 | 'refresh_token', 97 | 'client_id', 98 | 'client_secret', 99 | 'handle_exceptions' 100 | ); 101 | foreach($valid_config_options as $valid_config_option) { 102 | if (array_key_exists($valid_config_option, $config)) { 103 | $this->{$valid_config_option} = $config[$valid_config_option]; 104 | } 105 | } 106 | if ($this->use_sandbox && (!array_key_exists('api_home', $config) || !array_key_exists('authorization_endpoint', $config))) { 107 | $this->api_home = static::SANDBOX_API_HOME; 108 | $this->authorization_endpoint = static::SANDBOX_AUTHORIZATION_ENDPOINT; 109 | } 110 | } 111 | 112 | public function clearCredentials() 113 | { 114 | $config = array( 115 | 'access_token' => '', 116 | 'access_token_expires' => '', 117 | 'refresh_token' => '', 118 | 'client_id' => '', 119 | 'client_secret' => '' 120 | ); 121 | $this->updateFromConfig($config); 122 | } 123 | 124 | public function setAccessToken($access_token) 125 | { 126 | $this->access_token = $access_token; 127 | } 128 | public function getAccessToken() 129 | { 130 | return $this->access_token; 131 | } 132 | 133 | public function setAccessTokenExpires($access_token_expires) 134 | { 135 | $this->access_token_expires = $access_token_expires; 136 | } 137 | public function getAccessTokenExpires() 138 | { 139 | return $this->access_token_expires; 140 | } 141 | 142 | public function setRefreshToken($refresh_token) 143 | { 144 | $this->refresh_token = $refresh_token; 145 | } 146 | public function getRefreshToken() 147 | { 148 | return $this->refresh_token; 149 | } 150 | 151 | public function setClientId($client_id) 152 | { 153 | $this->client_id = $client_id; 154 | } 155 | public function getClientId() 156 | { 157 | return $this->client_id; 158 | } 159 | 160 | public function setClientSecret($client_secret) 161 | { 162 | $this->client_secret = $client_secret; 163 | } 164 | public function getClientSecret() 165 | { 166 | return $this->client_secret; 167 | } 168 | 169 | public function setUseSandbox($use_sandbox) 170 | { 171 | $this->use_sandbox = $use_sandbox; 172 | } 173 | public function getUseSandbox() 174 | { 175 | return $this->use_sandbox; 176 | } 177 | 178 | public function getApiHome() 179 | { 180 | return $this->api_home; 181 | } 182 | 183 | public function getAuthorizationEndpoint() 184 | { 185 | return $this->authorization_endpoint; 186 | } 187 | 188 | public function get($uri = "", $post = null) 189 | { 190 | return $this->go('GET', $uri, $post); 191 | } 192 | 193 | public function put($uri, $post = null) 194 | { 195 | return $this->go('PUT', $uri, $post); 196 | } 197 | 198 | public function post($uri, $post = null) 199 | { 200 | return $this->go('POST', $uri, $post); 201 | } 202 | 203 | public function patch($uri, $post = null) 204 | { 205 | return $this->go('PATCH', $uri, $post); 206 | } 207 | 208 | public function delete($uri, $post = null) 209 | { 210 | return $this->go('DELETE', $uri, $post); 211 | } 212 | 213 | public function options($uri, $post = null) 214 | { 215 | return $this->go('OPTIONS', $uri, $post); 216 | } 217 | 218 | public function head($uri, $post = null) 219 | { 220 | return $this->go('HEAD', $uri, $post); 221 | } 222 | 223 | private function go($method, $uri, $post, $is_retry = false) 224 | { 225 | if (!$this->obtaining_updated_access_token) { 226 | $this->refreshTokenAsNeeded(); 227 | } 228 | 229 | //Nothing passed in, set uri to homepage 230 | if (!$uri) { 231 | $uri = $this->getApiHome(); 232 | } 233 | 234 | //Setup Guzzle Details 235 | $guzzle_args = array( 236 | 'headers' => $this->getHeaders(), 237 | 'connect_timeout' => 30, 238 | ); 239 | 240 | //Set Query or Body 241 | if ($method === "GET" && $post !== null) { 242 | $guzzle_args['query'] = $post; 243 | } elseif ($post !== null) { 244 | $guzzle_args['body'] = $post; 245 | } 246 | 247 | if (!$this->handle_exceptions) { 248 | return $this->processRequest($method, $uri, $post, $guzzle_args, $is_retry); 249 | } else { 250 | try { 251 | return $this->processRequest($method, $uri, $post, $guzzle_args, $is_retry); 252 | //Catch Errors - http error 253 | } catch (\GuzzleHttp\Exception\RequestException $e) { 254 | return array("error_description" => $e->getMessage()); 255 | //Catch Errors - not JSON 256 | } catch (\GuzzleHttp\Exception\ParseException $e) { 257 | return array("error_description" => $e->getMessage()); 258 | } 259 | } 260 | } 261 | 262 | private function processRequest($method, $uri, $post, $guzzle_args, $is_retry = false) 263 | { 264 | // special case for PATCHing a Downloadable File 265 | if ($post !== null && is_array($post) && array_key_exists('file', $post) && $method == 'PATCH') { 266 | $method = 'POST'; 267 | $guzzle_args['headers']['X-HTTP-Method-Override'] = 'PATCH'; 268 | } 269 | 270 | $api_request = $this->guzzle->createRequest($method, $uri, $guzzle_args); 271 | $this->last_response = $this->guzzle->send($api_request); 272 | $data = $this->last_response->json(); 273 | $this->saveLinks($data); 274 | if ($this->hasExpiredAccessTokenError($data) && !$this->shouldRefreshToken()) { 275 | if (!$is_retry) { 276 | // we should have gotten a refresh token... looks like our access_token_expires was incorrect 277 | // so we'll clear it out to force a refresh 278 | $this->access_token_expires = 0; 279 | return $this->go($method, $uri, $post, true); // try one more time 280 | } else { 281 | return array("error_description" => 'An error occurred attempting to update your access token. Please verify your refresh token and OAuth client credentials.'); 282 | } 283 | } 284 | return $data; 285 | } 286 | 287 | //Clear any saved links 288 | public function clearLinks() 289 | { 290 | $this->links = array(); 291 | } 292 | 293 | //Save Links to the Object For Easy Retrieval Later 294 | public function saveLinks($data) 295 | { 296 | if (isset($data['_links'])) { 297 | foreach ($data['_links'] as $rel => $link) { 298 | if (!in_array($rel, $this->registered_link_relations) 299 | && $rel != 'curies' 300 | && $rel.'/' != static::LINK_RELATIONSHIPS_BASE_URI) { 301 | $this->links[$rel] = $link['href']; 302 | } 303 | } 304 | } else if (isset($data['links'])) { 305 | foreach ($data['links'] as $link) { 306 | foreach ($link['rel'] as $rel) { 307 | if (!in_array($rel, $this->registered_link_relations) 308 | && $rel.'/' != static::LINK_RELATIONSHIPS_BASE_URI) { 309 | $this->links[$rel] = $link['href']; 310 | } 311 | } 312 | } 313 | } 314 | } 315 | 316 | // Get a link out of the internally stored links 317 | // The link relationship base uri can be excluded ("fx:" for HAL, full URI for Siren) 318 | public function getLink($link_rel_string) 319 | { 320 | $search_string = $link_rel_string; 321 | if (!in_array($link_rel_string, $this->registered_link_relations) 322 | && strpos($link_rel_string, "fx:") === FALSE 323 | && strpos($link_rel_string, static::LINK_RELATIONSHIPS_BASE_URI) === FALSE) { 324 | if ($this->getAcceptContentType() == static::DEFAULT_ACCEPT_CONTENT_TYPE) { 325 | $search_string = 'fx:' . $search_string; 326 | } else { 327 | $search_string = static::LINK_RELATIONSHIPS_BASE_URI . $search_string; 328 | } 329 | } 330 | if (isset($this->links[$search_string])) { 331 | return $this->links[$search_string]; 332 | } else { 333 | return ""; 334 | } 335 | } 336 | 337 | // Get stored links (excluding link rel base uri) 338 | public function getLinks() 339 | { 340 | $links = array(); 341 | foreach($this->links as $rel => $href) { 342 | $simple_rel = $rel; 343 | $base_uris = array("fx:", static::LINK_RELATIONSHIPS_BASE_URI); 344 | foreach($base_uris as $base_uri) { 345 | $pos = strpos($simple_rel, $base_uri); 346 | if ($pos !== FALSE && ($simple_rel.'/' != $base_uri)) { 347 | $simple_rel = substr($simple_rel, strlen($base_uri)); 348 | } 349 | } 350 | $links[$simple_rel] = $href; 351 | } 352 | return $links; 353 | } 354 | 355 | //Return any errors that exist in the response data. 356 | public function getErrors($data) 357 | { 358 | $errors = array(); 359 | if ($this->getLastStatusCode() >= 400) { 360 | if (isset($data['error_description'])) { 361 | $errors[] = $data['error_description']; 362 | } elseif (isset($data['_embedded']['fx:errors'])) { 363 | foreach ($data['_embedded']['fx:errors'] as $error) { 364 | $errors[] = $error['message']; 365 | } 366 | } else { 367 | $errors[] = 'No data returned.'; 368 | } 369 | } 370 | return $errors; 371 | } 372 | 373 | public function hasExpiredAccessTokenError($data) 374 | { 375 | $errors = $this->getErrors($data); 376 | if (in_array('The access token provided has expired', $errors)) { 377 | return true; 378 | } 379 | return false; 380 | } 381 | 382 | // Set a custom supported content type (application/hal+json, application/vnd.siren+json, etc) 383 | public function setAcceptContentType($accept_content_type) 384 | { 385 | $this->accept_content_type = $accept_content_type; 386 | } 387 | 388 | public function getAcceptContentType() 389 | { 390 | if ($this->accept_content_type == '') { 391 | return static::DEFAULT_ACCEPT_CONTENT_TYPE; 392 | } 393 | 394 | return $this->accept_content_type; 395 | } 396 | 397 | //Get headers for this call 398 | public function getHeaders() 399 | { 400 | $headers = array( 401 | 'FOXY-API-VERSION' => 1 402 | ); 403 | if ($this->access_token && $this->include_auth_header) { 404 | $headers['Authorization'] = "Bearer " . $this->access_token; 405 | } 406 | $headers['Accept'] = $this->getAcceptContentType(); 407 | 408 | return $headers; 409 | } 410 | 411 | //Get Last Status Code 412 | public function getLastStatusCode() 413 | { 414 | if ($this->last_response == '') { 415 | return ''; 416 | } 417 | return $this->last_response->getStatusCode(); 418 | } 419 | //Get Last Response Header 420 | public function getLastResponseHeader($header) 421 | { 422 | if ($this->last_response == '') { 423 | return ''; 424 | } 425 | return $this->last_response->getHeader($header); 426 | } 427 | 428 | public function hasOAuthCredentialsForTokenRefresh() 429 | { 430 | return ($this->client_id && $this->client_secret && $this->refresh_token); 431 | } 432 | 433 | public function accessTokenNeedsRefreshing() 434 | { 435 | return (!$this->access_token_expires || (($this->access_token_expires - 30) < time())); 436 | } 437 | 438 | public function shouldRefreshToken() 439 | { 440 | return ($this->hasOAuthCredentialsForTokenRefresh() && $this->accessTokenNeedsRefreshing()); 441 | } 442 | 443 | public function obtainingToken() 444 | { 445 | $this->obtaining_updated_access_token = true; 446 | $this->include_auth_header = false; 447 | } 448 | 449 | public function obtainingTokenDone() 450 | { 451 | $this->obtaining_updated_access_token = false; 452 | $this->include_auth_header = true; 453 | } 454 | 455 | public function refreshTokenAsNeeded() 456 | { 457 | if ($this->shouldRefreshToken()) { 458 | $refresh_token_data = array( 459 | 'grant_type' => 'refresh_token', 460 | 'refresh_token' => $this->refresh_token, 461 | 'client_id' => $this->client_id, 462 | 'client_secret' => $this->client_secret 463 | ); 464 | $this->obtainingToken(); 465 | $data = $this->post($this->getOAuthTokenEndpoint(),$refresh_token_data); 466 | $this->obtainingTokenDone(); 467 | if ($this->getLastStatusCode() == '200') { 468 | $this->access_token_expires = time() + $data['expires_in']; 469 | $this->access_token = $data['access_token']; 470 | } 471 | } 472 | } 473 | 474 | public function getAccessTokenFromClientCredentials() 475 | { 476 | $client_credentials_request_data = array( 477 | 'grant_type' => 'client_credentials', 478 | 'scope' => 'client_full_access', 479 | 'client_id' => $this->client_id, 480 | 'client_secret' => $this->client_secret 481 | ); 482 | $this->obtainingToken(); 483 | $data = $this->post($this->getOAuthTokenEndpoint(),$client_credentials_request_data); 484 | $this->obtainingTokenDone(); 485 | if ($this->getLastStatusCode() == '200') { 486 | $this->access_token_expires = time() + $data['expires_in']; 487 | $this->access_token = $data['access_token']; 488 | } 489 | return $data; 490 | } 491 | 492 | public function getAccessTokenFromAuthorizationCode($code) 493 | { 494 | $authorize_code_request_data = array( 495 | 'grant_type' => 'authorization_code', 496 | 'code' => $code, 497 | 'client_id' => $this->client_id, 498 | 'client_secret' => $this->client_secret 499 | ); 500 | $this->obtainingToken(); 501 | $data = $this->post($this->getOAuthTokenEndpoint(),$authorize_code_request_data); 502 | $this->obtainingTokenDone(); 503 | if ($this->getLastStatusCode() == '200') { 504 | $this->access_token_expires = time() + $data['expires_in']; 505 | $this->access_token = $data['access_token']; 506 | $this->refresh_token = $data['refresh_token']; 507 | } 508 | return $data; 509 | } 510 | 511 | public function getOAuthTokenEndpoint() 512 | { 513 | if ($this->oauth_token_endpoint == '') { 514 | $this->obtainingToken(); 515 | $data = $this->get(); 516 | if ($this->getLastStatusCode() == '200') { 517 | $this->oauth_token_endpoint = $this->getLink("token"); 518 | } else { 519 | trigger_error('ERROR IN getOAuthTokenEndpoint: ' . $this->getLastStatusCode()); 520 | //trigger_error(serialize($this->last_response->json())); 521 | //die or hard code the endpoint? 522 | $this->oauth_token_endpoint = $this->api_home . '/token'; 523 | } 524 | } 525 | return $this->oauth_token_endpoint; 526 | } 527 | 528 | } 529 | --------------------------------------------------------------------------------