2namespace Sale\Handlers\PaySystem;
15 private const API_VERSION_V1 =
'v1';
17 private const MODE_CHECKOUT =
'checkout';
19 private const SEND_METHOD_GET =
'get';
20 private const SEND_METHOD_POST =
'post';
22 private const HTTP_CODE_OK = 200;
23 private const HTTP_CODE_UNAUTHORIZED = 401;
24 private const HTTP_CODE_UNPROCESSABLE_ENTITY = 422;
25 private const HTTP_CODE_INTERNAL_SERVER_ERROR = 500;
27 private const BITRIX_LABEL =
'wp_bitrix';
29 private const REQUEST_PAY_SYSTEM_ID_PARAM =
'paySystemId';
30 private const REQUEST_PAYMENT_ID_PARAM =
'paymentId';
31 private const REQUEST_SOURCE_PARAM =
'source';
33 private const HISTORY_STATUS_PAID = 14;
35 private const INVOICE_ID_DELIMITER =
'#';
36 private const REFERENCE_ID_DELIMITER =
'_';
43 return Sale\PaySystem\Manager::getHandlerDescription(
'Wooppay')[
'HANDLER_MODE_LIST'];
49 private function isCheckoutMode(): bool
51 return $this->service->getField(
'PS_MODE') === self::MODE_CHECKOUT;
67 public function initiatePay(Sale\Payment
$payment, Main\Request
$request =
null): Sale\PaySystem\ServiceResult
69 $result =
new Sale\PaySystem\ServiceResult();
72 if (!$authResult->isSuccess())
74 $result->addErrors($authResult->getErrors());
78 $createInvoiceResult = $this->createInvoice(
$payment, $authResult->getData()[
'token']);
79 if (!$createInvoiceResult->isSuccess())
81 $result->addErrors($createInvoiceResult->getErrors());
85 $createInvoiceData = $createInvoiceResult->getData();
88 'PS_INVOICE_ID' => implode(
89 self::INVOICE_ID_DELIMITER,
91 $createInvoiceData[
'response'][
'invoice_id'],
92 $createInvoiceData[
'response'][
'operation_id'],
97 $templateParams = $this->getTemplateParams(
$payment);
98 $templateParams[
'url'] = $createInvoiceData[
'operation_url'];
102 if ($showTemplateResult->isSuccess())
104 $result->setTemplate($showTemplateResult->getTemplate());
108 $result->addErrors($showTemplateResult->getErrors());
111 if ($this->isCheckoutMode())
113 $result->setPaymentUrl($createInvoiceData[
'operation_url']);
124 private function getTemplateParams(Sale\Payment
$payment):
array
127 'sum' => Sale\PriceMaths::roundPrecision(
$payment->getSum()),
128 'currency' =>
$payment->getField(
'CURRENCY'),
135 private function getTemplateName(): string
137 return (
string)$this->service->getField(
'PS_MODE');
149 private function auth(Sale\Payment
$payment): Sale\PaySystem\ServiceResult
151 $result =
new Sale\PaySystem\ServiceResult();
158 $headers = $this->getHeaders();
160 $sendResult = $this->send(self::SEND_METHOD_POST,
$url, $headers,
$params);
161 if ($sendResult->isSuccess())
163 $sendData = $sendResult->getData();
164 if (empty($sendData[
'token']))
168 Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_ERROR_TOKEN_NOT_FOUND')
179 $result->addErrors($sendResult->getErrors());
198 private function createInvoice(Sale\Payment
$payment,
string $token): Sale\PaySystem\ServiceResult
200 $result =
new Sale\PaySystem\ServiceResult();
204 'reference_id' => $this->getReferenceId(
$payment),
205 'amount' => (string)
$payment->getSum(),
207 'add_info' => $this->getPaymentDescription(
$payment),
208 'request_url' => $this->getRequestUrl(
$payment),
209 'back_url' => $this->getBackUrl(
$payment),
212 if ($phoneNumber = $this->getPhoneNumber(
$payment))
214 $params[
'user_phone'] = $phoneNumber;
219 $params[
'service_name'] = $serviceName;
222 $headers = $this->getHeaders();
223 $headers[
'Authorization'] = $token;
225 $sendResult = $this->send(self::SEND_METHOD_POST,
$url, $headers,
$params);
226 if ($sendResult->isSuccess())
228 $result->setData($sendResult->getData());
232 $result->addErrors($sendResult->getErrors());
242 private function getReferenceId(Sale\Payment
$payment): string
244 return implode(self::REFERENCE_ID_DELIMITER, [self::BITRIX_LABEL,
$payment->getId(), uniqid()]);
256 protected function getPaymentDescription(Sale\Payment
$payment)
259 $collection =
$payment->getCollection();
260 $order = $collection->getOrder();
261 $userEmail =
$order->getPropertyCollection()->getUserEmail();
272 $payment->getField(
'ACCOUNT_NUMBER'),
273 $order->getField(
'ACCOUNT_NUMBER'),
276 ($userEmail) ? $userEmail->getValue() :
''
278 $this->getBusinessValue(
$payment,
'WOOPPAY_PAYMENT_DESCRIPTION')
286 private function getRequestUrl(Sale\Payment
$payment): string
289 $uri =
new Main\Web\Uri($requestUrl);
291 self::REQUEST_PAY_SYSTEM_ID_PARAM => $this->service->getField(
'ID'),
292 self::REQUEST_PAYMENT_ID_PARAM =>
$payment->getId(),
293 self::REQUEST_SOURCE_PARAM => self::BITRIX_LABEL,
296 return $uri->getLocator();
303 private function getBackUrl(Sale\Payment
$payment)
320 private function getPhoneNumber(Sale\Payment
$payment): ?string
325 $collection =
$payment->getCollection();
326 $order = $collection->getOrder();
329 && $clientCollection =
$order->getContactCompanyCollection()
332 $primaryClient = $clientCollection->getPrimaryContact();
335 if ($primaryClient ===
null)
337 $primaryClient = $clientCollection->getPrimaryCompany();
343 $clientId = $primaryClient->getField(
'ENTITY_ID');
344 $crmFieldMultiResult = \CCrmFieldMulti::GetList(
349 'TYPE_ID' =>
'PHONE',
352 while ($crmFieldMultiData = $crmFieldMultiResult->Fetch())
354 $phoneNumber = $crmFieldMultiData[
'VALUE'];
365 $phoneNumberProp =
$order->getPropertyCollection()->getPhone();
366 if ($phoneNumberProp)
368 $phoneNumber = $phoneNumberProp->getValue();
372 return $phoneNumber ? $this->normalizePhone($phoneNumber) : null;
379 private function normalizePhone($phoneNumber)
383 $parsedNumber = Main\PhoneNumber\Parser::getInstance()->parse($phoneNumber,
'KZ');
384 if ($parsedNumber->isValid())
386 $parsedNumber = $parsedNumber->format(Main\PhoneNumber\
Format::E164);
387 $result = str_replace(
'+',
'', $parsedNumber);
407 $result =
new Sale\PaySystem\ServiceResult();
409 $httpClient =
new Main\Web\HttpClient();
410 $httpClient->setHeaders($headers);
412 if (
$method === self::SEND_METHOD_GET)
424 Sale\PaySystem\Logger::addDebugInfo(__CLASS__.
': request data: '.
$postData);
431 $errors = $httpClient->getError();
432 $result->addError(
new Main\
Error(Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_ERROR_EMPTY_RESPONSE')));
441 Sale\PaySystem\Logger::addDebugInfo(__CLASS__.
': response data: '.
$response);
443 $httpStatus = $httpClient->getStatus();
444 $verificationResult = $this->verifyResponse(
$response, $httpStatus);
445 if (!$verificationResult->isSuccess())
447 $result->addErrors($verificationResult->getErrors());
461 private function verifyResponse(
string $response,
int $httpStatus): Sale\PaySystem\ServiceResult
463 $result =
new Sale\PaySystem\ServiceResult();
468 $result->addError(
new Main\
Error(Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_ERROR_DECODE_RESPONSE')));
471 if ($httpStatus === self::HTTP_CODE_UNAUTHORIZED)
473 $result->addError(
new Main\
Error(Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_ERROR_STATUS_UNAUTHORIZED')));
474 if (!empty($responseData[
'message']))
476 $result->addError(
new Main\
Error($responseData[
'message']));
479 elseif ($httpStatus === self::HTTP_CODE_UNPROCESSABLE_ENTITY)
481 $result->addError(
new Main\
Error(Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_ERROR_STATUS_UNPROCESSABLE_ENTITY')));
482 foreach ($responseData as
$error)
484 if (!empty(
$error[
'field']) && !empty(
$error[
'message']))
491 elseif ($httpStatus === self::HTTP_CODE_INTERNAL_SERVER_ERROR)
493 $result->addError(
new Main\
Error(Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_ERROR_STATUS_INTERNAL_SERVER_ERROR')));
495 elseif ($httpStatus !== self::HTTP_CODE_OK)
499 Main\Localization\Loc::getMessage(
500 'SALE_HPS_WOOPPAY_ERROR_STATUS',
502 '#STATUS#' => $httpStatus,
508 if (!empty($responseData[
'message']))
510 $result->addError(
new Main\
Error($responseData[
'message']));
520 private function getHeaders():
array
523 'Content-Type' =>
'application/json',
531 protected function isTestMode(Sale\Payment
$payment =
null): bool
541 $testUrl =
'https://api.yii2-stage.test.wooppay.com/';
542 $activeUrl =
'https://api-core.wooppay.com/';
546 self::TEST_URL => $testUrl.self::API_VERSION_V1.
'/auth',
547 self::ACTIVE_URL => $activeUrl.self::API_VERSION_V1.
'/auth'
550 self::TEST_URL => $testUrl.self::API_VERSION_V1.
'/invoice/create',
551 self::ACTIVE_URL => $activeUrl.self::API_VERSION_V1.
'/invoice/create'
554 self::TEST_URL => $testUrl.self::API_VERSION_V1.
'/history/{id}',
555 self::ACTIVE_URL => $activeUrl.self::API_VERSION_V1.
'/history/{id}'
557 'historyReceipt' => [
558 self::TEST_URL => $testUrl.self::API_VERSION_V1.
'/history/receipt/{id}',
559 self::ACTIVE_URL => $activeUrl.self::API_VERSION_V1.
'/history/receipt/{id}'
562 self::TEST_URL => $testUrl.self::API_VERSION_V1.
'/reverse',
563 self::ACTIVE_URL => $activeUrl.self::API_VERSION_V1.
'/reverse'
566 self::TEST_URL => $testUrl.self::API_VERSION_V1.
'/reverse/mobile-return',
567 self::ACTIVE_URL => $activeUrl.self::API_VERSION_V1.
'/reverse/mobile-return'
577 protected function getUrl(Sale\Payment
$payment =
null,
$action): string
602 self::REQUEST_PAY_SYSTEM_ID_PARAM,
603 self::REQUEST_PAYMENT_ID_PARAM,
604 self::REQUEST_SOURCE_PARAM,
618 public function refund(Sale\Payment
$payment, $refundableSum): Sale\PaySystem\ServiceResult
620 $result =
new Sale\PaySystem\ServiceResult();
622 $authResult = $this->auth(
$payment);
623 if (!$authResult->isSuccess())
625 $result->addErrors($authResult->getErrors());
629 $invoiceHistoryResult = $this->getInvoiceHistory(
$payment, $authResult->getData()[
'token']);
630 if (!$invoiceHistoryResult->isSuccess())
632 $result->addErrors($invoiceHistoryResult->getErrors());
636 if ($invoiceHistoryResult->getData()[
'status'] !== self::HISTORY_STATUS_PAID)
640 Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_REFUND_STATUS_ERROR')
645 $invoiceHistoryReceiptResult = $this->getInvoiceHistoryReceipt(
$payment, $authResult->getData()[
'token']);
646 if (!$invoiceHistoryReceiptResult->isSuccess())
648 $result->addErrors($invoiceHistoryReceiptResult->getErrors());
654 'operation_id' => $this->getOperationId(
$payment),
655 'description' =>
$payment->getField(
'PAY_RETURN_COMMENT')
656 ?: Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_REFUND_REASON'),
659 if ($this->isMobileAgent($invoiceHistoryReceiptResult->getData()[
'agent']))
662 $params[
'force_refund'] =
true;
665 $headers = $this->getHeaders();
666 $headers[
'Authorization'] = $authResult->getData()[
'token'];
668 $sendResult = $this->send(self::SEND_METHOD_POST,
$url, $headers,
$params);
669 if ($sendResult->isSuccess())
671 $result->setOperationType(Sale\PaySystem\ServiceResult::MONEY_LEAVING);
675 $result->addErrors($sendResult->getErrors());
685 private function isMobileAgent(
string $agent): bool
687 $agentList = [
'agentkartel2',
'agentkcell',
'agenttele2'];
688 return (
bool)array_filter($agentList,
static function ($value) use ($agent) {
689 return mb_strpos($agent, $value) !==
false;
703 public function processRequest(Sale\Payment
$payment, Main\Request
$request): Sale\PaySystem\ServiceResult
705 $result =
new Sale\PaySystem\ServiceResult();
707 $authResult = $this->auth(
$payment);
708 if (!$authResult->isSuccess())
710 $result->addErrors($authResult->getErrors());
714 $invoiceHistoryResult = $this->getInvoiceHistory(
$payment, $authResult->getData()[
'token']);
715 if (!$invoiceHistoryResult->isSuccess())
717 $result->addErrors($invoiceHistoryResult->getErrors());
721 $invoiceHistoryData = $invoiceHistoryResult->getData();
722 if ($invoiceHistoryData[
'status'] === self::HISTORY_STATUS_PAID)
725 'PS_STATUS_CODE' => $invoiceHistoryData[
'status'],
726 'PS_SUM' => $invoiceHistoryData[
'amount'],
728 'PS_CURRENCY' =>
$payment->getField(
'CURRENCY'),
729 'PS_RESPONSE_DATE' =>
new Main\Type\DateTime(),
732 if ($this->isSumCorrect(
$payment, $invoiceHistoryData[
'amount']))
736 Sale\PaySystem\Logger::addDebugInfo(
737 __CLASS__.
': PS_CHANGE_STATUS_PAY='.$this->getBusinessValue(
$payment,
'PS_CHANGE_STATUS_PAY')
742 $result->setOperationType(Sale\PaySystem\ServiceResult::MONEY_COMING);
747 $result->addError(
new Main\
Error(Main\Localization\Loc::getMessage(
'SALE_HPS_WOOPPAY_ERROR_SUM')));
756 Main\Localization\Loc::getMessage(
757 'SALE_HPS_WOOPPAY_ERROR_REQUEST_STATUS',
759 '#STATUS#' => $invoiceHistoryData[
'status'],
779 private function getInvoiceHistory(Sale\Payment
$payment,
string $token): Sale\PaySystem\ServiceResult
781 $result =
new Sale\PaySystem\ServiceResult();
784 $headers[
'Authorization'] = $token;
786 $sendResult = $this->send(self::SEND_METHOD_GET,
$url, $headers);
787 if ($sendResult->isSuccess())
789 $result->setData($sendResult->getData());
793 $result->addErrors($sendResult->getErrors());
809 private function getInvoiceHistoryReceipt(Sale\Payment
$payment,
string $token): Sale\PaySystem\ServiceResult
811 $result =
new Sale\PaySystem\ServiceResult();
814 $headers[
'Authorization'] = $token;
816 $sendResult = $this->send(self::SEND_METHOD_GET,
$url, $headers);
817 if ($sendResult->isSuccess())
819 $result->setData($sendResult->getData());
823 $result->addErrors($sendResult->getErrors());
838 private function isSumCorrect(Sale\Payment
$payment,
$sum): bool
840 Sale\PaySystem\Logger::addDebugInfo(
842 .
': WooppaySum = '.Sale\PriceMaths::roundPrecision(
$sum)
843 .
'; paymentSum = '.Sale\PriceMaths::roundPrecision(
$payment->getSum())
846 return Sale\PriceMaths::roundPrecision(
$sum) === Sale\PriceMaths::roundPrecision(
$payment->getSum());
853 public function getPaymentIdFromRequest(Main\Request
$request)
855 return $request->get(self::REQUEST_PAYMENT_ID_PARAM);
862 private function getOperationId(Sale\Payment
$payment): ?string
864 $psInvoiceId =
$payment->getField(
'PS_INVOICE_ID');
867 [, $operationId] = explode(self::INVOICE_ID_DELIMITER, $psInvoiceId);
868 return (
string)$operationId;
881 return Main\Web\Json::encode(
$data, JSON_UNESCAPED_UNICODE);
888 private static function decode(
$data)
892 return Main\Web\Json::decode(
$data);
894 catch (Main\ArgumentException $exception)
910 public function sendResponse(Sale\PaySystem\ServiceResult
$result, Main\Request
$request)
922 Sale\PaySystem\Logger::addDebugInfo(__CLASS__.
': response: '.
$result);
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
static loadMessages($file)
static getHandlerModeList()
showTemplate(Payment $payment=null, $template='')
setExtraParams(array $values)
getBusinessValue(Payment $payment=null, $code)
static getIndicativeFields()
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
while($arParentIBlockProperty=$dbParentIBlockProperty->Fetch()) $errorMessage
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
if(file_exists($_SERVER['DOCUMENT_ROOT'] . "/urlrewrite.php")) $uri
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']