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/cvetdv.ru/bitrix/modules/sale/handlers/paysystem/tbankbusiness/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/cvetdv.ru/bitrix/modules/sale/handlers/paysystem/tbankbusiness/handler.php
<?php
namespace Sale\Handlers\PaySystem;

use Bitrix\Crm;
use Bitrix\Crm\EntityPreset;
use Bitrix\Crm\EntityRequisite;
use Bitrix\Main;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\PhoneNumber;
use Bitrix\Main\Request;
use Bitrix\Main\Web;
use Bitrix\Sale\BasketItem;
use Bitrix\Sale\Order;
use Bitrix\Sale\PayableBasketItem;
use Bitrix\Sale\Payment;
use Bitrix\Sale\PaymentCollection;
use Bitrix\Sale\PaySystem;
use Bitrix\Sale\PriceMaths;
use Bitrix\Sale\Services\Base\RestrictionInfoCollection;
use Bitrix\Sale\Services\PaySystem\Restrictions\RestrictableServiceHandler;
use Bitrix\Sale\Services\PaySystem\Restrictions\RestrictionCurrencyTrait;
use Bitrix\Sale\Services\PaySystem\Restrictions\RestrictionPersonTypeTrait;

class TBankBusinessHandler extends PaySystem\BaseServiceHandler implements RestrictableServiceHandler
{
	use RestrictionCurrencyTrait;
	use RestrictionPersonTypeTrait;

	protected const SANDBOX_URL = 'https://business.tbank.ru/openapi/sandbox/';
	protected const PRODUCTION_URL = 'https://business.tbank.ru/openapi/';

	public const ERROR_CODE_SYSTEM_FAILURE = -1;
	public const ERROR_CODE_RESPONSE_FAILURE = -2;
	public const ERROR_CODE_BAD_INVOICE_SUM = -3;
	public const ERROR_CODE_BAD_INVOICE_PARAMS = -4;

	protected const ERROR_STATUS_BAD_JSON = -1;

	protected const PAYMENT_STATUS_DRAFT = 'DRAFT';
	protected const PAYMENT_STATUS_SUBMITTED = 'SUBMITTED';
	protected const PAYMENT_STATUS_EXECUTED = 'EXECUTED';

	protected const PAYMENT_CURRENCY_RUB = 'RUB';

	protected const RESPONSE_STATUS_200 = 200;
	protected const RESPONSE_STATUS_400 = 400;
	protected const RESPONSE_STATUS_401 = 401;
	protected const RESPONSE_STATUS_403 = 403;
	protected const RESPONSE_STATUS_422 = 422;
	protected const RESPONSE_STATUS_429 = 429;
	protected const RESPONSE_STATUS_500 = 500;

	protected const RESPONSE_ERROR_INVOICE_NOT_FOUND = 'INVOICE_NOT_FOUND';

	protected const TEMPLATE_INVOICE_INFO = 'template';
	protected const TEMPLATE_INVOICE_STATUS = 'template_status';
	protected const TEMPLATE_INVOICE_EXPIRED = 'template_expired';

	public function initiatePay(Payment $payment, ?Request $request = null): PaySystem\ServiceResult
	{
		$result = new PaySystem\ServiceResult();

		if (!Loader::includeModule('crm'))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_MODULE_CRM_ABSENT')));

			return $result;
		}

		$invoiceState = [];
		if ($payment->getField('PS_INVOICE_ID'))
		{
			$checkInvoiceResult = $this->checkInvoiceState($payment);
			if ($this->isInvalidCheckInvoiceResult($checkInvoiceResult))
			{
				return $checkInvoiceResult;
			}
			$invoiceState = $checkInvoiceResult->getData();
			unset($checkInvoiceResult);
		}

		if ($this->needCreateInvoice($invoiceState))
		{
			$createInvoiceResult = $this->createInvoice($payment);
			if (!$createInvoiceResult->isSuccess())
			{
				return $createInvoiceResult;
			}

			$invoiceState = $createInvoiceResult->getData();

			if (isset($invoiceState['response']['invoiceId']))
			{
				$result->setPsData(['PS_INVOICE_ID' => $invoiceState['response']['invoiceId']]);
			}
		}

