HEX
Server: Apache
System: Linux srv13.cpanelhost.cl 3.10.0-962.3.2.lve1.5.38.el7.x86_64 #1 SMP Thu Jun 18 05:28:41 EDT 2020 x86_64
User: cca63905 (4205)
PHP: 7.3.20
Disabled: NONE
Upload Files
File: /home4/cca63905/public_html/nueva/modules/pmproductvideoreviews/lib/RecReviews/Client.php
<?php
/**
 * rec.reviews
 *
 * @author    Presta-Module.com <support@presta-module.com> - https://www.presta-module.com
 * @copyright Presta-Module - https://www.presta-module.com
 * @license   see file: LICENSE.txt
 *
 *           ____     __  __
 *          |  _ \   |  \/  |
 *          | |_) |  | |\/| |
 *          |  __/   | |  | |
 *          |_|      |_|  |_|
 */

namespace RecReviews;

if (!defined('_PS_VERSION_')) {
    exit;
}

class Client
{
    const WEBSITE_URL = 'https://recreviews.com/';
    const API_URL = 'https://dashboard.recreviews.com/';
    const ONBOARDING_URL = 'https://dashboard.recreviews.com/onboarding';
    const MODULE_SOURCE = 'addons';
    const CLIENT_ID = '9627cf77-6413-4b48-aa3e-5d903b774598';
    const SECRET_ID = 'T7BY4Eb3VWXic25m8Ls7YR2IhROTcsVGdY50ZDO';
    const RBM_PATH = 'https://billing-api.distribution.prestashop.net/v1/customers/';
    const RBM_TOKEN = 'EVKsZ5puh0mt6A1hV8VSQ10LfAE18ot5';

    /**
     * The access token to use to authentify requests
     *
     * @var string
     */
    private $access_token;

    private function __construct()
    {
    }

    public static function getClient()
    {
        static $client = null;
        if ($client === null) {
            $client = new static();
        }
        return $client;
    }

