403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/boxberry.delivery/lib/boxberry/api/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/boxberry.delivery/lib/boxberry/api/Client.php
<?php

namespace Boxberry\Api;

use Bitrix\Main\Application;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Error;
use Bitrix\Main\IO\Directory;
use Bitrix\Main\IO\File;
use Bitrix\Main\Result;
use Bitrix\Main\Text\StringHelper;
use Bitrix\Main\Web\Http\ClientException;
use Bitrix\Main\Web\Http\FormStream;
use Bitrix\Main\Web\Http\Method;
use Bitrix\Main\Web\Http\Request;
use Bitrix\Main\Web\Http\Stream;
use Bitrix\Main\Web\Uri;
use Boxberry\Api\Entity\CompanyApiSettings;
use Boxberry\Api\Entity\DadataResult;
use Boxberry\Api\Entity\DeliveryCalculationParams;
use Boxberry\Api\Entity\DeliveryCalculationResult;
use Boxberry\Api\Entity\GetKeyIntegration;
use Boxberry\Api\Entity\GetLastStatusData;
use Boxberry\Api\Entity\ParcelInfoResult;
use Boxberry\Api\Entity\ParcelParams;
use Boxberry\Api\Entity\ParcelResult;
use Boxberry\Api\Entity\ParselSendResult;
use Boxberry\Api\Entity\PointsDescriptionResult;
use Boxberry\Api\Entity\ZipCheck;
use Boxberry\Api\Exceptions\BoxberryApiException;
use Bitrix\Main\Data\Cache;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Text\Encoding;
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Json;
use Boxberry\Api\Entity\WidgetSettings;
use Boxberry\Bitrix\Helpers\Delivery;
use Boxberry\Bitrix\Helpers\Logger;
use Boxberry\Bitrix\Helpers\Options;
use Boxberry\Client\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LogLevel;

Loc::loadMessages(__FILE__);

class Client
{
    public const TEST_TOKEN = 'b050ebfcdb91b9117932f89d05d40bb4';
    public const YANDEX_TEST_TOKEN = '0f779ef5a201ac33d30c571a961e4604';
    public const SOURCE_BOXBERRY = 'BOXBERRY';
    public const SOURCE_YANDEX = 'YANDEX';
    public const TEST_WIDGET_KEY = '1$1WxHaMxOqq-BN1iQI9vQTIQJe9r1VoC_';
    public const YANDEX_TEST_WIDGET_KEY = '1$bf44ea16088a8abb821c3ca623644c6a';
    private const DADATA_TOKEN = 'Token a105367bc6479ffb2a355fad7536e0fb504c1b97';
    private const API_URL = 'https://api.boxberry.ru/json.php';
    public const MODULE_UPDATE_URL = 'https://bitrix.boxberry.ru/new_module_updates/checkModuleUpdate.php';
    private const DADATA_API_URL = 'https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/address';
    private const CACHE_DIR = '/bb_api/';
    public const FILE_UPLOAD_DIR = '/upload/boxberry/';

    private array $defaultHeaders = [
        'Content-Type' => 'application/json'
    ];
    private string $token;
    private bool $logEnabled;
    private string $logFilePath;
    private int $logFileSize;
    private HttpClient $client;
    private Cache $cache;
    private ?Logger $logger = null;
    private ?string $docRoot;
    private Uri $uri;
    private string $requestType;
    private int $responseCode = 0;
    private bool $yaDelivery = false;
    private bool $authorization = false;
    private string $source = self::SOURCE_BOXBERRY;

    public function __construct($token, $socketTimeout = 60, $streamTimeout = 60)
    {
        $this->client = new HttpClient(['socketTimeout' => $socketTimeout, 'streamTimeout' => $streamTimeout]);
        $this->cache = Cache::createInstance();
        $this->token = trim($token);
        $this->uri = new Uri(static::API_URL);
        $this->setLogConfig();

        if ($this->logEnabled) {
            $this->docRoot = Application::getDocumentRoot();
        }

    }

    public function getLogger(): ?Logger
    {
        return $this->logger;
    }

    public function initSource(): void
    {
        try {
            $companyApiSettings = $this->companyApiSettings();
            $this->yaDelivery = $companyApiSettings->isYaDelivery();
        } catch (\Exception $e) {
            $this->yaDelivery = false;
        }

        $this->yaDelivery ?
            $this->setSource(self::SOURCE_YANDEX) :
            $this->setSource(self::SOURCE_BOXBERRY);

    }

