Files
wyczarujprezent.pl/modules/zakeke/classes/ZakekeApi.php
2024-10-28 22:14:22 +01:00

427 lines
11 KiB
PHP

<?php
/**
* Copyright (C) 2020 Futurenext srl
*
* This file is part of Zakeke.
*
* Zakeke Interactive Product Designer can not be copied and/or distributed
* without the express permission of Futurenext srl
*
* @author Futurenext srl <help@zakeke.com>
* @copyright 2019 Futurenext srl
* @license https://www.zakeke.com/privacy/#general_conditions
*/
class ZakekeApi
{
const ZAKEKE_API_URL = 'https://zakeke-api-frontdoor.azurefd.net';
/** @var bool Enable debug mode */
protected $debug = false;
/**
* Check if the design identifier is valid by throwing an exception
*
* @param $designId
* @throws Exception
*/
private static function checkDesignId($designId)
{
if (strpos($designId, 'Testing-') === 0) {
return;
}
if (!preg_match('/\d\d\d-\w{22}/', $designId)) {
throw new Exception($designId . ' is not a valid design identifier');
}
}
/**
* ZakekeApi constructor.
*
* @param bool $debug
*/
public function __construct($debug)
{
$this->debug = $debug;
}
/**
* Associate the guest with a customer
*
* @param string $guestCode Guest identifier.
* @param string $customerId Customer identifier.
*
* @throws Exception
* @return void
*/
public function associateGuest($guestCode, $customerId)
{
$data = $this->authMinimalData();
$data['visitorcode'] = $guestCode;
$data['customercode'] = $customerId;
$this->authToken($data);
}
/**
* Get the minimal data required to get the authentication token
*
* @return array
*/
private function authMinimalData()
{
$data = array(
'api_client_id' => Configuration::get('ZAKEKE_API_CLIENT_ID'),
'api_secret_key' => Configuration::get('ZAKEKE_API_SECRET_KEY')
);
return $data;
}
/**
* Zakeke authentication token.
*
* @param array $data
* @param array $authData
*
* @throws Exception
* @return string
*/
public function authToken($data, $authData = null)
{
if (is_null($authData)) {
$authData = $this->authMinimalData();
}
$url = ZakekeApi::ZAKEKE_API_URL . '/token';
$postfields = http_build_query(array_merge($data, array(
'grant_type' => 'client_credentials'
)), null, '&');
$headers = array(
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json',
'User-Agent: prestashop-zakeke/' . ZAKEKE_VERSION . '; Prestashop/' . _PS_VERSION_ . '; ' . __PS_BASE_URI__
);
$curl = curl_init();
curl_setopt_array(
$curl,
array(
CURLOPT_URL => $url,
CURLOPT_USERPWD => $authData['api_client_id'] . ':' . $authData['api_secret_key'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_VERBOSE => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $postfields,
CURLOPT_HTTPHEADER => $headers
)
);
$rawResponse = curl_exec($curl);
$error = curl_error($curl);
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$this->maybeLog($url, 'POST', $data, $rawResponse, $statusCode);
if ($error || !$this->isStatusCodeOk($statusCode)) {
$msg = '$zakekeApi authToken: status: ' . $statusCode
. ' ' . $error . ', response: ' . $rawResponse;
throw new Exception($msg);
}
$result = json_decode($rawResponse, true);
return $result['access_token'];
}
/**
* Performs the underlying HTTP request.
*
* @param string $method HTTP method (GET|POST|PUT|PATCH|DELETE)
* @param string $resource MailChimp API resource to be called
* @param array $args array of parameters to be passed
* @param string $authToken Authentication token
*
* @throws Exception
* @return array array of decoded result
*/
protected function request($method, $resource, $args = array(), $authToken = null)
{
$url = ZakekeApi::ZAKEKE_API_URL . $resource;
// attach arguments (in body or URL)
$postfields = '';
if (!empty($args)) {
if ($method === 'GET') {
$url .= '?' . http_build_query($args);
} else {
$postfields = json_encode($args);
}
}
$headers = array(
'Content-Type: application/json',
'Accept: application/json',
'User-Agent: prestashop-zakeke/' . ZAKEKE_VERSION . '; Prestashop/' . _PS_VERSION_ . '; ' . __PS_BASE_URI__
);
if ($authToken != null) {
$headers[] = 'Authorization: Bearer ' . $authToken;
}
$curl = curl_init();
curl_setopt_array(
$curl,
array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_VERBOSE => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS => $postfields,
CURLOPT_HTTPHEADER => $headers
)
);
$rawResponse = curl_exec($curl);
$error = curl_error($curl);
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$this->maybeLog($resource, $method, $args, $rawResponse, $statusCode);
if ($error ||!$this->isStatusCodeOk($statusCode)) {
$msg = '$zakekeApi request: ' . $resource . ', status: ' . $statusCode
. ' ' . $error . ', response: ' . $rawResponse;
throw new Exception($msg);
}
$result = json_decode($rawResponse, true);
return $result;
}
/**
* Remove sensitive information from the logs
*
* @param string $message
* @return string
*/
private static function sanitizeLog($message)
{
$zakeke_api_secret = Configuration::get('ZAKEKE_API_SECRET_KEY');
if ($zakeke_api_secret) {
$message = str_replace($zakeke_api_secret, 'ZAKEKE_API_SECRET_KEY', $message);
}
return $message;
}
/**
* Conditionally log Zakeke API Call
*
* @param string $url Zakeke url
* @param string $method HTTP Method
* @param array $args HTTP Request Body
* @param string $response HTTP Response
* @param int $statusCode HTTP status code
*
* @return void
*/
private function maybeLog($url, $method, $args, $response, $statusCode)
{
if (!$this->debug) {
return;
}
PrestaShopLogger::addLog(
self::sanitizeLog(
'Zakeke Webservice Call URL: ' . $method . ' ' . $url . ' METHOD: $method BODY: ' . print_r(
$args,
true
) . ' RESPONSE: ' . $statusCode . ' - ' . $response
)
);
}
/**
* Check if the response was successful.
*
* @param int $statusCode HTTP status code
*
* @return bool
*/
protected function isStatusCodeOk($statusCode)
{
return $statusCode >= 200 && $statusCode < 400;
}
/**
* Get the needed data for adding a product to the cart
*
* @param string $designId Zakeke design identifier
* @param int $qty Quantity
*
* @throws Exception
* @return object
*/
public function cartInfo($designId, $qty)
{
self::checkDesignId($designId);
$authToken = $this->authToken(array());
$url = '/api/designdocs/' . $designId . '/cartinfo';
$data = array(
'qty' => $qty
);
$json = $this->request('GET', $url, $data, $authToken);
$res = new stdClass();
$res->pricing = $json['pricing'];
$preview = new stdClass();
$preview->url = $json['tempPreviewUrl'];
$preview->label = '';
$res->previews = array($preview);
return $res;
}
/**
* Get the needed data for adding a product to the cart
*
* @param string $configurationId Zakeke configuration identifier
* @param int $qty Quantity
*
* @throws Exception
* @return array
*/
public function configuratorCartInfo($configurationId, $qty)
{
self::checkDesignId($configurationId);
$authToken = $this->authToken(array(
'access_type' => 'S2S'
));
$url = '/v1/compositions/' . $configurationId . '/cartinfo';
$data = array(
'qty' => $qty
);
return $this->request('GET', $url, $data, $authToken);
}
/**
* Order containing Zakeke customized products placed.
*
* @param array $data The data of the order
*
* @throws Exception
* @return void
*/
public function placeOrder($data)
{
$authData = array();
if (isset($data['customerID'])) {
$authData['customercode'] = $data['customerID'];
} elseif (isset($data['visitorID'])) {
$authData['visitorcode'] = $data['visitorID'];
}
$authToken = $this->authToken($authData);
$data['marketplaceID'] = '1';
$this->request('POST', '/api/orderdocs', $data, $authToken);
}
/**
* Get the Zakeke design preview files
*
* @param string $designId Zakeke design identifier
*
* @throws Exception
* @return array
*/
public function getPreviews($designId)
{
self::checkDesignId($designId);
$authToken = $this->authToken(array());
$data = array(
'docid' => $designId
);
$json = self::request(
'GET',
'/api/designs/0/previewfiles',
$data,
$authToken
);
$previews = array();
foreach ($json as $preview) {
if ($preview['format'] == 'SVG') {
continue;
}
$previewObj = new stdClass();
$previewObj->url = $preview['url'];
$previewObj->label = $preview['sideName'];
$previews[] = $previewObj;
}
return $previews;
}
/**
* Get the Zakeke design output zip
*
* @param string $designId Zakeke design identifier
*
* @throws Exception
* @return string
*/
public function getZakekeOutputZip($designId)
{
self::checkDesignId($designId);
$authToken = $this->authToken(array());
$data = array(
'docid' => $designId
);
$json = $this->request(
'GET',
'/api/designs/0/outputfiles/zip',
$data,
$authToken
);
return $json['url'];
}
public function checkCredentials($clientId, $secretKey)
{
try {
$this->authToken(array(), array(
'api_client_id' => $clientId,
'api_secret_key' => $secretKey
));
return true;
} catch (Exception $e) {
return false;
}
}
}