    /**
     * Retrieve CURL Handle
     *
     * @param string $access_token
     * @param string $url
     * @param string $method
     * @param array $params
     * @param array $addHeaders
     *
     * @return resource
     */
    private static function getCurlHandle($access_token, $url, $method = 'GET', $params = [], $addHeaders = [])
    {
        // initialize curl library
        $curlHandle = curl_init();

        $headers = [
            'Accept' => 'application/json',
            'Authorization' => 'Bearer ' . $access_token,
            'Content-type' => 'application/json',
            'X-Platform' => 'Prestashop',
        ];

        // Combine headers, prevent override of original headers
        $headers = ($headers + $addHeaders);
        $curlHeaders = [];
        foreach ($headers as $key => $value) {
            $curlHeaders[] = $key . ': ' . $value;
        }

        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $curlHeaders);
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curlHandle, CURLOPT_ENCODING, '');
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($curlHandle, CURLOPT_URL, $url);
        curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($curlHandle, CURLOPT_TIMEOUT, 30);
        curl_setopt($curlHandle, CURLOPT_NOSIGNAL, 1);
        curl_setopt($curlHandle, CURLOPT_FAILONERROR, false);

        if ($method == 'GET') {
            curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'GET');
            curl_setopt($curlHandle, CURLOPT_HTTPGET, true);
            curl_setopt($curlHandle, CURLOPT_POST, false);
        } elseif ($method == 'POST') {
            curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
            curl_setopt($curlHandle, CURLOPT_POST, true);
            // Content type is set to JSON so we can encode our form data this way
            curl_setopt($curlHandle, CURLOPT_POSTFIELDS, json_encode($params));
        }

        return $curlHandle;
    }

    /**
     * Retrieve response regarding a query
     *
     * @param string $access_token
     * @param string $path
     * @param array $params
     * @param array $addHeaders
     *
     * @return object
     *
     * @throws Exception
     */
    public static function getResponse($access_token, $path, $method = 'GET', $params = [], $addHeaders = [], $module_source = 'prestamodule')
    {
        if ($module_source == 'prestamodule') {
            // Create URL
            $url = self::API_URL . $path;
        } elseif ($module_source == 'addons') {
            $url = $path;
        }

        if (count($params) && $method == 'GET') {
            $url .= '?' . http_build_query($params);
        }

        // Retrieve CURL handle
        $curlHandle = self::getCurlHandle($access_token, $url, $method, $params, $addHeaders);
        $errorNb = $errorMessage = null;
        $response = curl_exec($curlHandle);

        $httpCode = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);

        if ($response === false) {
            $errorNb = curl_errno($curlHandle);
            $errorMessage = curl_error($curlHandle);
            curl_close($curlHandle);
        } else {
            $response = json_decode($response);
        }

        if ($httpCode == 200 || ($module_source = 'addons' && $httpCode == 404)) { // we have to test 404 for use case when customer doesn't exist or subscription doesn't exist
            return $response;
        } elseif ($httpCode == 429) {
            throw new \Exception('Error Processing Request - Too many requests', 2);
        } elseif ($httpCode == 403) {
            return $httpCode;
        } elseif ($httpCode == 419) {
            throw new \Exception('Error Processing CSRF Token Request - Server error', 4);
        } elseif ($httpCode == 500) {
            throw new \Exception('Error Processing Request - Server error', 5);
        } elseif ($httpCode == 504) {
            throw new \Exception('Error Processing Request - Timeout', 6);
        } elseif (empty($httpCode)) {
            throw new \Exception(sprintf('Error Processing Request - Unknown - %s', $errorMessage), 7);
        } elseif ($httpCode == 401) { // Happen when the Oauth didn't work
            // Attempt to refresh the token if it's expired
            $refreshedToken = self::refreshToken();
            if ($refreshedToken === false) {
                \Configuration::updateValue('PVR_OAUTH', []);
                \Configuration::updateValue('PVR_RBM_SUB_ID', null);
                \Configuration::updateValue('PVR_API_SHOP_ID', null);
                return \Tools::redirectAdmin(\Context::getContext()->link->getAdminLink('AdminModules') . '&configure=pmproductvideoreviews');
            }
            // If we were able to refresh the token, try again
            return self::getResponse($refreshedToken, $path, $method, $params, $addHeaders, $module_source);
        }

        throw new \Exception("Error Processing Request - HTTP Code $httpCode", 1);
    }

    /**
     * Update configuration
     *
     * @param string $access_token
     * @param array $configuration
     *
     * @return object
     */
    public static function updateModuleConfigurationForGis($access_token, $aConfiguration)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/module/configuration', 'POST', $aConfiguration);

        if (!empty($response->result)) {
            return true;
        }

        return false;
    }

    /**
     * Send data to Gis
     *
     * @param string $access_token
     * @param string $data
     *
     * @return object
     */
    public static function sendReviewData($access_token, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/reviews', 'POST', $data);

        if (!empty($response->result)) {
            return $response->recorderUrl;
        }

        return true;
    }

    /**
     * get the review data from apo
     *
     * @param string $access_token
     * @param string $data
     *
     * @return object
     */
    public static function getReviewData($access_token, $data = [])
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/reviews', 'GET', $data);

        if (isset($response->reviews)) {
            return $response->reviews;
        }

        return [];
    }

    /**
     * Update review data on our API
     *
     * @param string $access_token
     * @param string $reviewIdApi
     * @param string $data
     *
     * @return object
     */
    public static function updateReviewData($access_token, $reviewIdApi, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/reviews/' . $reviewIdApi, 'POST', $data);

        if (!empty($response->result)) {
            return true;
        }

        return true;
    }

    /**
     * get the Api shop
     *
     * @param string $access_token
     *
     * @return object
     */
    public static function getShop($access_token, $data = [])
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/shop', 'GET', $data);

        if (!empty($response->result)) {
            return $response->shop;
        }

        return false;
    }

    /**
     * Update review data on our API
     *
     * @param string $access_token
     * @param string $reviewIdApi
     * @param string $data
     *
     * @return object
     */
    public static function getUpdatedReview($access_token, $reviewIdApi, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/reviews/updated/' . $reviewIdApi, 'GET', $data);

        if (!empty($response->result)) {
            return $response->review;
        }

        return true;
    }

    /**
     * Send publish review to api
     *
     * @param string $access_token
     * @param string $reviewIdApi
     * @param string $data
     *
     * @return object
     */
    public static function getReview($access_token, $reviewIdApi, $data = [])
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/reviews/' . $reviewIdApi, 'GET', $data);

        if (!empty($response->review)) {
            return $response->review;
        }

        return true;
    }

    /**
     * Send publish review to api
     *
     * @param string $access_token
     * @param string $reviewIdApi
     * @param string $data
     *
     * @return object
     */
    public static function publishReview($access_token, $reviewIdApi, $data = [])
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/reviews/' . $reviewIdApi . '/publish', 'POST', $data);

        if (!empty($response->result)) {
            return true;
        }

        return true;
    }

    /**
     * Send unpublish review to api
     *
     * @param string $access_token
     * @param string $reviewIdApi
     * @param string $data
     *
     * @return object
     */
    public static function unpublishReview($access_token, $reviewIdApi, $data = [])
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/reviews/' . $reviewIdApi . '/unpublish', 'POST', $data);

        if (!empty($response->result)) {
            return true;
        }

        return true;
    }

    /**
     * Send data to Gis on update status
     *
     * @param string $access_token
     * @param string $data
     *
     * @return object
     */
    public static function sendUpdateStatus($access_token, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/orders/status', 'POST', $data);

        if (!empty($response->result)) {
            return true;
        }

        return true;
    }

    /**
     * Send data to Gis on voucher information
     *
     * @param string $access_token
     * @param string $data
     *
     * @return object
     */
    public static function sendVoucher($access_token, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/orders/voucher', 'POST', $data);

        if (!empty($response->result)) {
            return true;
        }

        return true;
    }

    /**
     * Send data the order data information to handle email scheduler
     *
     * @param string $access_token
     * @param string $data
     *
     * @return object
     */
    public static function sendOrderData($access_token, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/orders', 'POST', $data);

        if (!empty($response->result)) {
            return true;
        }

        return true;
    }

    /**
     * Send data the order data information to handle email scheduler
     *
     * @param string $access_token
     * @param string $data
     *
     * @return object
     */
    public static function getOrderData($access_token, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/orders', 'GET', $data);

        if (!empty($response->orders)) {
            return $response->orders;
        }

        return [];
    }

    /**
     * Revoke the access token
     *
     * @param string $access_token
     * @param string $data
     *
     * @return object
     */
    public static function revoke($access_token, $data)
    {
        if (empty($access_token)) {
            return false;
        }

        $response = self::getResponse($access_token, 'api/module/revoke', 'POST', $data);

        if (!empty($response->result)) {
            return true;
        }

        return false;
    }

    /**
     * Generates our code verifier for the oAuth process
     *
     * @param int $length
     *
     * @return string
     */
    public static function codeVerifierGen($length = 128)
    {
        $bytes = openssl_random_pseudo_bytes($length);
        $position = 0;
        $result = '';
        $str = 'abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~';
        for ($i = 0; $i < $length; ++$i) {
            $position = ($position + ord($bytes[$i])) % strlen($str);
            $result .= $str[$position];
        }

        return $result;
    }

    /**
     * Creates a code challenge based on the provided verifier string
     *
     * @param string $verifier
     *
     * @return string
     */
    public static function createCodeChallengeFromVerifier($verifier)
    {
        return strtr(rtrim(base64_encode(hash('sha256', $verifier, true)), '='), '+/', '-_');
    }

    /**
     * Setter for the access token
     *
     * @param string $access_token
     *
     * @return $this
     */
    public function setAccessToken($access_token)
    {
        $this->access_token = $access_token;

        return $this;
    }

    /**
     * Get the access token
     *
     * @param string $authorizationCode
     * @param string $redirectUri
     * @param string $clientId
     * @param string $codeVerifier
     *
     * @return object|null
     */
    public function getAccessToken($authorizationCode, $redirectUri, $clientId, $codeVerifier)
    {
        $response = $this->getResponse($this->access_token, 'oauth/token', 'POST', [
            'grant_type' => 'authorization_code',
            'client_id' => $clientId,
            'code_verifier' => $codeVerifier,
            'redirect_uri' => $redirectUri,
            'code' => $authorizationCode,
        ]);

        if (!empty($response) && !empty($response->token_type && !empty($response->access_token))) {
            return $response;
        }
        return null;
    }

    /**
     * Refreshes the oAuth token using the stored refresh token
     *
     * @return bool
     */
    public static function refreshToken()
    {
        $oAuthConfig = json_decode(\Configuration::get('PVR_OAUTH'), true);
        if (empty($oAuthConfig)
            || empty($oAuthConfig['refresh_token'])
            || empty($oAuthConfig['clientId'])
            || empty($oAuthConfig['codeVerifier'])
        ) {
            return false;
        }

        $response = self::getResponse('', 'oauth/token', 'POST', [
            'grant_type' => 'refresh_token',
            'refresh_token' => $oAuthConfig['refresh_token'],
            'client_id' => $oAuthConfig['clientId'],
            'code_verifier' => $oAuthConfig['codeVerifier'],
        ]);

        if (!empty($response) && !empty($response->token_type && !empty($response->access_token))) {
            // Store new values
            $oAuthConfig['access_token'] = $response->access_token;
            $oAuthConfig['expires_in'] = time() + $response->expires_in;
            $oAuthConfig['refresh_token'] = $response->refresh_token;
            $oAuthConfig['token_type'] = $response->token_type;
            \Configuration::updateValue('PVR_OAUTH', json_encode($oAuthConfig));

            return $response->access_token;
        }

        return false;
    }

    /**
     * Get the access token
     *
     * @param string $rbmSubscriptionId
     *
     * @return object|null
     */
    public function getAccessTokenRbm($rbmSubscriptionId)
    {
        $response = '';

        if (self::MODULE_SOURCE == 'addons') {
            $response = $this->getResponse('', 'oauth/token', 'POST', [
                'grant_type' => 'client_credentials',
                'client_id' => self::CLIENT_ID,
                'client_secret' => self::SECRET_ID,
                'rbmSubscriptionId' => $rbmSubscriptionId,
            ]);
        }

        if (!empty($response) && !empty($response->token_type && !empty($response->access_token))) {
            return $response;
        }

        return null;
    }

    /**
     * Get rbm subscription id
     *
     * @param string $psToken
     * @param string $psCustomerId
     *
     * @return int
     */
    public static function getRmbSubscriptionId($psToken, $psCustomerId)
    {
        $response = '';

        if (self::MODULE_SOURCE == 'addons') {
            $response = self::getResponse($psToken, self::RBM_PATH . $psCustomerId . '/subscriptions/pmproductvideoreviews', 'GET', [], [], 'addons');
        }

        if (!empty($response->id)) {
            return $response->id;
        }

        return null;
    }

    /**
     * Performs the request to create a limited trial subscription to our API
     *
     * @param array $data
     *
     * @return mixed
     */
    public function createLimitedTrialSubscription($data)
    {
        if (self::MODULE_SOURCE != 'addons') {
            return;
        }

        $response = $this->getResponse('', 'api/rbm/subscription/initTrial', 'POST', array_merge(['token' => self::RBM_TOKEN], $data));
        if (!empty($response->result) && !empty($response->subscription) && !empty($response->shop)) {
            return [
                'subscription' => $response->subscription,
                'shop' => $response->shop,
            ];
        }

        return null;
    }
}