    public function isSourceBoxberry(): bool
    {
        return $this->getSource() === self::SOURCE_BOXBERRY;
    }

    public function isSourceYandex(): bool
    {
        return $this->getSource() === self::SOURCE_YANDEX;
    }

    protected function setLogConfig(): void
    {
        $this->logEnabled = Options::isApiLogEnabled();
        $this->logFilePath = Options::getApiLogFilePath();
        $this->logFileSize = Options::getApiLogFileSize();
    }

    public function log(string $level, string $message): void
    {
        if ($this->logEnabled) {
            if ($this->logger === null) {
                $this->logger = new Logger($this->docRoot . $this->logFilePath, $this->logFileSize * 1024 * 1024);
            }

            try {
                $this->logger->log($level, $message);
            } catch (\Throwable $e) {
                return;
            }
        }
    }

    public function getResponseHeaders(): array
    {
        return $this->client->getHeaders()->getHeaders();
    }

    public function getRequestHeaders(): array
    {
        return $this->client->getRequestHeaders()->getHeaders();
    }

    public static function convertEncoding($data, $targetCharset = 'UTF-8'): mixed
    {
        if (is_array($data)) {
            $convertedData = [];
            foreach ($data as $key => $value) {
                $convertedData[$key] = Client::convertEncoding($value, $targetCharset);
            }
        } else {
            $sourceCharset = Encoding::detectUtf8($data) ? 'UTF-8' : 'CP1251';
            $convertedData = Encoding::convertEncoding($data, $sourceCharset, $targetCharset);
        }

        return $convertedData;
    }

    protected function setHeaders(array $headers): void
    {
        $this->client->setHeaders($headers);
    }

    protected function setResult(array $params): void
    {
        if ($this->isPost()) {
            $this->client->post($this->uri->getLocator(), Json::encode($params, JSON_UNESCAPED_UNICODE));

        }

        if ($this->isGet()) {
            $this->uri->addParams($params);
            $this->client->get($this->uri->getUri());
        }
    }

    protected function isGet(): bool
    {
        return $this->requestType === HttpClient::HTTP_GET;
    }

    protected function isPost(): bool
    {
        return $this->requestType === HttpClient::HTTP_POST;
    }

    /**
     * @throws BoxberryApiException
     */
    public function apiRequest($requestType = HttpClient::HTTP_POST, $params = [], $headers = [], $cacheTime = 86400)
    {
        $credentials = [
            'token' => $this->token,
        ];

        if (isset($params['method'])) {
            $params['method'] = ucfirst($params['method']);
        }

        $this->requestType = $requestType;
        $headers = empty($headers) ? $this->defaultHeaders : $headers;

        $params = Client::convertEncoding(array_merge($credentials, $params));
        $cacheKey = md5($this->uri->getLocator() . $requestType . serialize($params) . serialize($headers));
        $cacheInitDir = self::CACHE_DIR . StringHelper::camel2snake($params['method']) . DIRECTORY_SEPARATOR;

        if ($this->cache->initCache($cacheTime, $cacheKey, $cacheInitDir)) {
            $this->log(LogLevel::INFO, $this->makeApiLogMessage(true, $requestType, $params, $headers, $this->cache->getVars()));
            $this->responseCode = 200;
            $this->authorization = true;
            return $this->cache->getVars();
        }

        $this->setHeaders($headers);
        $this->setResult($params);

        try {
            $responseBody = Json::decode($this->client->getResult());
        } catch (\Exception $e) {
            $this->log(LogLevel::ERROR, $e->getMessage());
            throw new BoxberryApiException($e->getMessage());
        }

        $this->responseCode = $this->client->getStatus();

        $this->responseCode === 200 ? $this->authorization = true : $this->authorization = false;

        if ($this->client->getStatus() === 200 || $this->client->getStatus() === 401) {
            $this->cache->startDataCache($cacheTime, $cacheKey, $cacheInitDir);
            $this->cache->endDataCache($responseBody);
            $this->log(LogLevel::INFO, $this->makeApiLogMessage(false, $requestType, $params, $headers, $responseBody));
            return $responseBody;
        }

        if ($errors = $this->client->getError()) {
            foreach ($errors as $errorCode => $errorMessage) {
                $this->log(LogLevel::ERROR, $errorMessage);
            }
        }

        if ($responseBody) {
            $this->log(LogLevel::ERROR, $this->makeApiLogMessage(false, $requestType, $params, $headers, $responseBody));
            throw new BoxberryApiException($responseBody);
        }

        throw new BoxberryApiException(Loc::getMessage('BB_INCORRECT_HTTP_RESULT_STATUS_CODE') . ':' . $this->client->getStatus() . ' | ' . $params['method']);

    }

