3namespace Sale\Handlers\PaySystem;
6use Bitrix\Main\Entity\Result;
7use Bitrix\Main\Localization\Loc;
8use Bitrix\Main\Request;
9use Bitrix\Main\Web\HttpClient;
10use Bitrix\Main\Web\Json;
11use Bitrix\Sale\Payment;
12use Bitrix\Sale\PaymentCollection;
13use Bitrix\Sale\PaySystem;
14use Bitrix\Sale\PaySystem\Logger;
15use Bitrix\Sale\PaySystem\ServiceResult;
16use Bitrix\Sale\PriceMaths;
20 private const PAYMENT_METHOD_CODE =
'CC';
21 private const REFUND_ACTION =
'CREDITVOID';
23 private const ANALYTICS_TAG =
'api_bitrix24ua';
31 private const CALLBACK_ORDER_PARAM =
'order';
32 private const CALLBACK_EXT1_PARAM =
'ext1';
33 private const CALLBACK_EXT2_PARAM =
'ext2';
35 private const TRANSACTION_STATUS_SALE =
'SALE';
36 private const TRANSACTION_STATUS_REFUND =
'REFUND';
38 private const REFUND_STATUS_ACCEPTED =
'ACCEPTED';
39 private const REFUND_STATUS_ERROR =
'ERROR';
41 private const PS_MODE_BANK_CARD =
'bank_card';
42 private const PS_MODE_GOOGLE_PAY =
'google_pay';
43 private const PS_MODE_APPLE_PAY =
'apple_pay';
44 private const PS_MODE_PRIVAT24 =
'privat24';
51 $result =
new PaySystem\ServiceResult();
54 'CURRENCY' =>
$payment->getField(
'CURRENCY'),
55 'SUM' => PriceMaths::roundPrecision(
$payment->getSum()),
57 'FORM_DATA' => $this->getFormData(
$payment),
62 if ($showTemplateResult->isSuccess())
64 $result->setTemplate($showTemplateResult->getTemplate());
68 $result->addErrors($showTemplateResult->getErrors());
82 $paymentMethodCode = self::PAYMENT_METHOD_CODE;
83 $paymentData = $this->getPaymentData(
$payment);
84 $encodedPaymentData = $this->encodePaymentData($paymentData);
85 $successUrl = $this->getSuccessUrl(
$payment);
88 $sign = $this->getPaymentFormSignature(
96 $paymentNumber =
$payment->getField(
'ACCOUNT_NUMBER');
97 $paySystemId = $this->service->getField(
'ID');
101 'PAYMENT' => $paymentMethodCode,
102 'DATA' => $encodedPaymentData,
103 'URL' => $successUrl,
106 'ORDER' => $paymentNumber,
108 'EXT_2' => $paySystemId,
109 'EXT_3' => self::ANALYTICS_TAG,
115 $formData[
'EMAIL'] =
$email;
126 private function encodePaymentData(
array $paymentData): string
128 return base64_encode(Json::encode($paymentData, JSON_UNESCAPED_UNICODE));
135 private function decode(
$data)
139 return Main\Web\Json::decode(
$data);
141 catch (Main\ArgumentException $exception)
151 private function getPaymentData(Payment
$payment)
153 $formattedPaymentSum = $this->getFormattedPaymentSum(
$payment);
154 $paymentDescription = $this->getPaymentDescription(
$payment);
157 'amount' => $formattedPaymentSum,
158 'currency' =>
$payment->getField(
"CURRENCY"),
159 'description' => $paymentDescription,
168 private function getFormattedPaymentSum(Payment
$payment)
170 $paymentSum = PriceMaths::roundPrecision(
$payment->getSum());
171 return $this->formatPaymentSum($paymentSum);
178 private function formatPaymentSum($paymentSum): string
180 return number_format($paymentSum, 2,
'.',
'');
188 private function getSuccessUrl(Payment
$payment): string
197 private function getPaymentDescription(Payment
$payment)
200 $collection =
$payment->getCollection();
201 $order = $collection->getOrder();
202 $userEmail =
$order->getPropertyCollection()->getUserEmail();
214 $payment->getField(
'ACCOUNT_NUMBER'),
215 $order->getField(
'ACCOUNT_NUMBER'),
218 ($userEmail) ? $userEmail->getValue() :
'',
235 private function getPaymentFormSignature(
237 string $paymentMethodCode,
238 string $encodedPaymentData,
246 . strrev($paymentMethodCode)
247 . strrev($encodedPaymentData)
248 . strrev($successUrl)
267 $result =
new PaySystem\ServiceResult();
268 Logger::addDebugInfo(__CLASS__ .
': request payload: ' . Json::encode(
$request->getValues(), JSON_UNESCAPED_UNICODE));
271 if ($signatureCheckResult->isSuccess())
273 $transactionId =
$request->get(
'id');
274 $transactionStatus =
$request->get(
'status');
276 if ($transactionId && $transactionStatus === self::TRANSACTION_STATUS_SALE)
278 $description = Loc::getMessage(
'SALE_HPS_PLATON_TRANSACTION_DESCRIPTION', [
280 '#PAYMENT_NUMBER#' =>
$request->get(
'order'),
282 $requestSum =
$request->get(
'amount');
284 'PS_INVOICE_ID' => $transactionId,
285 'PS_STATUS_CODE' => $transactionStatus,
287 'PS_SUM' => $requestSum,
288 'PS_CURRENCY' =>
$request->get(
'currency'),
289 'PS_RESPONSE_DATE' =>
new Main\Type\DateTime(),
291 'PS_CARD_NUMBER' =>
$request->get(
'card'),
294 if ($this->checkPaymentSum(
$payment, $requestSum))
296 $paymentFields[
'PS_STATUS'] =
'Y';
298 $result->setOperationType(PaySystem\ServiceResult::MONEY_COMING);
299 $result->setPsData($paymentFields);
303 $errorMessage = Loc::getMessage(
'SALE_HPS_PLATON_SUM_MISMATCH');
308 elseif ($transactionStatus === self::TRANSACTION_STATUS_REFUND)
310 $oldDescription =
$payment->getField(
'PS_STATUS_DESCRIPTION');
311 $newDescription = str_replace(
312 ' ' . Loc::getMessage(
'SALE_HPS_PLATON_REFUND_IN_PROCESS'),
316 $payment->setField(
'PS_STATUS_DESCRIPTION', $newDescription);
317 $result->setOperationType(PaySystem\ServiceResult::MONEY_LEAVING);
324 $errorMessage = Loc::getMessage(
'SALE_HPS_PLATON_REQUEST_ERROR');
331 $result->addError(
new Main\
Error(Loc::getMessage(
'SALE_HPS_PLATON_SIGNATURE_MISMATCH')));
342 private function checkCallbackSignature(Payment
$payment, Request
$request): PaySystem\ServiceResult
346 $callbackSignature =
$request->get(
'sign');
355 Logger::addDebugInfo(__CLASS__ .
": local signature: $localSignature, callback signature: $callbackSignature");
356 if ($callbackSignature !== $localSignature)
358 $result->addError(
new Main\
Error(
'signature mismatch'));
370 private function checkPaymentSum(Payment
$payment, $requestSum): bool
372 $roundedRequestSum = PriceMaths::roundPrecision($requestSum);
373 $roundedPaymentSum = PriceMaths::roundPrecision(
$payment->getSum());
374 Logger::addDebugInfo(__CLASS__ .
": request sum: $roundedRequestSum, payment sum: $roundedPaymentSum");
376 return $roundedRequestSum === $roundedPaymentSum;
385 self::CALLBACK_ORDER_PARAM,
386 self::CALLBACK_EXT1_PARAM,
387 self::CALLBACK_EXT2_PARAM,
394 protected static function isMyResponseExtended(Request
$request, $paySystemId)
396 return (
int)
$request->get(self::CALLBACK_EXT2_PARAM) === (int)$paySystemId;
402 public function getPaymentIdFromRequest(Request
$request)
410 public function refund(Payment
$payment, $refundableSum)
412 $result =
new PaySystem\ServiceResult();
414 $transactionId =
$payment->getField(
'PS_INVOICE_ID');
415 $cardNumber =
$payment->getField(
'PS_CARD_NUMBER');
419 $formattedPaymentSum = $this->getFormattedPaymentSum(
$payment);
425 $signature = $this->getCallbackSignature(
$email,
$password, $transactionId, $cardNumber);
428 'action' => self::REFUND_ACTION,
429 'client_key' => $apiKey,
430 'trans_id' => $transactionId,
431 'amount' => $formattedPaymentSum,
432 'hash' => $signature,
436 if (!$responseResult->isSuccess())
438 $result->addErrors($responseResult->getErrors());
442 $responseData = $responseResult->getData();
444 Logger::addDebugInfo(__CLASS__ .
': refund payload: ' . Json::encode($responseData, JSON_UNESCAPED_UNICODE));
445 switch ($responseData[
'result'])
447 case self::REFUND_STATUS_ACCEPTED:
448 $newDescription =
$payment->getField(
'PS_STATUS_DESCRIPTION') .
' ' . Loc::getMessage(
'SALE_HPS_PLATON_REFUND_IN_PROCESS');
449 $payment->setField(
'PS_STATUS_DESCRIPTION', $newDescription);
450 $result->setData($responseData);
452 case self::REFUND_STATUS_ERROR:
453 $result->addError(
new Main\
Error(Loc::getMessage(
'SALE_HPS_PLATON_RESPONSE_ERROR', [
454 '#PS_RESPONSE#' => $responseData[
'error_message'],
458 $result->addError(
new Main\
Error(Loc::getMessage(
'SALE_HPS_PLATON_REFUND_ERROR')));
463 $result->addError(
new Main\
Error(Loc::getMessage(
'SALE_HPS_PLATON_ERROR_CARD_NOT_FOUND')));
479 $httpClient =
new HttpClient();
483 $errors = $httpClient->getError();
491 $responseData = $this->decode(
$response);
492 $result->setData($responseData);
505 private function getCallbackSignature(
string $email,
string $password,
string $transactionId,
string $cardNumber): string
513 mb_substr($cardNumber, 0, 6)
514 . mb_substr($cardNumber, -4)
524 private function getUserEmailValue(Payment
$payment): string
527 $emailProperty =
$payment->getOrder()->getPropertyCollection()->getUserEmail();
530 $email = $emailProperty->getValue();
539 'formActionUrl' =>
'https://secure.platononline.com/payment/auth',
540 'requestUrl' =>
'https://secure.platononline.com/post-unq/',
549 return PaySystem\Manager::getHandlerDescription(
'Platon')[
'HANDLER_MODE_LIST'];
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
static getHandlerModeList()
getUrl(Payment $payment=null, $action)
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)
if(Loader::includeModule( 'bitrix24')) elseif(Loader::includeModule('intranet') &&CIntranetUtils::getPortalZone() !=='ru') $description
while($arParentIBlockProperty=$dbParentIBlockProperty->Fetch()) $errorMessage
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']