3namespace Sale\Handlers\PaySystem;
6use Bitrix\Main\Localization\Loc;
7use Bitrix\Main\Request;
8use Bitrix\Main\Type\DateTime;
9use Bitrix\Main\Web\HttpClient;
10use Bitrix\Sale\BusinessValue;
11use Bitrix\Sale\PaySystem;
12use Bitrix\Sale\Payment;
14Loc::loadMessages(__FILE__);
33 'PS_MODE' => $this->service->getField(
'PS_MODE'),
34 'BX_PAYSYSTEM_CODE' => $this->service->getField(
'ID'),
47 return array(
'BX_HANDLER' =>
'YANDEX');
55 static protected function isMyResponseExtended(Request
$request, $paySystemId)
57 $id =
$request->get(
'BX_PAYSYSTEM_CODE');
58 return (
int)$id === (int)$paySystemId;
66 public function refund(Payment
$payment, $refundableSum)
68 $result =
new PaySystem\ServiceResult();
70 $requestDT = date(
'c');
72 $cause = Loc::getMessage(
'SALE_HPS_YANDEX_CUSTOMER_REJECTION');
77 clientOrderId=\''.$payment->getId().
'\'
78 requestDT=\
''.$requestDT.
'\'
79 invoiceId=\
''.$payment->getField(
'PS_INVOICE_ID').
'\'
80 shopId=\
''.$shopId.
'\'
81 amount=\
''.number_format($refundableSum, 2,
'.',
'').
'\'
82 currency=\
''.$currency.
'\'
86 $url = $this->getUrl($payment, 'return');
88 $signResult = $this->signRequest($payment, $request);
89 if ($signResult->isSuccess())
91 $data = $signResult->getData();
92 $pkcs7 = $data['PKCS7
'];
94 $CertPem = PaySystem\YandexCert::getValue('CERT
', $shopId);
95 $PkeyPem = PaySystem\YandexCert::getValue('PKEY
', $shopId);
97 $cert = self::createTmpFile($CertPem);
98 $pkey = self::createTmpFile($PkeyPem);
100 $ch = curl_init($url);
101 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
102 curl_setopt($ch, CURLOPT_HEADER, 0);
103 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
104 curl_setopt($ch, CURLOPT_ENCODING, "");
105 curl_setopt($ch, CURLOPT_USERAGENT, "1C-Bitrix");
106 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
107 curl_setopt($ch, CURLOPT_TIMEOUT, 120);
108 curl_setopt($ch, CURLOPT_POST, 1);
109 curl_setopt($ch, CURLOPT_POSTFIELDS, $pkcs7);
110 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
111 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
112 curl_setopt($ch, CURLOPT_SSLCERT, $cert);
113 curl_setopt($ch, CURLOPT_SSLKEY, $pkey);
114 $content = curl_exec($ch);
115 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
116 $curlError = curl_error($ch);
119 PaySystem\Logger::addDebugInfo('Yandex: returnPaymentResponse:
'.$content);
121 if ($content !== false)
123 $element = $this->parseXmlResponse('returnPaymentResponse
', $content);
124 $status = (int)$element->getAttribute('status
');
127 $result->setOperationType(PaySystem\ServiceResult::MONEY_LEAVING);
131 $error .= Loc::getMessage('SALE_HPS_YANDEX_REFUND_ERROR
').' '.Loc::getMessage('SALE_HPS_YANDEX_REFUND_ERROR_INFO
', array('#STATUS#
' => $status, '#
ERROR#
' => $element->getAttribute('error
')));
136 $error .= Loc::getMessage('SALE_HPS_YANDEX_REFUND_CONNECTION_ERROR
', array('#URL#
' => $url, '#
ERROR#
' => $curlError, '#CODE#
' => $httpCode));
141 $error .= implode("\n", $signResult->getErrorMessages());
146 $result->addError(new Error($error));
148 $error = 'Yandex: returnPaymentRequest:
'.join('\n
', $result->getErrorMessages());
149 PaySystem\Logger::addError($error);
163 private function isCorrectHash(Payment $payment, Request $request)
167 $request->get('action
'),
168 $request->get('orderSumAmount
'),
169 $request->get('orderSumCurrencyPaycash
'),
170 $request->get('orderSumBankPaycash
'),
171 $this->getBusinessValue($payment, 'YANDEX_SHOP_ID
'),
172 $request->get('invoiceId
'),
173 $this->getBusinessValue($payment, 'PAYMENT_BUYER_ID
'),
174 $this->getBusinessValue($payment, 'YANDEX_SHOP_KEY
')
179 PaySystem\Logger::addDebugInfo(
180 'Yandex: calculatedHash=
'.mb_strtoupper($hash)."; yandexHash=".mb_strtoupper($request->get('md5
'))
183 return mb_strtoupper($hash) === mb_strtoupper($request->get('md5
'));
194 private function isCorrectSum(Payment $payment, Request $request)
196 $sum = $request->get('orderSumAmount
');
197 $paymentSum = $this->getBusinessValue($payment, 'PAYMENT_SHOULD_PAY
');
199 PaySystem\Logger::addDebugInfo(
200 'Yandex: yandexSum=
'.round($sum, 2)."; paymentSum=".round($paymentSum, 2)
203 return round($paymentSum, 2) == round($sum, 2);
211 public function sendResponse(PaySystem\ServiceResult $result, Request $request)
214 $APPLICATION->RestartBuffer();
216 $data = $result->getData();
218 if (!$result->isResultApplied() && $data['CODE
'] === 0)
223 $dateISO = date("Y-m-d\TH:i:s").mb_substr(date("O"), 0, 3).":".mb_substr(date("O"), -2, 2);
224 header("Content-Type: text/xml");
225 header("Pragma: no-cache");
226 $text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
228 if ($data['HEAD
'] <> '')
230 $text .= "<".$data['HEAD
']." performedDatetime=\"".$dateISO."\"";
231 $text .= " code=\"".$data['CODE
']."\" shopId=\"".$data['SHOP_ID
']."\" invoiceId=\"".$data['INVOICE_ID
']."\"";
233 if ($data['TECH_MESSAGE
'] <> '')
234 $text .= " techMessage=\"".$data['TECH_MESSAGE
']."\"";
239 PaySystem\Logger::addDebugInfo('Yandex: response:
'.$text);
249 public function getPaymentIdFromRequest(Request $request)
251 return $request->get('orderNumber
');
259 private function processCheckAction(Payment $payment, Request $request)
261 $result = new PaySystem\ServiceResult();
262 $data = $this->extractDataFromRequest($request);
264 if ($this->isCorrectSum($payment, $request))
271 $errorMessage = 'Incorrect payment sum
';
272 $result->addError(new Error($errorMessage));
274 PaySystem\Logger::addError('Yandex: checkOrderResponse:
'.$errorMessage);
277 $result->setData($data);
286 private function extractDataFromRequest(Request $request)
289 'HEAD
' => $request->get('action
').'Response
',
290 'SHOP_ID
' => $request->get('shopId
'),
291 'INVOICE_ID
' => $request->get('invoiceId
')
300 private function processNoticeAction(Payment $payment, Request $request)
302 $result = new PaySystem\ServiceResult();
303 $data = $this->extractDataFromRequest($request);
304 $modeList = static::getHandlerModeList();
305 $description = Loc::getMessage('SALE_HPS_YANDEX_TRANSACTION
').": ".$request->get('invoiceId
')."; ";
306 if ($request->get('paymentDatetime
'))
308 $description .= Loc::getMessage('SALE_HPS_YANDEX_DATE_PAYED
').": ".$request->get('paymentDatetime
');
312 "PS_STATUS_CODE" => mb_substr($data['HEAD
'], 0, 5),
313 "PS_STATUS_DESCRIPTION" => $description,
314 "PS_STATUS_MESSAGE" => $modeList[$request->get('paymentType
')],
315 "PS_SUM" => $request->get('orderSumAmount
'),
316 "PS_CURRENCY" => mb_substr($request->get('orderSumCurrencyPaycash
'), 0, 3),
317 "PS_RESPONSE_DATE" => new DateTime(),
318 "PS_INVOICE_ID" => $request->get('invoiceId
')
321 if ($this->isCorrectSum($payment, $request))
324 $fields["PS_STATUS"] = "Y";
326 PaySystem\Logger::addDebugInfo(
327 'Yandex: PS_CHANGE_STATUS_PAY=
'.$this->getBusinessValue($payment, 'PS_CHANGE_STATUS_PAY
')
330 if ($this->getBusinessValue($payment, 'PS_CHANGE_STATUS_PAY
') == 'Y
')
332 $result->setOperationType(PaySystem\ServiceResult::MONEY_COMING);
338 $fields["PS_STATUS"] = "N";
339 $errorMessage = 'Incorrect payment sum
';
340 $result->addError(new Error($errorMessage));
342 PaySystem\Logger::addError('Yandex: paymentAvisoResponse:
'.$errorMessage);
345 $result->setData($data);
346 $result->setPsData($fields);
356 private function processCancelAction(Payment $payment, Request $request)
358 $result = new PaySystem\ServiceResult();
359 $data = $this->extractDataFromRequest($request);
361 if ($this->isCorrectHash($payment, $request))
364 $result->setOperationType(PaySystem\ServiceResult::MONEY_LEAVING);
370 $errorMessage = 'Incorrect payment hash sum
';
371 $result->addError(new Error($errorMessage));
373 PaySystem\Logger::addError('Yandex: cancelOrderResponse:
'.$errorMessage);
376 $result->setData($data);
384 protected function getUrlList()
389 self::ACTIVE_URL =>
'https://penelope.yamoney.ru/webservice/mws/api/confirmPayment',
390 self::TEST_URL =>
'https://penelope-demo.yamoney.ru:8083/webservice/mws/api/confirmPayment'
393 self::ACTIVE_URL =>
'https://penelope.yamoney.ru/webservice/mws/api/cancelPayment',
394 self::TEST_URL =>
'https://penelope-demo.yamoney.ru:8083/webservice/mws/api/cancelPayment'
397 self::ACTIVE_URL =>
'https://penelope.yamoney.ru/webservice/mws/api/returnPayment',
398 self::TEST_URL =>
'https://penelope-demo.yamoney.ru:8083/webservice/mws/api/returnPayment',
410 $result =
new PaySystem\ServiceResult();
419 else if (
$action ==
'cancelOrder')
423 else if (
$action ==
'paymentAviso')
430 $data[
'TECH_MESSAGE'] =
'Unknown action: '.$action;
438 $data[
'TECH_MESSAGE'] =
'Incorrect hash sum';
447 $error =
'Yandex: processRequest: '.$action.
': '.join(
'\n',
$result->getErrorMessages());
448 PaySystem\Logger::addError(
$error);
458 protected function isTestMode(Payment
$payment =
null)
467 public function confirm(Payment
$payment)
469 $result =
new PaySystem\ServiceResult();
470 $httpClient =
new HttpClient();
473 $requestDT = date(
'c');
479 'requestDT' => $requestDT
483 if ($responseString !==
false)
485 $element = $this->parseXmlResponse(
'confirmPaymentResponse', $responseString);
486 $status = (int)$element->getAttribute(
'status');
488 $result->setOperationType(PaySystem\ServiceResult::MONEY_COMING);
499 $error =
'Yandex: confirmPayment: '.join(
'\n',
$result->getErrorMessages());
500 PaySystem\Logger::addError(
$error);
510 public function cancel(Payment
$payment)
512 $result =
new PaySystem\ServiceResult();
513 $httpClient =
new HttpClient();
516 $requestDT = date(
'c');
519 'requestDT' => $requestDT
523 if($responseString !==
false)
525 $element = $this->parseXmlResponse(
'cancelPaymentResponse', $responseString);
526 $status = (int)$element->getAttribute(
'status');
528 $result->setOperationType(PaySystem\ServiceResult::MONEY_LEAVING);
539 $error =
'Yandex: cancelPayment: '.join(
'\n',
$result->getErrorMessages());
540 PaySystem\Logger::addError(
$error);
551 private function parseXmlResponse($operation, $requestString)
553 $xmlParser = new \CDataXML();
555 $xmlParser->LoadString($requestString);
556 $tree = $xmlParser->GetTree();
557 $elements = $tree->elementsByName($operation);
568 private function signRequest(Payment
$payment, $xml)
570 $result =
new PaySystem\ServiceResult();
572 $dataFile = self::createTmpFile($xml);
573 $signedFile = self::createTmpFile();
576 $CertPem = PaySystem\YandexCert::getValue(
'CERT',
$shopId);
577 $PkeyPem = PaySystem\YandexCert::getValue(
'PKEY',
$shopId);
579 if ($PkeyPem && $CertPem)
581 if (openssl_pkcs7_sign($dataFile, $signedFile, $CertPem, $PkeyPem,
array(), PKCS7_NOCHAIN + PKCS7_NOCERTS))
583 $signedData = explode(
"\n\n", file_get_contents($signedFile));
584 $pkcs7 =
"-----BEGIN PKCS7-----\n".$signedData[1].
"\n-----END PKCS7-----";
589 $result->addError(
new Error(Loc::getMessage(
'SALE_HPS_YANDEX_REFUND_ERROR')));
594 $result->addError(
new Error(Loc::getMessage(
'SALE_HPS_YANDEX_REFUND_ERROR')));
604 private static function createTmpFile(
$data =
null)
606 $filePath = tempnam(sys_get_temp_dir(),
'YaMWS');
608 file_put_contents($filePath,
$data);
628 "PC" => Loc::getMessage(
"SALE_HPS_YANDEX_YMoney"),
629 "AC" => Loc::getMessage(
"SALE_HPS_YANDEX_Cards"),
630 "GP" => Loc::getMessage(
"SALE_HPS_YANDEX_Terminals"),
631 "MC" => Loc::getMessage(
"SALE_HPS_YANDEX_Mobile"),
632 "SB" => Loc::getMessage(
"SALE_HPS_YANDEX_Sberbank"),
633 "MP" => Loc::getMessage(
"SALE_HPS_YANDEX_mPOS"),
634 "AB" => Loc::getMessage(
"SALE_HPS_YANDEX_AlphaClick"),
635 "MA" => Loc::getMessage(
"SALE_HPS_YANDEX_MasterPass"),
636 "PB" => Loc::getMessage(
"SALE_HPS_YANDEX_Promsvyazbank"),
637 "QW" => Loc::getMessage(
"SALE_HPS_YANDEX_Qiwi"),
639 "QP" => Loc::getMessage(
"SALE_HPS_YANDEX_YKuppiRu"),
640 "" => Loc::getMessage(
"SALE_HPS_YANDEX_Smart")
649 $whiteList =
array(
'PC',
'AC',
'MC',
'MP',
'AB',
'MA',
'QW',
'KV',
'QP');
650 return in_array($this->service->getField(
'PS_MODE'), $whiteList);
658 $personTypeList = PaySystem\Manager::getPersonTypeIdList($this->service->getField(
'ID'));
659 $personTypeId = array_shift($personTypeList);
660 $shopId = BusinessValue::get(
'YANDEX_SHOP_ID', $this->service->getConsumerName(), $personTypeId);
669 public static function findMyDataRefundablePage(
array $paySystemList)
672 $personTypeList = BusinessValue::getPersonTypes();
673 $handler = PaySystem\Manager::getFolderFromClassName(get_called_class());
674 $description = PaySystem\Manager::getHandlerDescription($handler);
676 foreach ($paySystemList as
$data)
678 foreach ($personTypeList as $personType)
680 $shopId = BusinessValue::get(
'YANDEX_SHOP_ID', PaySystem\Service::PAY_SYSTEM_PREFIX.
$data[
'ID'], $personType[
'ID']);
683 $cert = PaySystem\YandexCert::getCert(
$shopId);
687 'HANDLER' =>
'yandex',
688 'LINK_PARAMS' =>
'shop_id='.
$shopId,
689 'CONFIGURED' => ($cert) ?
'Y' :
'N'
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
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']