%PDF- %PDF-
| Direktori : /home/bitrix/www/bitrix/modules/sale/handlers/paysystem/alfabankb2b/ |
| Current File : //home/bitrix/www/bitrix/modules/sale/handlers/paysystem/alfabankb2b/handler.php |
<?php
namespace Sale\Handlers\PaySystem;
use Bitrix\Sale\Payment;
use Bitrix\Sale\PaySystem;
use Bitrix\Sale;
use Bitrix\Main;
use Bitrix\Sale\PaySystem\ServiceResult;
Main\Localization\Loc::loadMessages(__FILE__);
class AlfaBankB2BHandler extends PaySystem\BaseServiceHandler implements PaySystem\IRequested
{
/**
* @param Sale\Payment $payment
* @param Main\Request|null $request
* @return PaySystem\ServiceResult
*/
public function initiatePay(Sale\Payment $payment, Main\Request $request = null)
{
$serviceResult = new ServiceResult();
if ($request === null)
{
$instance = Main\Application::getInstance();
$context = $instance->getContext();
$request = $context->getRequest();
}
if ($request->get('initiate_pay') !== null)
{
$template = '';
$params = $this->getParamsBusValue($payment);
$params['CODE'] = $params['PAYMENT_ID'];
$params['PAYMENT_ID'] = $payment->getId();
/**
* from AlfaBank documentation:
* document number(in our system PAYMENT_ID) must be > 0 and < 99999, can not end on 000
*/
if ($params['PAYMENT_ID'] < 99999)
{
if ($params['PAYMENT_ID'] % 1000 === 0)
$params['PAYMENT_ID']++;
}
else
{
$params['PAYMENT_ID'] %= 99999;
}
$params['PAYMENT_SHOULD_PAY'] = roundEx($params['PAYMENT_SHOULD_PAY'], 2)*100;
/** @var Main\Type\DateTime $date */
$date = $params['PAYMENT_DATE_INSERT'];
$params['PAYMENT_DATE_INSERT'] = $date->format('Y-m-d');
$this->setInitiateMode(PaySystem\BaseServiceHandler::STRING);
$this->setExtraParams($params);
$result = $this->showTemplate($payment, 'payment');
if ($result->isSuccess())
$template = $result->getTemplate();
$data = $this->createRequest($template);
$url = $this->getUrl($payment, 'create');
$result = $this->sendRequest($url, 'WSCreatePaymentDocRURAdd', $data);
if ($result->isSuccess())
{
$data = $result->getData();
$xml = new \CDataXML();
$xml->LoadString($data['RESPONSE']);
$response = $xml->GetArray();
if (is_array($response['Envelope']['#']['Body'][0]['#']) && array_key_exists('Fault', $response['Envelope']['#']['Body'][0]['#']))
{
$detailErrors = $response['Envelope']['#']['Body'][0]['#']['Fault'][0]['#']['detail'][0]['#'];
foreach ($detailErrors as $error)
{
$errorCode = $error[0]['#']['errorCode'][0]['#'];
$errorString = Main\Localization\Loc::getMessage('SALE_HPS_ALFABANK_ERROR_'.$errorCode);
if (strlen($errorString) === 0)
$errorString = $error[0]['#']['errorString'][0]['#'];
$serviceResult->addError(new Main\Error($errorString));
}
}
else if (is_array($response) && $this->verifySign($response))
{
$docId = $response['Envelope']['#']['Body'][0]['#']['WSCreatePaymentDocRURAddResponse'][0]['#']['outParms'][0]['#']['docId'][0]['#'];
if ($docId !== '')
$serviceResult->setPsData(array('PS_INVOICE_ID' => $docId));
}
}
$templateName = $serviceResult->isSuccess() ? 'success' : 'failure';
$result = $this->showTemplate($payment, $templateName);
$serviceResult->setTemplate($result->getTemplate());
}
else
{
/** @var \Bitrix\Sale\PaymentCollection $paymentCollection */
$paymentCollection = $payment->getCollection();
/** @var \Bitrix\Sale\Order $order */
$order = $paymentCollection->getOrder();
$this->setExtraParams(
array(
'ORDER_ID' => $order->getId(),
'ACCOUNT_NUMBER' => $order->getField('ACCOUNT_NUMBER'),
'PAYSYSTEM_ID' => $this->service->getField('ID')
)
);
$serviceResult = $this->showTemplate($payment, 'template');
}
return $serviceResult;
}
/**
* @param $data
* @return string
*/
private function createRequest($data)
{
$data = $this->convertToUtf8($data);
$start = strpos($data, '<soapenv:Body');
$end = strpos($data, '</soapenv:Body>');
$body = substr($data, $start, $end - $start + 15);
$this->setExtraParams(array('DIGEST_VALUE' => $this->getHash($body)));
$result = $this->showTemplate(null, 'sign');
if ($result->isSuccess())
{
$signedInfo = $result->getTemplate();
$signature = $this->sign($signedInfo);
$replace = array(
'#CERT#' => $this->getCert(),
'#SIGNED_INFO#' => $signedInfo,
'#SIGNATURE_VALUE#' => base64_encode($signature),
);
$data = strtr($data, $replace);
}
return '<?xml version="1.0"?>'.$data;
}
/**
* @param array $data
* @return bool
*/
private function verifySign(array $data)
{
$signedInfo = $data['Envelope']['#']['Header'][0]['#']['Security'][0]['#']['Signature'][0]['#']['SignedInfo'];
$signatureValue = $data['Envelope']['#']['Header'][0]['#']['Security'][0]['#']['Signature'][0]['#']['SignatureValue'][0]['#'];
$cert = $data['Envelope']['#']['Header'][0]['#']['Security'][0]['#']['BinarySecurityToken'][0]['#'];
// openssl verify
return true;
}
/**
* @param $data
* @return string
*/
private function getHash($data)
{
return base64_encode(hash('gost-crypto', $data, true));
}
/**
* @param $url
* @param $action
* @param $data
* @return ServiceResult
*/
private function sendRequest($url, $action, $data)
{
$serviceResult = new ServiceResult();
$urlObj = new Main\Web\Uri($url);
if ($urlObj->getScheme() === 'https')
{
$scheme = 'ssl://';
$port = 443;
}
else
{
$scheme = '';
$port = 80;
}
$header = "POST ".$urlObj->getPath()." HTTP/1.0\r\n";
$header .= "Host: ".$urlObj->getHost()."\r\n";
$header .= "Content-Type: text/xml; charset=utf-8\r\n";
$header .= "Connection: Keep-Alive\r\n";
$header .= "SOAPAction: ".$action."\r\n";
$header .= sprintf("Content-length: %s\r\n", strlen($data));
$header .= "\r\n";
$errNo = '';
$errStr = '';
$fp = stream_socket_client($scheme.$urlObj->getHost().':'.$port.$urlObj->getPath(), $errNo, $errStr, 30);
if ($fp !== false)
{
fputs($fp, $header.$data);
$response = @stream_get_contents($fp);
list($header, $body) = explode("\r\n\r\n", $response);
$serviceResult->setData(array('RESPONSE' => $body));
fclose($fp);
}
else
{
$serviceResult->addError(new Main\Error($errNo.' - '.$errStr));
}
return $serviceResult;
}
/**
* @param $data
* @return false|string
*/
private function sign($data)
{
if (IsModuleInstalled('bitrix24') && function_exists('bx_alfabank_sign'))
return bx_alfabank_sign($data);
return false;
}
/**
* @return string
*/
private function getCert()
{
$cert = '';
if (IsModuleInstalled('bitrix24') && function_exists('bx_alfabank_cert'))
$cert = bx_alfabank_cert();
return $cert;
}
/**
* @return array
*/
public function getCurrencyList()
{
return array('RUB');
}
/**
* @return array
*/
protected function getUrlList()
{
return array(
'create' => array(
self::TEST_URL => 'https://testjmb.alfabank.ru/CS/ALBO/WSCreatePaymentDocRUR/WSCreatePaymentDocRUR11',
self::ACTIVE_URL => 'https://link.alfabank.ru/CS/ALBO/WSCreatePaymentDocRUR/WSCreatePaymentDocRUR11'
),
'request' => array(
self::TEST_URL => 'https://testjmb.alfabank.ru/CS/ALBO/WSCreateAccountMovementListRequest/WSCreateAccountMovementListRequest',
self::ACTIVE_URL => 'https://link.alfabank.ru/CS/ALBO/WSCreateAccountMovementListRequest/WSCreateAccountMovementListRequest'
),
'list' => array(
self::TEST_URL => 'https://testjmb.alfabank.ru/CS/ALBO/WSGetAccountMovementList/WSGetAccountMovementList',
self::ACTIVE_URL => 'https://link.alfabank.ru/CS/ALBO/WSGetAccountMovementList/WSGetAccountMovementList'
),
);
}
/**
* @param Main\Request $request
* @return ServiceResult
*/
public function createMovementListRequest(Main\Request $request)
{
$serviceResult = new ServiceResult();
$template = '';
$date = $request->get('DATE_START');
$dateStart = new Main\Type\Date($date);
if (empty($date))
$dateStart->add('-10d');
$date = $request->get('DATE_END');
$dateEnd = new Main\Type\Date($date);
if (empty($date))
$dateEnd->add('-1d');
$this->setInitiateMode(PaySystem\BaseServiceHandler::STRING);
$this->setExtraParams(array('START_DATE' => $dateStart->format('Y-m-d'), 'END_DATE' => $dateEnd->format('Y-m-d')));
$result = $this->showTemplate(null, 'listrequest');
if ($result->isSuccess())
$template = $result->getTemplate();
$data = $this->createRequest($template);
$result = $this->sendRequest($this->getUrl(null, 'request'), 'WSCreateAccountMovementListRequestAdd', $data);
if ($result->isSuccess())
{
$data = $result->getData();
$xml = new \CDataXML();
$xml->LoadString($data['RESPONSE']);
$response = $xml->GetArray();
if (is_array($response['Envelope']['#']['Body'][0]['#']) && array_key_exists('Fault', $response['Envelope']['#']['Body'][0]['#']))
{
$detailErrors = $response['Envelope']['#']['Body'][0]['#']['Fault'][0]['#']['detail'][0]['#'];
foreach ($detailErrors as $error)
{
$errorCode = $error[0]['#']['errorCode'][0]['#'];
$errorString = Main\Localization\Loc::getMessage('SALE_HPS_ALFABANK_ERROR_'.$errorCode);
if (strlen($errorString) === 0)
$errorString = $error[0]['#']['errorString'][0]['#'];
$serviceResult->addError(new Main\Error($errorString));
}
}
else if (is_array($response) && $this->verifySign($response))
{
$requestId = $response['Envelope']['#']['Body'][0]['#']['WSCreateAccountMovementListRequestAddResponse'][0]['#']['outParms'][0]['#']['requestId'][0]['#'];
if (strlen($requestId) > 0)
$serviceResult->setData(array('requestId' => $requestId));
}
}
else
{
$serviceResult->addErrors($result->getErrors());
}
return $serviceResult;
}
/**
* @param $requestId
* @return ServiceResult
*/
public function getMovementListStatus($requestId = null)
{
$serviceResult = new ServiceResult();
$status = false;
$time = '';
$template = '';
$this->setInitiateMode(PaySystem\BaseServiceHandler::STRING);
$this->setExtraParams(array('REQUEST_ID' => $requestId));
$result = $this->showTemplate(null, 'movementstatus');
if ($result->isSuccess())
$template = $result->getTemplate();
$data = $this->createRequest($template);
$result = $this->sendRequest($this->getUrl(null, 'list'), 'WSGetAccountMovementListStatus', $data);
if ($result->isSuccess())
{
$data = $result->getData();
$xml = new \CDataXML();
$xml->LoadString($data['RESPONSE']);
$response = $xml->GetArray();
if (is_array($response['Envelope']['#']['Body'][0]['#']) && array_key_exists('Fault', $response['Envelope']['#']['Body'][0]['#']))
{
$detailErrors = $response['Envelope']['#']['Body'][0]['#']['Fault'][0]['#']['detail'][0]['#'];
foreach ($detailErrors as $error)
{
$errorCode = $error[0]['#']['errorCode'][0]['#'];
$errorString = Main\Localization\Loc::getMessage('SALE_HPS_ALFABANK_ERROR_'.$errorCode);
if (strlen($errorString) === 0)
$errorString = $error[0]['#']['errorString'][0]['#'];
$serviceResult->addError(new Main\Error($errorString));
}
}
else if (is_array($response) && $this->verifySign($response))
{
$status = $response['Envelope']['#']['Body'][0]['#']['WSGetAccountMovementListStatusResponse'][0]['#']['outParms'][0]['#']['status'][0]['#'];
$status = ($status === 'true') ? true : false;
if ($status !== true)
$time = $response['Envelope']['#']['Body'][0]['#']['WSGetAccountMovementListStatusResponse'][0]['#']['outParms'][0]['#']['estimatedTime'][0]['#'];
}
}
$serviceResult->setData(array('status' => $status, 'estimatedTime' => $time));
return $serviceResult;
}
/**
* @param $requestId
* @return ServiceResult
*/
public function getMovementList($requestId = null)
{
$serviceResult = new ServiceResult();
$template = '';
$this->setInitiateMode(PaySystem\BaseServiceHandler::STRING);
$this->setExtraParams(array('REQUEST_ID' => $requestId));
$result = $this->showTemplate(null, 'movementlist');
if ($result->isSuccess())
$template = $result->getTemplate();
$data = $this->createRequest($template);
$result = $this->sendRequest($this->getUrl(null, 'list'), 'WSGetAccountMovementListDoc', $data);
if ($result->isSuccess())
{
$data = $result->getData();
$xml = new \CDataXML();
$xml->LoadString($data['RESPONSE']);
$response = $xml->GetArray();
if (is_array($response['Envelope']['#']['Body'][0]['#']) && array_key_exists('Fault', $response['Envelope']['#']['Body'][0]['#']))
{
$detailErrors = $response['Envelope']['#']['Body'][0]['#']['Fault'][0]['#']['detail'][0]['#'];
foreach ($detailErrors as $error)
{
$errorCode = $error[0]['#']['errorCode'][0]['#'];
$errorString = Main\Localization\Loc::getMessage('SALE_HPS_ALFABANK_ERROR_'.$errorCode);
if (strlen($errorString) === 0)
$errorString = $error[0]['#']['errorString'][0]['#'];
$serviceResult->addError(new Main\Error($errorString));
}
}
else if (is_array($response) && $this->verifySign($response))
{
$dataRow = $response['Envelope']['#']['Body'][0]['#']['WSGetAccountMovementListDocResponse'][0]['#']['outParms'][0]['#']['resultSet'][0]['#']['row'];
if ($dataRow)
{
$itemList = array();
foreach ($dataRow as $row)
{
$document = $row['#'];
$itemList[] = array(
'PAYMENT_ID' => $document['code'][0]['#'],
'CONTRACTOR_INN' => $document['contractorInn'][0]['#'],
'CONTRACTOR_KPP' => $document['contractorKpp'][0]['#'],
'OPERATION' => $document['operation'][0]['#'],
'SUM' => (int)$document['amount'][0]['#'] / 100,
'CHARGE_DATE' => new Main\Type\Date($document['chargeDate'][0]['#'], 'Y-m-d'),
'DOC_DATE' => new Main\Type\Date($document['docDate'][0]['#'], 'Y-m-d'),
'INVOICE_ID' => $document['documentId'][0]['#']
);
}
$serviceResult->setData(array('ITEMS' => $itemList));
}
}
}
else
{
$serviceResult->addErrors($result->getErrors());
}
return $serviceResult;
}
/**
* @param $data
* @return mixed
*/
private function convertToUtf8($data)
{
static $isUtf = null;
if ($isUtf === null)
$isUtf = defined('BX_UTF');
if ($isUtf === true)
return $data;
if (is_array($data))
{
foreach ($data as $key => $value)
$data[$key] = Main\Text\Encoding::convertEncoding($data[$key], LANG_CHARSET, 'UTF-8');
}
elseif (!is_numeric($data) && is_string($data))
{
$data = Main\Text\Encoding::convertEncoding($data, LANG_CHARSET, 'UTF-8');
}
return $data;
}
/**
* @return bool
*/
public function isTuned()
{
$userCode = $this->getBusinessValue(null, 'ALFABANK_EXTERNAL_USER_CODE');
return !empty($userCode);
}
/**
* @param Payment $payment
* @param $code
* @return mixed
*/
protected function getBusinessValue(Payment $payment = null, $code)
{
if ($payment === null)
{
$paySystemId = $this->service->getField('ID');
$personTypeList = PaySystem\Manager::getPersonTypeIdList($paySystemId);
$personTypeId = array_shift($personTypeList);
return Sale\BusinessValue::get($code, $this->service->getConsumerName(), $personTypeId);
}
return parent::getBusinessValue($payment, $code);
}
/**
* @param Payment $payment
* @return bool
*/
protected function isTestMode(Payment $payment = null)
{
return false;
}
}