    private function makeApiLogMessage($fromCache, $method, $params, $headers, $responseBody): string
    {
        $time = date('d.m.Y H:i:s');
        $logUrl = Client::convertEncoding(self::API_URL);
        $logMethod = Client::convertEncoding($method);
        $logParams = Client::convertEncoding($params);
        $logHeaders = Client::convertEncoding($headers);
        $logResponseBody = Client::convertEncoding($responseBody);

        $logMessage = "From cache: " . ($fromCache ? 'yes' : 'no') . "\n";
        $logMessage .= "Time: $time\n";
        $logMessage .= "URL: $logUrl\n";
        $logMessage .= "Method: $logMethod\n";
        $logMessage .= "Headers: " . print_r($logHeaders, true) . "\n";
        $logMessage .= "Parameters: " . print_r($logParams, true) . "\n";
        $logMessage .= "Response Body: " . print_r($logResponseBody, true) . "\n";

        return $logMessage;
    }

    /**
     * @throws BoxberryApiException
     */
    public function companyApiSettings(): CompanyApiSettings
    {
        $params = [
            'method' => __FUNCTION__
        ];

        $result = $this->apiRequest(HttpClient::HTTP_GET, $params, [], 300);

        return new CompanyApiSettings($result);
    }

    /**
     * @throws BoxberryApiException
     */
    public function parcelInfo($trackNumber): ParcelInfoResult
    {
        $params = [
            'method' => __FUNCTION__,
            'parcels' => [
                [
                    'track' => $trackNumber
                ]
            ]
        ];

        $result = $this->apiRequest(HttpClient::HTTP_POST, $params, [], 0);

        return new ParcelInfoResult($result);
    }


    /**
     * @throws BoxberryApiException
     */
    public function getKeyIntegration(): GetKeyIntegration
    {
        $params = [
            'method' => __FUNCTION__
        ];

        $key = $this->apiRequest(HttpClient::HTTP_GET, $params, [], 0);

        return new GetKeyIntegration($key);
    }

    /**
     * @throws BoxberryApiException
     */
    public function deliveryCalculation(DeliveryCalculationParams $deliveryCalculationParams): DeliveryCalculationResult
    {
        $costs = $this->apiRequest(HttpClient::HTTP_POST, $deliveryCalculationParams->toArray());
        return new DeliveryCalculationResult($costs);
    }

    /**
     * @param DeliveryCalculationParams[] $deliveryCalculationParamsArray
     * @throws BoxberryApiException
     */
    public function deliveryCalculationMulti(array $deliveryCalculationParamsArray): array
    {
        $results = [];
        foreach ($deliveryCalculationParamsArray as $deliveryCalculationParams) {
            $costs = $this->apiRequest(HttpClient::HTTP_POST, $deliveryCalculationParams->toArray());
            $results[] = new DeliveryCalculationResult($costs);
        }

        return $results;
    }

    /**
     * @throws BoxberryApiException
     */
    public function listCitiesFull($countryCode = '')
    {
        $params = [
            'method' => __FUNCTION__,
        ];

        if ($countryCode) {
            $params['CountryCode'] = $countryCode;
        }

        return $this->apiRequest(HttpClient::HTTP_GET, $params, [], 0);
    }

    /**
     * @throws BoxberryApiException
     */
    public function widgetSettings(): WidgetSettings
    {
        $params = [
            'method' => __FUNCTION__
        ];

        $widgetSettings = $this->apiRequest(HttpClient::HTTP_GET, $params);

        return new WidgetSettings($widgetSettings);
    }

    /**
     * @throws BoxberryApiException
     */
    public function zipCheck(string $zip): ZipCheck
    {
        $params = [
            'method' => __FUNCTION__,
            'Zip' => $zip
        ];

        $zipCheck = $this->apiRequest(HttpClient::HTTP_GET, $params);

        return new ZipCheck($zipCheck);
    }

    /**
     * @throws BoxberryApiException
     */
    public function pointsForParcels()
    {
        $params = [
            'method' => __FUNCTION__,
        ];

        return $this->apiRequest(HttpClient::HTTP_GET, $params, [], 0);
    }

    /**
     * @throws BoxberryApiException
     */
    public function pointsDescription(string $code, $photo = 0): PointsDescriptionResult
    {
        $params = [
            'method' => __FUNCTION__,
            'code' => $code,
            'photo' => $photo
        ];

        $data = $this->apiRequest(HttpClient::HTTP_GET, $params, [], 0);

        return new PointsDescriptionResult($data);
    }

