Files
grzanieplus.pl/plugins/stAllegroPlugin/lib/rest/AllegroRestApi.class.php
2025-03-12 17:06:23 +01:00

550 lines
15 KiB
PHP

<?php
/**
* Object PHP interface for Allegro REST API
*
* This class allows you to call any resource
* with correct request
*
* It also implements some features which
* will save you a lot of time
*
* Example:
* <pre>
* // Register your application here:
* // https://apps.developer.allegro.pl
*
* // Creating auth URL using client id and redirect_uri
* var_dump(
* AllegroRestApi::getAuthLink($clientId, $redirectUri)
* );
*
* // After clicking the link and granting permission you
* // will be redirected to $redirectUri with "code"
* //
* // Use given code to finally generate access token
* $tokens = AllegroRestApi::generateToken(
* $_GET['code'],
* $clientId,
* $clientSecret,
* $redirectUri
* );
*
* // Above token will be active for 12 hours and you can
* // refresh it indefinitely (in example using cron)
* AllegroRestApi::refreshToken(
* $tokens->refresh_token,
* $clientId,
* $clientSecret,
* $redirectUri
* );
*
* // Creating an instance of RestApi
* $restApi = new AllegroRestApi($tokens->access_token);
*
* // Getting our comments
* $response = $restApi->get('/sale/user-ratings?user.id=' . $yourUserId)
* </pre>
*
* @see https://developer.allegro.pl/about/
* @author Maciej Strączkowski <m.straczkowski@gmail.com>
* @copyright ZOONDO.EU Maciej Strączkowski
* @version 2.0.0
*/
class AllegroRestApi
{
/**
* An url address for production API
*/
const URL = 'https://api.allegro.pl';
/**
* An url address for sandbox API
*/
const SANDBOX_URL = 'https://api.allegro.pl.allegrosandbox.pl';
const AUTH_URL = 'https://allegro.pl/auth/oauth';
const SANDBOX_AUTH_URL = 'https://allegro.pl.allegrosandbox.pl/auth/oauth';
const UPLOAD_URL = 'https://upload.allegro.pl';
const SANDBOX_UPLOAD_URL = 'https://upload.allegro.pl.allegrosandbox.pl';
/**
* Allegro REST API access token
*
* @var string
*/
protected $token = null;
/**
* Should we use sandbox mode?
*
* @var boolean
*/
protected $sandbox = false;
/**
* Last error response from Allegro REST API
*
* @var stdClass
*/
protected static $lastErrors = null;
protected static $lastHttpCode = null;
protected static $lastRequestInfo = null;
protected static $lastHeaders = array();
/**
* Saves given token and sandbox boolean
* value into class properties
*
* @param string $token
* @param boolean $sandbox
*/
public function __construct($token, $sandbox = false)
{
$this->setToken($token);
$this->setSandbox($sandbox);
}
/**
* Returns an authorization link which user
* should click to give access
*
* @param string $clientId
* @param string $redirectUri
* @return string
*/
public static function getAuthLink($clientId, $redirectUri, $sandbox = false)
{
$api = new AllegroRestApi(null, $sandbox);
$redirectUri = rawurlencode($redirectUri);
return $api->getAuthUrl() . "/authorize"
. "?response_type=code"
. "&client_id=$clientId"
. "&redirect_uri=$redirectUri";
}
/**
* Generates access token using given
* credentials and code
*
* @param string $code Code from allegro
* @param string $clientId Client ID
* @param string $redirectUri Client secret
* @return object
*/
public static function generateToken($code, $clientId, $clientSecret, $redirectUri, $sandbox = false)
{
// Creating an instance of class
$api = new AllegroRestApi(null, $sandbox);
// Returning response
$response = $api->sendRequest($api->getAuthUrl() . "/token"
. "?grant_type=authorization_code"
. "&code=$code"
. "&redirect_uri=$redirectUri",
'POST',
array(),
array(
'Authorization' => 'Basic ' . base64_encode("$clientId:$clientSecret")
)
);
if (is_object($response) && isset($response->access_token)) {
$api = new AllegroRestApi($response->access_token, $sandbox);
$me = $api->get('/me');
$response->seller_id = $me->id;
}
return $response;
}
/**
* Refreshes access token using given
* credentials
*
* @param string $code Code from allegro
* @param string $clientId Client ID
* @param string $redirectUri Client secret
* @return object
*/
public static function refreshToken($refreshToken, $clientId, $clientSecret, $redirectUri, $sandbox = false)
{
// Creating an instance of class
$api = new AllegroRestApi(null, $sandbox);
$query = http_build_query(array(
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
'redirect_uri' => $redirectUri,
), null, '&');
// Returning response
$response = $api->sendRequest($api->getAuthUrl() . "/token?".$query,
'POST',
array(),
array(
'Authorization' => 'Basic ' . base64_encode("$clientId:$clientSecret")
)
);
if (is_object($response) && isset($response->access_token)) {
$api = new AllegroRestApi($response->access_token, $sandbox);
$me = $api->get('/me');
$response->seller_id = $me->id;
}
return $response;
}
/**
* Stores token in class property to
* use it in requests
*
* @param string $value Access token
* @return AllegroRestApi
*/
public function setToken($value)
{
$this->token = $value;
return $this;
}
/**
* Returns api access token from property
*
* @return string Access token
*/
public function getToken()
{
return $this->token;
}
/**
* Stores boolean in class property to
* determine which environment should we use
*
* @param boolean $value True or false
* @return AllegroRestApi
*/
public function setSandbox($value)
{
$this->sandbox = (boolean)$value;
return $this;
}
/**
* Returns boolean value which determines
* which environment should we use
*
* @return boolean True or false
*/
public function getSandbox()
{
return $this->sandbox;
}
/**
* Returns REST API basic URL depending
* on current sandbox setting
*
* @return string An URL address
*/
public function getUrl()
{
// Returning correct URL depending on sandbox setting
return $this->getSandbox()
? AllegroRestApi::SANDBOX_URL
: AllegroRestApi::URL;
}
/**
* Returns REST API AUTH URL depending
* on current sandbox setting
*
* @return string An URL address
*/
public function getAuthUrl()
{
// Returning correct URL depending on sandbox setting
return $this->getSandbox()
? AllegroRestApi::SANDBOX_AUTH_URL
: AllegroRestApi::AUTH_URL;
}
/**
* Returns REST API UPLOAD URL depending
* on current sandbox setting
*
* @return string An URL address
*/
public function getUploadUrl()
{
// Returning correct URL depending on sandbox setting
return $this->getSandbox()
? AllegroRestApi::SANDBOX_UPLOAD_URL
: AllegroRestApi::UPLOAD_URL;
}
/**
* Generates UUID which can be used in
* some actions
*
* @return string UUID
*/
public function getUuid()
{
return sprintf(
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000,
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0xffff)
);
}
/**
* Sends GET request to Allegro REST API
* and returns response
*
* @param string $resource Resource path
* @param array $headers Request headers
* @return object
*/
public function get($resource)
{
return $this->sendRequest($resource, 'GET', array());
}
/**
* Sends POST request to Allegro REST API
* and returns response
*
* @param string $resource Resource path
* @param array $data Request body
* @param array $headers Request headers
* @return object
*/
public function post($resource, array $data)
{
return $this->sendRequest($resource, 'POST', $data);
}
/**
* Sends PUT request to Allegro REST API
* and returns response
*
* @param string $resource Resource path
* @param array $data Request body
* @param array $headers Request headers
* @return object
*/
public function put($resource, array $data)
{
return $this->sendRequest($resource, 'PUT', $data);
}
/**
* Sends DELETE request to Allegro REST API
* and returns response
*
* @param string $resource Resource path
* @param array $headers Request headers
* @return object
*/
public function delete($resource)
{
return $this->sendRequest($resource, 'DELETE', array());
}
/**
* Sends request to Allegro REST API
* using given arguments
*
* Returns API response as JSON object
*
* @param string $resource Resource path
* @param string $method Request method
* @param array|string $data Request body
* @return object
*/
public function sendRequest(string $resource, string $method, $data = array(), array $headers = array())
{
self::$lastErrors = array();
$headers = array_merge(array(
'Authorization' => 'Bearer ' . $this->getToken(),
'Content-Type' => 'application/vnd.allegro.public.v1+json',
'Accept' => 'application/vnd.allegro.public.v1+json',
'Accept-Language' => 'pl-PL',
), $headers);
stCommunication::forceSocketConnectionTime();
self::$lastHeaders = array();
$httpHeaders = self::parseHeaders($headers);
$ch = curl_init(stristr($resource, 'http') !== false ? $resource : $this->getUrl() . '/' . ltrim($resource, '/'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array('AllegroRestApi', 'setCurlHeaders'));
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
if (!empty($data))
{
curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($data) ? json_encode($data) : $data);
}
if ($data)
{
stPayment::log('allegro', sprintf("Calling %s (method: %s, headers: %s, data: %s)", $resource, strtoupper($method), json_encode($headers, JSON_UNESCAPED_UNICODE), json_encode($data, JSON_UNESCAPED_UNICODE)));
}
else
{
stPayment::log('allegro', sprintf("Calling %s (method: %s, headers: %s)", $resource, strtoupper($method), json_encode($headers, JSON_UNESCAPED_UNICODE)));
}
$response = curl_exec($ch);
if (false === $response)
{
$error = curl_error($ch);
self::$lastErrors = array(new stdClass());
self::$lastErrors[0]->code = curl_errno($ch);
self::$lastErrors[0]->message = $error;
self::$lastErrors[0]->path = null;
self::$lastErrors[0]->details = null;
self::$lastErrors[0]->userMessage = $error;
$e = new stAllegroException($error);
$trace = str_replace("\n", ", ", $e->getTraceAsString());
stPayment::log('allegro', sprintf("Got exception \"%s\" (headers: %s, trace: %s)", $e->getMessage(), json_encode(self::$lastHeaders, JSON_UNESCAPED_UNICODE), $trace));
throw $e;
}
if ($response)
{
$response = json_decode($response);
}
$info = curl_getinfo($ch);
self::$lastHttpCode = $info['http_code'];
self::$lastRequestInfo = $info;
if (self::$lastHttpCode >= 400)
{
if (isset($response->errors))
{
self::$lastErrors = $response->errors;
}
if (isset($response->error))
{
self::$lastErrors = array(new stdClass());
self::$lastErrors[0]->code = $response->error;
self::$lastErrors[0]->message = $response->error_description;
self::$lastErrors[0]->path = null;
self::$lastErrors[0]->details = null;
self::$lastErrors[0]->userMessage = $response->error_description;
}
$traceId = isset(self::$lastHeaders['trace-id']) ? self::$lastHeaders['trace-id'] : 'none';
$e = new stAllegroException(self::$lastErrors ? self::$lastErrors[0]->message : (is_object($response) ? json_encode($response, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : $response). " (trace-id: $traceId)", self::$lastHttpCode);
$trace = str_replace("\n", ", ", $e->getTraceAsString());
stPayment::log('allegro', sprintf("Got exception \"%s\" (headers: %s, trace: %s)", $e->getMessage(), json_encode(self::$lastHeaders, JSON_UNESCAPED_UNICODE), $trace));
throw $e;
}
stCommunication::restoreSocketConnectionTime();
return $response;
}
/**
* Last Error response from Allegro REST API
*
* @return stdClass
*/
public static function getLastErrors()
{
return self::$lastErrors;
}
public static function getLastErrorsAsString($delimiter = "\n")
{
$messages = array();
$errors = self::getLastErrors();
foreach ($errors as $error)
{
$messages[] = $error->userMessage ? $error->userMessage : $error->message;
}
return implode($delimiter, $messages);
}
public static function getLastRequestInfo()
{
return self::$lastRequestInfo;
}
public static function getLastHttpCode()
{
return self::$lastHttpCode;
}
protected static function setCurlHeaders($handle, $header)
{
$details = explode(':', $header, 2);
if (count($details) == 2)
{
$key = trim($details[0]);
$value = trim($details[1]);
self::$lastHeaders[$key] = $value;
}
return strlen($header);
}
protected static function parseHeaders(array $headers)
{
$result = array();
foreach ($headers as $header => $value)
{
$result[] = "$header: $value";
}
return $result;
}
}