Обработчики платежной системы реализуют логику оплаты и принятия информации о завершении оплаты от платежной системы. Код обработчика вносится при редактировании платежной системы через центр администрирования, файлы размещаются в директории /hostcmsfiles/shop/pay/handler{ID}.php
.
Обработчик платежной системы представляет собой класс, унаследованный от Shop_Payment_System_Handler
, имя класса зависит от идентификатора платежной системы по схеме Shop_Payment_System_Handler{ID}
В левом меню выберите раздел Контент → Интернет-магазины. Перейдите в магазин и выберите в меню Справочники пункт Платежные системы.
Пример минимального кода обработчика для платежной системы с кодом 9:
<?php
class Shop_Payment_System_Handler9 extends Shop_Payment_System_Handler
{
}
Пример типового обработчика платежной системы с кодом 9:
<?php
class Shop_Payment_System_Handler9 extends Shop_Payment_System_Handler
{
/**
* Идентификатор валюты, в которой передается сумма в платежную систему
*/
protected $_currency = 1;
/**
* Метод, вызываемый в коде настроек ТДС через Shop_Payment_System_Handler::checkBeforeContent($oShop); Может быть использован для получения данных от платежной системе о статусе платежа.
*/
public function checkPaymentBeforeContent()
{
if (isset($_REQUEST['SignatureValue']))
{
// Получаем ID заказа
$order_id = intval(Core_Array::getRequest('InvId'));
$oShop_Order = Core_Entity::factory('Shop_Order')->find($order_id);
if (!is_null($oShop_Order->id))
{
// Вызов обработчика платежной системы
Shop_Payment_System_Handler::factory($oShop_Order->Shop_Payment_System)
->shopOrder($oShop_Order)
->paymentProcessing();
}
exit();
}
}
/**
* Метод, вызываемый в коде ТДС через Shop_Payment_System_Handler::checkAfterContent($oShop); Может быть использован как для получения информации от платежной системы о статусе платежа, так и о выводе информации о результатах оплаты после перенаправления пользователя платежной системой на корзину магазина.
*/
public function checkPaymentAfterContent()
{
if (isset($_REQUEST['SignatureValue']))
{
// Получаем ID заказа
$order_id = intval(Core_Array::getRequest('InvId'));
$oShop_Order = Core_Entity::factory('Shop_Order')->find($order_id);
if (!is_null($oShop_Order->id))
{
// Вызов обработчика платежной системы
Shop_Payment_System_Handler::factory($oShop_Order->Shop_Payment_System)
->shopOrder($oShop_Order)
->paymentProcessing();
}
}
}
/*
* Метод, запускающий выполнение клиентского обработчика. Используется с версии 6.9.7
*/
public function userExecute()
{
// Показ формы оплаты (перехода на оплату), сама форма генерируется в getNotification()
$this->printNotification();
return $this;
}
/**
* Оформление нового заказа
*/
protected function _processOrder()
{
// Вызываем стандартное оформление заказа из родительского класса Shop_Payment_System_Handler
parent::_processOrder();
// Установка XSL-шаблонов в соответствии с настройками в узле структуры
$this->setXSLs();
// Отправка писем клиенту и пользователю
$this->send();
return $this;
}
/**
* Обработка уведомлений об оплате заказа или возврате пользователя из магазина.
* Используются уникальные параметры, передаваемые платежной системой и позволяющие
* определить, идет уведомление об платежной системы об оплате или возврат пользователя
* из платежной системы на сайт после успешной/неуспешной оплаты.
*/
public function paymentProcessing()
{
// Пользователь перешел на страницу с уведомлением о статусе заказа
if (isset($_REQUEST['InvId']) && isset($_REQUEST['некийПараметр']))
{
$this->showResultMessage();
return TRUE;
}
// Пришло подтверждение оплаты, обработаем его
if (isset($_REQUEST['InvId']))
{
$this->ProcessResult();
return TRUE;
}
}
/**
* Сумма заказа в валюте платежной системы ($this->_currency)
*/
public function getSumWithCoeff()
{
return Shop_Controller::instance()->round(($this->_currency > 0
&& $this->_shopOrder->shop_currency_id > 0
? Shop_Controller::instance()->getCurrencyCoefficientInShopCurrency(
$this->_shopOrder->Shop_Currency,
Core_Entity::factory('Shop_Currency', $this->_currency)
)
: 0) * $this->_shopOrder->getAmount() * $this->_coefficient);
}
/**
* Возвращает строку с формой перехода к оплате
*/
public function getNotification()
{
$sSum = $this->getSumWithCoeff();
ob_start();
?>
<h1>Оплата через платежную систему XYZ</h1>
<p>Сумма к оплате составляет <strong><?php echo $sSum?> <?php echo Core_Entity::factory('Shop_Currency', $this->_currency)->name?></strong></p>
<p>Для оплаты нажмите кнопку "Оплатить".</p>
<form action="http://xxxyyyzzz.com/pay.php" method="POST">
<input type="hidden" name="Sum" value="<?php echo $sSum?>">
<input type="hidden" name="InvId" value="<?php echo $this->_shopOrder->id?>">
<input type="hidden" name="Desc" value="<?php echo "Оплата счета N {$this->_shopOrder->invoice}"?>">
<input type="submit" value="Оплатить">
</form>
<?php
return ob_get_clean();
}
/**
* Получить код счета (в данном случае равен коду перехода на оплату).
* Используется, например, в центре администрирования при печати заказа
*/
public function getInvoice()
{
return $this->getNotification();
}
// Вывод сообщения об успешности/неуспешности оплаты
function showResultMessage()
{
$iShop_Order_Id = Core_Array::getRequest('InvId', 0);
$oShop_Order = Core_Entity::factory('Shop_Order')->find($iShop_Order_Id);
if(is_null($oShop_Order->id))
{
// Заказ не найден
return FALSE;
}
$sHash = Core_Array::getRequest('Signature', '');
$sSum = Core_Array::getRequest('Sum', '');
// В данном примере сумма обязательно должна быть с двумя десятичными нулями
$sHostcmsSum = sprintf("%.2f", $this->getSumWithCoeff());
// Суммы совпали?
$sHostcmsHash = $sSum == $sHostcmsSum
? md5("параметры_используемые_при_контроле_хэша")
: '';
// Сравниваем хэши
if (mb_strtoupper($sHostcmsHash) == mb_strtoupper($sHash))
{
$sStatus = $oShop_Order->paid == 1 ? "оплачен" : "не оплачен";
?><h1>Заказ <?php echo $sStatus?></h1>
<p>Заказ <strong>№ <?php echo $oShop_Order->invoice?></strong> <?php echo $sStatus?>.</p>
<?php
}
else
{
?><p>Хэш не совпал!</p><?php
}
}
/*
* Обработка статуса оплаты
*/
function ProcessResult()
{
$iShop_Order_Id = Core_Array::getRequest('InvId', 0);
$oShop_Order = Core_Entity::factory('Shop_Order')->find($iShop_Order_Id);
if(is_null($oShop_Order->id) || $oShop_Order->paid)
{
// Заказ не найден
return FALSE;
}
$sHash = Core_Array::getRequest('Signature', '');
$sSum = Core_Array::getRequest('Sum', '');
// В данном примере сумма обязательно должна быть с двумя десятичными нулями
$sHostcmsSum = sprintf("%.2f", $this->getSumWithCoeff());
if ($sSum == $sHostcmsSum)
{
$sHostcmsHash = md5("параметры_используемые_при_контроле_хэша");
// Сравниваем хэши
if (mb_strtoupper($sHostcmsHash) == mb_strtoupper($sHash))
{
$this->shopOrder($oShop_Order)->shopOrderBeforeAction(clone $oShop_Order);
$oShop_Order->system_information = "Товар оплачен через платежную систему XYZ.\n";
$oShop_Order->paid();
$this->setXSLs();
$this->send();
// Ответ платежной системе на уведомление об оплате, см. API платежной системы
echo "OK{$oShop_Order->id}\n";
ob_start();
$this->changedOrder('changeStatusPaid');
ob_get_clean();
}
else
{
$oShop_Order->system_information = 'XYZ хэш не совпал!';
$oShop_Order->save();
// Ответ платежной системе на уведомление об оплате, см. API платежной системы
echo "bad sign\n";
}
}
else
{
$oShop_Order->system_information = 'XYZ сумма не совпала!';
$oShop_Order->save();
// Ответ платежной системе на уведомление об оплате, см. API платежной системы
echo "bad sign\n";
}
}
}
В коде настроек ТДС корзины вызов обработчиков платежных систем осуществлется следующим образом:
Shop_Payment_System_Handler::checkBeforeContent($oShop);
в коде ТДС:
Shop_Payment_System_Handler::checkAfterContent($oShop);