    /**
     * @throws BoxberryApiException
     */
    public function parselCreate(ParcelParams $parcelParams): ParcelResult
    {
        $data = $this->apiRequest(HttpClient::HTTP_POST, $parcelParams->toArray(), [], 0);
        return new ParcelResult($data);
    }

    /**
     * @throws BoxberryApiException
     */
    public function parselSend(array $trackNumbers): ParselSendResult
    {
        $params = [
            'method' => __FUNCTION__,
            'ImIds' => implode(',', $trackNumbers)
        ];

        $data = $this->apiRequest(HttpClient::HTTP_GET, $params, [], 0);

        return new ParselSendResult($data);
    }

    /**
     * @throws BoxberryApiException
     */
    public function getLastStatusData(array $trackNumbers): GetLastStatusData
    {
        $params = [
            'method' => __FUNCTION__,
            'trackNumbers' => $trackNumbers
        ];

        $statuses = $this->apiRequest(HttpClient::HTTP_POST, $params, [], 0);

        return new GetLastStatusData($statuses);
    }

    /**
     * @throws BoxberryApiException
     */
    public function cancelOrder(string $trackNumber, string $cancelType = '1')
    {
        $params = [
            'method' => __FUNCTION__,
            'track' => $trackNumber,
            'cancelType' => $cancelType
        ];

        return $this->apiRequest(HttpClient::HTTP_POST, $params, [], 0);
    }

    /**
     * @throws BoxberryApiException
     */
    public function changeOrderStorageDate($storageDate, $trackNumber)
    {
        $params = [
            'method' => __FUNCTION__,
            'storageDate' => $storageDate,
            'track' => $trackNumber
        ];

        return $this->apiRequest(HttpClient::HTTP_GET, $params, [], 0);
    }

    public function getToken(): string
    {
        return $this->token;
    }

    public function setToken(string $token): void
    {
        $this->token = $token;
    }

    public function setTestToken(): void
    {
        $this->token = self::TEST_TOKEN;
    }

    public function getClient(): HttpClient
    {
        return $this->client;
    }

    public function setClient(HttpClient $client): void
    {
        $this->client = $client;
    }

    public function getCache(): Cache
    {
        return $this->cache;
    }

    public function setCache(Cache $cache): void
    {
        $this->cache = $cache;
    }

    public function getDefaultHeaders(): array
    {
        return $this->defaultHeaders;
    }

    public function setDefaultHeaders(array $defaultHeaders): void
    {
        $this->defaultHeaders = $defaultHeaders;
    }

    public static function getTestToken(): string
    {
        return self::TEST_TOKEN;
    }

    public static function getApiUrl(): string
    {
        return self::API_URL;
    }

    public function checkApiToken(): Result
    {
        $result = new Result();

        try {
            $key = $this->getKeyIntegration();
            $this->initSource();
            $result->setData(['key' => $key->getKey(), 'source' => $this->source]);
        } catch (BoxberryApiException $e) {
            $result->addError(new Error($e->getMessage()));
        }

        return $result;
    }

    public static function downloadFile($url, $fileName): Result
    {
        $httpClient = new HttpClient();
        $result = new Result();
        $absolutePath = Application::getDocumentRoot() . self::FILE_UPLOAD_DIR;
        $filePath = $absolutePath . $fileName;

        if (!Directory::isDirectoryExists($absolutePath)) {
            Directory::createDirectory($absolutePath);
        }

        if ($httpClient->download($url, $filePath)) {
            $fileUrl = self::FILE_UPLOAD_DIR . $fileName;

            $result->setData([
                'message' => Loc::getMessage('BB_FILE_DOWNLOADED_SUCCESSFULLY'),
                'path' => $fileUrl
            ]);
        } else {
            $result->addError(new Error(Loc::getMessage('BB_ERROR_DOWNLOAD_FILE') . $url, 0, ['url' => $url]));
        }

        return $result;
    }

    public static function getFilePathByrOrderId($orderId, $fileType = 'label'): ?string
    {
        $absolutePath = Application::getDocumentRoot() . self::FILE_UPLOAD_DIR;
        $fileName = $fileType . '_' . $orderId . '.pdf';
        $filePath = $absolutePath . $fileName;

        if (File::isFileExists($filePath)) {
            return self::FILE_UPLOAD_DIR . $fileName;
        }

        return null;
    }