		$template = $this->getTemplateName($payment, $invoiceState);

		$this->setExtraParams(
			$this->getTemplateParams($payment, $template, $invoiceState)
		);

		$result->setTemplate($this->showTemplate($payment, $template)->getTemplate());

		return $result;
	}

	/**
	 * @return array
	 */
	public function getCurrencyList(): array
	{
		return [
			self::PAYMENT_CURRENCY_RUB,
		];
	}

	/**
	 * Returns list of restrictions that installed on service add.
	 * Add person type restriction.
	 *
	 * @return RestrictionInfoCollection
	 */
	public function getRestrictionList(): RestrictionInfoCollection
	{
		$collection = new RestrictionInfoCollection();

		$this->getRestrictionCurrency($collection);
		$this->getRestrictionEntityPersonType($collection);

		return $collection;
	}

	/**
	 * Returns true, if payment in test mode.
	 * @param Payment|null $payment Payment information.
	 * @return bool
	 */
	protected function isTestMode(?Payment $payment = null): bool
	{
		return ($this->getBusinessValue($payment, 'TBB_TEST_MODE') === 'Y');
	}

	/**
	 * @inheritDoc
	 */
	public function getClientType($psMode): string
	{
		return PaySystem\ClientType::B2B;
	}

	/**
	 * @return array
	 */
	protected function getUrlList(): array
	{
		return [
			'invoice' => [
				self::TEST_URL => self::SANDBOX_URL . 'api/v1/invoice/send',
				self::ACTIVE_URL => self::PRODUCTION_URL.'api/v1/invoice/send',
			],
			'invoiceCheck' => [
				self::TEST_URL => self::SANDBOX_URL . 'api/v1/openapi/invoice/{invoiceId}/info',
				self::ACTIVE_URL => self::PRODUCTION_URL . 'api/v1/openapi/invoice/{invoiceId}/info',
			],
		];
	}

	/**
	 * Returns string with T-Bank authorization token from seo-proxy server.
	 *
	 * @return string|null
	 */
	protected function getTBankAuthToken(): ?string
	{
		if (!Main\Loader::includeModule('seo'))
		{
			return null;
		}

		\Bitrix\Seo\Service::clearClientsCache();
		$authAdapter = \Bitrix\Seo\Checkout\Service::getAuthAdapter(\Bitrix\Seo\Checkout\Service::TYPE_TBANK_BUSINESS);

		return $authAdapter->getToken();
	}

	/**
	 * Returns T-Bank sandbox authorization token.
	 *
	 * @return string
	 */
	protected function getTBankTestToken(): string
	{
		return 'TinkoffOpenApiSandboxSecretToken';
	}

	/**
	 * Returns query headers.
	 *
	 * @param Payment $payment Payment information.
	 * @return array
	 */
	protected function getHeaders(Payment $payment): array
	{
		$token =
			$this->isTestMode($payment)
				? $this->getTBankTestToken()
				: $this->getTBankAuthToken()
		;

		return [
			'Content-Type' => 'application/json',
			'Accept' => 'application/json',
			'Authorization' => 'Bearer ' . $token,
		];
	}

	/**
	 * @param Payment $payment
	 * @param array $invoiceStatus
	 * @return string
	 */
	protected function getTemplateName(Payment $payment, array $invoiceStatus = []): string
	{
		$template = null;

		if (
			$this->isExistDatePayBefore($payment)
			&& !$this->isValidDatePayBefore($payment)
		)
		{
			$template = self::TEMPLATE_INVOICE_EXPIRED;
		}
		else
		{
			$currentStatus = ($invoiceStatus['response']['status'] ?? '');
			if ($this->isValidPaymentStatus($currentStatus))
			{
				$template = self::TEMPLATE_INVOICE_STATUS;
			}
		}

		return $template ?? self::TEMPLATE_INVOICE_INFO;
	}

	protected function getTemplateParams(Payment $payment, $template, $invoiceState = []) : array
	{
		$result = [];
		switch ($template)
		{
			case self::TEMPLATE_INVOICE_INFO:
				$result = $this->getInvoiceSumTemplateParams($payment);

				if (isset($invoiceState['response']['pdfUrl']))
				{
					$result['INVOICE_URL'] = $invoiceState['response']['pdfUrl'];
				}

				if (isset($invoiceState['params']['dueDate']))
				{
					$dueDate = new Main\Type\Date(
						$invoiceState['params']['dueDate'],
						'Y-m-d'
					);
					$result['INVOICE_DUE_DATE'] = $dueDate->toString();
				}
				break;
			case self::TEMPLATE_INVOICE_STATUS:
				$result = $this->getInvoiceSumTemplateParams($payment);

				$result['INVOICE_STATUS'] = $this->getInvoiceStatusTitle(
					$invoiceState['response']['status'] ?? ''
				);
				break;
		}

		return $result;
	}

	/**
	 * Returns invoice sum for templates.
	 *
	 * @param Payment $payment Payment description.
	 * @return array
	 */
	protected function getInvoiceSumTemplateParams(Payment $payment): array
	{
		Loader::includeModule('currency');

		$result = [];

		$invoiceSum = $this->getInvoiceSum($payment);
		if ($invoiceSum !== null)
		{
			$result['INVOICE_SUM'] = $invoiceSum;
			$result['INVOICE_SUM_FORMATTED'] = \CCurrencyLang::CurrencyFormat(
				$invoiceSum,
				self::PAYMENT_CURRENCY_RUB
			);
		}

		return $result;
	}

	/**
	 * @param array $data
	 * @return string|false
	 */
	private static function encode(array $data): bool|string
	{
		try
		{
			return Web\Json::encode($data, JSON_UNESCAPED_UNICODE);
		}
		catch (Main\ArgumentException)
		{
			return false;
		}
	}

	/**
	 * @param string $data
	 * @return mixed
	 */
	private static function decode(string $data): mixed
	{
		try
		{
			return Web\Json::decode($data);
		}
		catch (Main\ArgumentException)
		{
			return false;
		}
	}

	protected function checkInvoiceState(Payment $payment): PaySystem\ServiceResult
	{
		$url = str_replace(
			'{invoiceId}',
			$payment->getField('PS_INVOICE_ID'),
			$this->getUrl($payment, 'invoiceCheck')
		);

		return $this->send(
			Web\Http\Method::GET,
			$url,
			$this->getHeaders($payment)
		);
	}

	protected function isInvalidCheckInvoiceResult(PaySystem\ServiceResult $result): bool
	{
		if ($result->isSuccess())
		{
			return false;
		}

		if ($this->isInvoiceNotFound($result->getData()))
		{
			return false;
		}

		return true;
	}

	protected function isInvoiceNotFound(array $invoiceState): bool
	{
		$status = (int)($invoiceState['status'] ?? 0);
		$errorCode = $invoiceState['response']['errorCode'] ?? '';

		return
			$status === self::RESPONSE_STATUS_422
			&& $errorCode === self::RESPONSE_ERROR_INVOICE_NOT_FOUND
		;
	}

	protected function needCreateInvoice(array $invoiceState = []): bool
	{
		if (empty($invoiceState))
		{
			return true;
		}
		$currentStatus = ($invoiceState['response']['status'] ?? '');
		if ($this->isValidPaymentStatus($currentStatus))
		{
			return false;
		}

		if ($this->isInvoiceNotFound($invoiceState))
		{
			return true;
		}

		return false;
	}

	/**
	 * @param Payment $payment
	 * @return PaySystem\ServiceResult
	 */
	protected function createInvoice(Payment $payment): PaySystem\ServiceResult
	{
		if (!$this->isInvoiceSumCorrect($payment))
		{
			$result = new PaySystem\ServiceResult();
			$result->addError(new Main\Error(
				Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_BAD_INVOICE_SUM'),
				self::ERROR_CODE_BAD_INVOICE_SUM
			));

			return $result;
		}

		$invoiceQueryParams = $this->getInvoiceQueryParams($payment);
		$result = $this->checkInvoiceQueryParams($invoiceQueryParams);
		if (!$result->isSuccess())
		{
			$this->addDebugInfo(
				Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_INVALID_INVOICE_PARAMS'),
				$invoiceQueryParams
			);

			return $result;
		}

		return $this->send(
			Web\Http\Method::POST,
			$this->getUrl($payment, 'invoice'),
			$this->getHeaders($payment),
			$invoiceQueryParams
		);
	}

	protected function getInvoiceQueryParams(Payment $payment): array
	{
		$result = [
			'invoiceNumber' => (string)$payment->getId(), // digital identifier
			'payer' => $this->getPayerData($payment),
			'items' => $this->getProductsForInvoice($payment),
			'contactPhone' => $this->getContactPhone($payment),
		];

		$email = $this->getEmail($payment);
		if ($email)
		{
			$result['contacts'] = [
				[
					'email' => $email,
				]
			];
		}

		$comment = $this->getInvoiceComment($payment);
		if ($comment !== '')
		{
			$result['comment'] = $comment;
		}

		$dueDate = $this->getDueDate($payment);
		if (!empty($dueDate))
		{
			$result['dueDate'] = $dueDate;
		}

		return $result;
	}

	protected function checkInvoiceQueryParams(array $invoiceQueryParams): PaySystem\ServiceResult
	{
		$result = new PaySystem\ServiceResult();

		if (empty($invoiceQueryParams['payer']))
		{
			$result->addError(new Main\Error(
				Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_INVALID_PAYER_DATA'),
				self::ERROR_CODE_BAD_INVOICE_PARAMS
			));
		}
		if (empty($invoiceQueryParams['items']))
		{
			$result->addError(new Main\Error(
				Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_INVALID_INVOICE_ITEMS'),
				self::ERROR_CODE_BAD_INVOICE_PARAMS
			));
		}

		return $result;
	}

	protected function getDueDate(Payment $payment): string
	{
		if (!$this->isValidDatePayBefore($payment))
		{
			return '';
		}
		/** @var Main\Type\Date $datePayBefore */
		$datePayBefore = $payment->getField('DATE_PAY_BEFORE');

		return $datePayBefore->format('Y-m-d');
	}

	protected function getPayerData(Payment $payment): ?array
	{
		/** @var PaymentCollection $collection */
		$collection = $payment->getCollection();
		$order = $collection->getOrder();

		$clientCollection = $this->getClientCollection($order);
		if ($clientCollection === null)
		{
			return null;
		}

		$company = $clientCollection->getPrimaryCompany();
		if ($company === null)
		{
			return null;
		}

		$requisite =
			(
				new Crm\Requisite\DefaultRequisite(
					new Crm\ItemIdentifier(
						\CCrmOwnerType::Company,
						(int)$company->getField('ENTITY_ID')
					)
				)
			)
			->setCheckPermissions(false)
		;
		$requisiteValues = $requisite->get();

		$title = trim((string)$company->getCustomerName());
		$inn = trim((string)($requisiteValues['RQ_INN'] ?? ''));
		$kpp = trim((string)($requisiteValues['RQ_KPP'] ?? ''));

		if ($title === '' || $inn === '')
		{
			return null;
		}

		if ($kpp === '')
		{
			if (!isset($requisiteValues['PRESET_ID']))
			{
				return null;
			}

			$companyPreset = EntityPreset::getSingleInstance()->getById($requisiteValues['PRESET_ID']);

			if (
				is_array($companyPreset)
				&& isset($companyPreset['XML_ID'])
				&& (string)$companyPreset['XML_ID'] === EntityRequisite::XML_ID_DEFAULT_PRESET_RU_COMPANY
			)
			{
				return null;
			}

			$kpp = '0';
		}

		return [
			'name' => $title,
			'inn' => $inn,
			'kpp' => $kpp,
		];
	}

	protected function getProductsForInvoice(Payment $payment): array
	{
		$catalogIncluded = Loader::includeModule('catalog');
		/** @var PaymentCollection $paymentCollection */
		$paymentCollection = $payment->getCollection();

		$order = $paymentCollection->getOrder();
		$basket = $order->getBasket();

		$defaultMeasure = '';
		if ($catalogIncluded)
		{
			$measureDescription = \CCatalogMeasure::getDefaultMeasure(true, false);
			$defaultMeasure = $measureDescription['SYMBOL_RUS'];
			unset($measureDescription);
		}

		$result = [];
		// /** @var BasketItem $basketItem */
		/*
		foreach ($basket->getBasketItems() as $basketItem)
		{
			$row = [
				'name' => $basketItem->getField('NAME'),
				'amount' => $basketItem->getQuantity(),
				'price' => $basketItem->getPriceWithVat(),
			];

			$vat = $basketItem->getVatRate();
			if ($vat === null)
			{
				$vat = 'None';
			}
			else
			{
				$vat = (string)((int)((float)$vat * 100));
			}
			$row['vat'] = $vat;
			$row['unit'] = (string)$basketItem->getField('MEASURE_NAME') ?: $defaultMeasure;

			$result[] = $row;
		}
		*/
		/** @var PayableBasketItem $payableBasketItem */
		foreach ($payment->getPayableItemCollection()->getBasketItems() as $payableBasketItem)
		{
			/** @var BasketItem $basketItem */
			$basketItem = $basket->getItemById($payableBasketItem->getField('ENTITY_ID'));
			if ($basketItem)
			{
				$row = [
					'name' => $basketItem->getField('NAME'),
					'amount' => $basketItem->getQuantity(),
					'price' => $basketItem->getPriceWithVat(),
				];

				$vat = $basketItem->getVatRate();
				if ($vat === null)
				{
					$vat = 'None';
				}
				else
				{
					$vat = (string)((int)((float)$vat * 100));
				}
				$row['vat'] = $vat;
				$row['unit'] = (string)$basketItem->getField('MEASURE_NAME') ?: $defaultMeasure;

				$result[] = $row;
			}
		}

		return $result;
	}

	/**
	 * Returns contact phone for sms notification.
	 *
	 * @param Payment $payment Payment description.
	 * @return string
	 */
	protected function getContactPhone(Payment $payment): string
	{
		/** @var PaymentCollection $collection */
		$collection = $payment->getCollection();
		$phoneNumber = $this->getClientPhoneNumber($collection->getOrder());

		return
			$phoneNumber
				? $this->normalizePhoneNumber($phoneNumber)
				: ''
		;
	}

	/**
	 * Returns client or company phone number, if exists.
	 *
	 * @param Order $order Crm order.
	 * @return string|null
	 */
	protected function getClientPhoneNumber(Order $order): ?string
	{
		$clientCollection = $this->getClientCollection($order);
		if (!$clientCollection)
		{
			return null;
		}

		$phoneNumber = null;

		$clientId = $this->getPrimaryContactId($clientCollection);
		$entityId = \CCrmOwnerType::ContactName;

		if ($clientId === null)
		{
			$clientId = $this->getPrimaryCompanyId($clientCollection);
			$entityId = \CCrmOwnerType::CompanyName;
		}

		if ($clientId)
		{
			$crmFieldMultiResult = \CCrmFieldMulti::GetList(
				[
					'ID' => 'desc',
				],
				[
					'ENTITY_ID' => $entityId,
					'ELEMENT_ID' => $clientId,
					'TYPE_ID' => 'PHONE',
				]
			);
			while ($crmFieldMultiData = $crmFieldMultiResult->Fetch())
			{
				$phoneNumber = $crmFieldMultiData['VALUE'];
				if ($phoneNumber)
				{
					break;
				}
			}
			unset(
				$crmFieldMultiData,
				$crmFieldMultiResult,
			);
		}

		return $phoneNumber;
	}

	/**
	 * Returns empty string or phone number in E164 format - +71234567890.
	 *
	 * @param string $phoneNumber Raw phone number.
	 * @return string
	 */
	protected function normalizePhoneNumber(string $phoneNumber): string
	{
		$phoneNumber = trim($phoneNumber);
		if ($phoneNumber === '')
		{
			return '';
		}

		$parser = PhoneNumber\Parser::getInstance();
		$number = $parser->parse($phoneNumber);

		return (string)$number->format(PhoneNumber\Format::E164);
	}

	protected function getEmail(Payment $payment): ?string
	{
		/** @var PaymentCollection $collection */
		$collection = $payment->getCollection();
		$order = $collection->getOrder();
		$userEmail = $order->getPropertyCollection()->getUserEmail();

		return $userEmail?->getValue();
	}

	protected function getInvoiceComment(Payment $payment): string
	{
		/** @var PaymentCollection $collection */
		$collection = $payment->getCollection();
		$order = $collection->getOrder();

		$description =  str_replace(
			[
				'#PAYMENT_NUMBER#',
				'#ORDER_NUMBER#',
				'#PAYMENT_ID#',
				'#ORDER_ID#',
				'#USER_EMAIL#',
			],
			[
				$payment->getField('ACCOUNT_NUMBER'),
				$order->getField('ACCOUNT_NUMBER'),
				$payment->getId(),
				$order->getId(),
				(string)$this->getEmail($payment),
			],
			$this->getBusinessValue($payment, 'TBB_COMMENT_TEMPLATE') ?? ''
		);

		return mb_substr(trim($description), 0, 1000);
	}

	protected function getInvoiceSum(Payment $payment): ?float
	{
		/** @var PaymentCollection $paymentCollection */
		$paymentCollection = $payment->getCollection();

		$order = $paymentCollection->getOrder();
		$basket = $order->getBasket();

		$found = false;
		$price = 0.0;
		// /** @var BasketItem $basketItem */
		/*
		foreach ($basket->getBasketItems() as $basketItem)
		{
			$found = true;
			$price += $basketItem->getFinalPrice();
		}
		*/
		/** @var PayableBasketItem $payableBasketItem */
		foreach ($payment->getPayableItemCollection()->getBasketItems() as $payableBasketItem)
		{
			/** @var BasketItem $basketItem */
			$basketItem = $basket->getItemById($payableBasketItem->getField('ENTITY_ID'));
			if ($basketItem)
			{
				$found = true;
				$price += $basketItem->getFinalPrice();
			}
		}

		return
			$found
				? $price
				: null
		;
	}

	/**
	 * Returns true, if payment sum equals calculated basket sum.
	 *
	 * @param Payment $payment Payment object.
	 * @return bool
	 */
	protected function isInvoiceSumCorrect(Payment $payment): bool
	{
		$paymentSum = PriceMaths::roundPrecision($payment->getSum());
		$invoiceSum = $this->getInvoiceSum($payment);

		$this->addDebugInfo(
			'invoiceSum',
			[
				'invoiceSum' => $invoiceSum,
				'paymentSum' => $paymentSum,
			]
		);

		return $paymentSum === $invoiceSum;
	}

	protected function send(string $method, string $url, array $headers, array $params = []): PaySystem\ServiceResult
	{
		$result = new PaySystem\ServiceResult();

		$httpClient = new Web\HttpClient();
		$httpClient->setHeaders($headers);

		switch ($method)
		{
			case Web\Http\Method::GET:
				$response = $httpClient->get($url);
				break;
			case Web\Http\Method::POST:
				$postData = null;
				if ($params)
				{
					$postData = static::encode($params);
				}
				$this->addDebugInfo('request data', $postData);
				$response = $httpClient->post($url, $postData);
				break;
			default:
				$response = null;
				break;
		}

		if ($response === null)
		{
			$result->addError(new Main\Error(
				Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_UNSUPPORTED_PROTOCOL'),
				self::ERROR_CODE_SYSTEM_FAILURE
			));

			return $result;
		}

		$this->addDebugInfo('response data', $response);

		$status = $httpClient->getStatus();
		$response = static::decode($response);
		if (!is_array($response))
		{
			$status = self::ERROR_STATUS_BAD_JSON;
		}

		switch ($status)
		{
			case self::ERROR_STATUS_BAD_JSON:
				$result->setData([
					'params' => $params,
					'status' => $status,
				]);
				$result->addError(new Main\Error(
					Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_UNKNOWN_ANSWER'),
					self::ERROR_CODE_SYSTEM_FAILURE
				));
				break;
			case self::RESPONSE_STATUS_200:
				$result->setData([
					'params' => $params,
					'response' => $response,
					'status' => $status,
				]);
				break;
			case self::RESPONSE_STATUS_400:
			case self::RESPONSE_STATUS_401:
			case self::RESPONSE_STATUS_403:
			case self::RESPONSE_STATUS_422:
			case self::RESPONSE_STATUS_429:
			case self::RESPONSE_STATUS_500:
			default:
				$result->setData([
					'params' => $params,
					'response' => $response,
					'status' => $status,
				]);
				$result->addError($this->getResponseError($status, $response));
				$this->addDebugInfo('invalid request', $response);
				break;
		}

		return $result;
	}

	protected function addDebugInfo(string $message, mixed $data): void
	{
		if ($message === '')
		{
			return;
		}
		if (is_array($data) || is_bool($data))
		{
			$data = mydump($data);
		}
		elseif (is_object($data))
		{
			if (method_exists($data, '__toString'))
			{
				$data = (string)$data;
			}
			else
			{
				$data = mydump($data);
			}
		}
		PaySystem\Logger::addDebugInfo(__CLASS__ . ': ' . $message . ': ' . $data);
	}

	protected function getResponseError(int $status, mixed $response): Main\Error
	{
		$error = match ($status)
		{
			self::RESPONSE_STATUS_400 => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_400_INVALID_REQUEST'),
			self::RESPONSE_STATUS_401 => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_401_BAD_AUTHENTICATION'),
			self::RESPONSE_STATUS_403 => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_403_BAD_AUTHORIZATION'),
			self::RESPONSE_STATUS_422 => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_422_BAD_DATA'),
			self::RESPONSE_STATUS_429 => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_429_TOO_MANY_REQUESTS'),
			self::RESPONSE_STATUS_500 => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_ERROR_500_SERVER'),
			default => Loc::getMessage(
				'SALE_HPS_TBANK_BUSINESS_ERROR_UNKNOWN_STATUS',
				[
					'#STATUS#' => $status,
				]
			),
		};

		$message = '';
		if (isset($response['errorMessage']))
		{
			$message = $response['errorMessage'];
			if (isset($response['errorDetails']) && is_array($response['errorDetails']))
			{
				$message .= '. ' . implode(', ', $response['errorDetails']);
			}
		}

		return new Main\Error(
			$message ?: $error,
			$response['errorCode'] ?? self::ERROR_CODE_RESPONSE_FAILURE
		);
	}

	protected function getInvoiceStatusTitle(string $status): string
	{
		return (string)match ($status)
		{
			self::PAYMENT_STATUS_DRAFT => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_INVOICE_STATUS_DRAFT'),
			self::PAYMENT_STATUS_SUBMITTED => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_INVOICE_STATUS_SUBMITTED'),
			self::PAYMENT_STATUS_EXECUTED => Loc::getMessage('SALE_HPS_TBANK_BUSINESS_INVOICE_STATUS_EXECUTED'),
			default => '',
		};
	}

	protected function isValidPaymentStatus(string $status): bool
	{
		return
			$status === self::PAYMENT_STATUS_DRAFT
			|| $status === self::PAYMENT_STATUS_SUBMITTED
			|| $status === self::PAYMENT_STATUS_EXECUTED
		;
	}

	protected function isValidDatePayBefore(Payment $payment): bool
	{
		$datePayBefore = $payment->getField('DATE_PAY_BEFORE');
		if ($datePayBefore instanceof Main\Type\Date)
		{
			$currentDate = new Main\Type\Date();
			if ($datePayBefore->getTimestamp() >= $currentDate->getTimestamp())
			{
				return true;
			}
		}

		return false;
	}

	protected function isExistDatePayBefore(Payment $payment): bool
	{
		return $payment->getField('DATE_PAY_BEFORE') instanceof Main\Type\Date;
	}

	protected function getClientCollection(Order $order): ?Crm\Order\ContactCompanyCollection
	{
		if ($order instanceof Crm\Order\Order)
		{
			return $order->getContactCompanyCollection();
		}

		return null;
	}

	protected function getPrimaryCompanyId(Crm\Order\ContactCompanyCollection $collection): ?int
	{
		$company = $collection->getPrimaryCompany();
		if ($company !== null)
		{
			$companyId = $company->getField('ENTITY_ID');

			return $companyId === null ? null : (int)$companyId;
		}

		return null;
	}

	protected function getPrimaryContactId(Crm\Order\ContactCompanyCollection $collection): ?int
	{
		$contact = $collection->getPrimaryContact();
		if ($contact !== null)
		{
			$contactId = $contact->getField('ENTITY_ID');

			return $contactId === null ? null : (int)$contactId;
		}

		return null;
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit