?php namespace hauSplio\Classes; use hauStructure\Components\Logger; use apeServices\Services\Other\RedisService; use Shopware\Components\Plugin\ConfigReader; use Shopware\Components\Plugin\Configuration\CachedReader; /** * Contains Splio API Handler * @url https://developer.splio.com/ * * @author Adnan Hodzic * @copyright 2022 von Affenfels GmbH */ abstract class SplioApi { /** * @var false|mixed */ protected mixed $splioMaintenance; /** * @var string */ private string $endpoint = 'https://api.splio.com/'; /** * @var string */ private string $token; private array $fields = [ 'id' => ['string'], 'lastname' => ['string'], 'firstname' => ['string'], 'creation_date' => ['string'], 'language' => ['string'], 'email' => ['string'], 'cellphone' => ['string'], 'lists' => ['array'], 'per_page' => ['integer'], 'page_number' => ['integer'], 'event_date' => ['string'], 'nq_points_quantity' => ['integer'], 'q_points_quantity' => ['integer'], 'context' => ['string'], 'is_final' => ['boolean'], 'card_code' => ['string'], 'elements' => ['array'], 'external_id' => ['string'], 'contact_id' => ['string'], 'store_external_id' => ['string'], 'ordered_at' => ['string'], 'discount_amount' => ['float', 'double'], 'shipping_amount' => ['float', 'double'], 'total_price' => ['float', 'double'], 'tax_amount' => ['float', 'double'], 'completed' => ['boolean'], 'currency' => ['string'], 'products' => ['array'], 'custom_fields' => ['array'], 'event' => ['string'], 'source_type' => ['string'], 'channel' => ['string'], 'individual_id' => ['string'], 'source_date' => ['string'], 'value_date' => ['string'], ]; /** * @var string */ private string $apiKey; /** * @var int */ public int $loyaltyProgramId; /** * @var bool */ private bool $authenticated; /** * @var string */ public string $customerStreamId; /** * @var array */ protected array $config; protected int $shopId; /** * @param CachedReader $configReader * @param RedisService $redisService * @param Logger $logger */ public function __construct( protected CachedReader $configReader, protected RedisService $redisService, protected Logger $logger, ) { $this->readConfig(); $this->authenticated = $this->authenticate(); } /** * Retrieves the plugin config * * @param null $shopId * * @return void */ private function readConfig($shopId = null): void { if (!$shopId) { $this->shopId = Shopware()->Container()->has('shop') ? Shopware()->Shop()->getId() : 1; } else { $this->shopId = $shopId; } $this->config = $this->configReader->getByPluginName('hauSplio', $this->shopId); if (!$shopId && !empty($this->apiKey)) { return; } $this->apiKey = $this->config['splioApiKey']; $this->loyaltyProgramId = (int)$this->config['splioLoyaltyProgramID']; $this->customerStreamId = $this->config['splioCustomerStreamId']; $this->splioMaintenance = $this->config['splioMaintenance'] ?? false; } /** * @param $params * * @return void * @throws SplioException */ public function validateFields($params): void { foreach ($params as $paramKey => $value) { if ($this->fields[$paramKey] && !in_array(gettype($value), $this->fields[$paramKey], true)) { throw new SplioException( 'Wrong type for field "' . $paramKey . '": ' . implode( ', ', $this->fields[$paramKey] ) . ' expected, ' . gettype($value) . ' given' ); } } } /** * Builds an url for the Splio api. * * @param $url * @param array $params * * @return string */ public function buildUrl($url, array $params = []): string { return $url . '?' . http_build_query($params); } /** * Makes a request to the splio api endpoint. * * @param string $method * @param string $url * @param array $params * @param bool $authorization * @param null $shopId * @param bool $returnDetailedError * * @return bool|array * @throws SplioException */ public function apiRequest(string $method, string $url, array $params = [], bool $authorization = true, $shopId = null, bool $returnDetailedError = false, bool $allowEmptyResult = false): bool|array { if ($this->splioMaintenance) { throw new SplioException("Maintenance Mode"); } if ($shopId) { $this->readConfig($shopId); $this->authenticated = $this->authenticate(); } if ($authorization && !$this->authenticated) { return false; } $url = $this->endpoint . $url; $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); if ($authorization) { curl_setopt($curl, CURLOPT_HTTPHEADER, [ 'Authorization: ' . $this->token, ]); } switch ($method) { case 'POST': curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($params)); break; case 'GET': break; case 'PATCH': curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($params)); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH'); break; case 'DELETE': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); break; } $result = curl_exec($curl); curl_close($curl); $resultEncoded = json_decode($result, true); $httpStatusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); if (!$resultEncoded) { if ($method === 'DELETE' || $method === 'PATCH') { // delete and patch return NULL return true; } if (($httpStatusCode === 200 || $httpStatusCode === 202) && $allowEmptyResult) { return true; } throw new SplioException("Error while sending a request!"); } if (is_array($resultEncoded) && !empty($resultEncoded)) { if ($resultEncoded['status'] === 404) { return $returnDetailedError ? $resultEncoded : false; } if ($resultEncoded['errors']) { throw new SplioException($resultEncoded['errors']); } if (isset($resultEncoded['error'])) { throw new SplioException($resultEncoded['error_description']); } } return $resultEncoded; } /** * @return bool */ private function authenticate(): bool { $url = 'authenticate'; if (!$this->redisService->has('splio_token-' . $this->shopId) || $this->redisService->get( 'splio_token-' . $this->shopId ) === '') { try { $request = $this->apiRequest('POST', $url, ['api_key' => $this->apiKey], false); if ($request['token']) { $this->redisService->set('splio_token-' . $this->shopId, ('Bearer ' . $request['token']), 3000); } else { $this->logger->error("Token missing in authenticate method!"); return false; } } catch (SplioException $exception) { $this->logger->info($exception->getMessage()); return false; } } $this->token = $this->redisService->get('splio_token-' . $this->shopId); return true; } }