    public static function getFilePathByName($fileName): ?string
    {
        $absolutePath = Application::getDocumentRoot() . self::FILE_UPLOAD_DIR;
        $filePath = $absolutePath . $fileName;

        if (File::isFileExists($filePath)) {
            return self::FILE_UPLOAD_DIR . $fileName;
        }

        return null;
    }

    public static function getParselSendNotIncludedTracks($errorMessage): array
    {
        $startPos = strpos($errorMessage, ':');
        if ($startPos !== false) {
            $idsStr = substr($errorMessage, $startPos + 1);
            $ids = explode(',', $idsStr);
            return array_map(function($id) {
                return trim($id, ' !');
            }, $ids);
        }

        return [];
    }

    public static function makeActFileNameByOrderIds($orderIds): string
    {
        return 'act_' . md5(implode('_', $orderIds)) . '.pdf';
    }

    public static function getModuleUpdate(string $url, $version, $archiveFormat): bool|string
    {
        $path = Application::getDocumentRoot() . Client::FILE_UPLOAD_DIR . 'updates/' . $version . '/boxberry' . $archiveFormat;

        if ((new HttpClient())->download($url, $path)) {
            return $path;
        }

        return false;
    }

    public static function checkModuleUpdate(): Result
    {
        return self::updateRequest(json_encode(self::getCheckUpdateArray()));
    }

    public static function logSuccessUpdate(): Result
    {
        return self::updateRequest(json_encode(array_merge(self::getCheckUpdateArray(), ['status' => 'success'])));
    }

    private static function updateRequest($postData): Result
    {
        $result = new Result();
        $httpClient = new HttpClient();
        $httpClient->setHeader('Content-Type', 'application/json');

        $httpClient->post(self::MODULE_UPDATE_URL, $postData);

        $response = $httpClient->getResult();
        $statusCode = $httpClient->getStatus();

        try {
            $response = Json::decode($response);
        } catch (\Exception $e) {
            $result->addError(new Error($e->getMessage()));
        }

        if ($statusCode === 200 && $response) {
            $result->setData($response);
        } else {
            $result->addError(new Error($response['error'], $statusCode));
        }

        return $result;

    }

    private static function getCheckUpdateArray(): array
    {
        return [
            'client_version' => Options::getModuleVersion(),
            'client_encoding' => LANG_CHARSET === 'windows-1251' ? 'cp1251' : 'utf8',
            'client_host' => $_SERVER['HTTP_HOST'],
            'archive_format' => \CBXArchive::GetAvailableFormats()
        ];
    }

    /**
     * @throws BoxberryApiException
     * @throws ArgumentException
     */
    public static function daDataRequest($address): DadataResult
    {
        $cache = Cache::createInstance();
        $cacheTime = 86400;
        $cacheId = md5($address);

        if ($cache->initCache($cacheTime, $cacheId, self::CACHE_DIR . 'dadata' . DIRECTORY_SEPARATOR)) {
            $result = $cache->getVars();
        } else {
            $params = [
                'query' => $address,
                'locations' => [
                    [
                        'country' => '*',
                    ]
                ]
            ];

            $headers = [
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
                'Authorization' => Options::isEnableDadataUserToken() ? 'Token ' . Options::getDadataUserToken() : self::DADATA_TOKEN
            ];

            $httpClient = new HttpClient();
            $httpClient->setHeaders($headers);
            $httpClient->post(self::DADATA_API_URL, json_encode(Client::convertEncoding($params), JSON_UNESCAPED_UNICODE));
            $responseBody = $httpClient->getResult();

            $result = new DadataResult(Json::decode($responseBody));

            if ($cache->startDataCache()) {
                $cache->endDataCache($result);
            }
        }

        return $result;
    }

    public function getSource(): string
    {
        return $this->source;
    }

    public function setSource(string $source): void
    {
        $this->source = $source;
        Option::set(Options::getModuleId(), substr($this->token, 0, 8) . '_' . 'SOURCE', $source);
    }

    public function getResponseCode(): int
    {
        return $this->responseCode;
    }

    public function setResponseCode(int $responseCode): void
    {
        $this->responseCode = $responseCode;
    }

    public function isYaDelivery(): bool
    {
        return $this->yaDelivery;
    }

    public function setYaDelivery(bool $yaDelivery): void
    {
        $this->yaDelivery = $yaDelivery;
    }

    public function isAuthorization(): bool
    {
        return $this->authorization;
    }

    public function setAuthorization(bool $authorization): void
    {
        $this->authorization = $authorization;
    }

}

Youez - 2016 - github.com/yon3zu
LinuXploit