550 lines
15 KiB
PHP
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;
|
|
}
|
|
}
|