В первую очередь скажу, что этот пост будет полезен только тем, кто более менее разбирается в PHP.
И так, я вкратце расскажу принцип работы платежных систем в старой версии корзины (до конструктора из 2.2.0)
По многих причинам корзина не может расширяться плагинами поэтому ниже мы будем писать хаки.
Допустим у нас есть агрегатор платежей
Начиная отсюда я буду считать, что у меня есть вымышленная(!) классическая платежная система
- Она называется myPayment
- Чтобы создать заказ мне нужно отправить через GET или POST на http://merchant.mypayment.com/ массив
- - логин продавца
- - номер заказа
- - сумма
- - хеш - цифровая подпись, образованная через md5 ($orderId : $amount, $password)
- После оплаты на сайт зайдет робот и мне нужно сравнить его хеш со своим и если все нормально, то ставим отметку "оплачено".
Разбираем payment.php
Основной файл, который отвечает за работу с платежными системами - это jbuniversal\framework\controllers\payment.php
На самом деле это контроллер, которая собрал в себя почти всю логику работы.
Сейчас мы в нем увидим жесткие условия для работы с PayPal, Interkassa, Robokassa
Вы можете найти тут такие методы как
_init() - делает минимально необходимые проверки заказа (существование). Так же содержит важную функцию, как определение заказа по внешнему ID
index() - отвечает за страницу с выбором платежной системы. Здесь проверяется, включен ли способ оплаты, и если да, то подготавливаются данные и рендерится HTML код формы.
paymentCallback() - Метод, который отвечает за валидацию заказа и отметку об оплате. Он нужен только для роботов и вернет что-то только если на него правильно отправить POST запрос.
Где хранить настройки ?
Откройте файл jbuniversal\config\basket.xml
И по аналогии добавим в низу
<!-- myPayment-->
<param name="@spacer-mypayment" type="jbspacer" default="MyPayment"/>
<param name="mypayment-enabled" type="jbbool" default="0" label="MyPayment"/>
<param name="mypayment-login" type="text" default="" label="Login" />
<param name="mypayment-password" type="text" default="" label="Password"/>
Это добавит опции вкл/логин/пароль в настройках каталога корзины.
Сохранятся они будут в базу данных как параметры каталога.
Рендеринг формы оплаты
По аналогии с одним из существующих способов добавим код рендеринга
<?php
// myPayment
if ((int)$appParams->get('mypayment-enabled', 0)) { // проверяем, включена ли система
// готовим данные для HTML-формы
$params = new stdClass();
// берем логин и пароль из настроек и избавляемся от случайных пробелов
$params->login = JString::trim($appParams->get('mypayment-login'));
$params->password = JString::trim($appParams->get('mypayment-password'));
// генерируем подпись (смотрите документацию вашего агрегатора)
$params->hash = md5(implode(':', array($params->login, $totalSumm, $this->password)));
// прочие не менее важные параметры формы
$params->amount = $totalSumm;
$params->orderId = $this->orderId;
$params->summFormated = $totalSummFormated;
$this->payments['mypayment'] = $this->app->data->create($params);
}
?>
Открываем этот файл (он содержит общую разметку для выбора платежной системы)
jbuniversal\templates\catalog\renderer\payment\_default.php и добавляем
<?php
if ((int)$view->appParams->get('global.jbzoo_cart_config.mypayment-enabled', 0)) {
echo '<div class="width25">'; // попутно можно подогнать ширину
echo $this->app->jblayout->render('payment_mypayment', $view->payments['mypayment']);
echo '</div>';
}
?>
Теперь создаем шаблон для формы jbuniversal\templates\catalog\renderer\payment_mypayment\_default.php
Переменная $data - это объект JSONData, который будет хранить все то что мы подготовили в index()
<form action="http://merchant.mypayment.com/" method=POST>
<input type="hidden" name="mypay_login" value="<?php echo $data->get('login'); ?>">
<input type="hidden" name="mypay_order_id" value="<?php echo $data->get('orderId'); ?>">
<input type="hidden" name="mypay_amount" value="<?php echo $data->get('amount'); ?>">
<input type="hidden" name="mypay_hash" value="<?php echo $data->get('hash'); ?>">
<input type="submit" class="add-to-cart" value="<?php echo JText::_('JBZOO_PAYMENT_BUTTON'); ?>"/>
</form>
Платежный робот и валидация заказа
Валидация у нас будет с помощью робота, который автомаически заходит на наш сайт по специальному адресу (status)
Адрес этот заранее указан в настройках мерчанта у myPayment
Первое что нам нужно сделать, это определить что робот является именно от myPayment
Для этого в _init() проверяем внешнюю переменную из реквеста, которая отвечает за номер заказа.
Обычно в этом нет никаких проблем, т.к каждая система имеет свое уникальное именование.
Для удобства используем константу
const TYPE_MYPAYMENT = 'MyPayment';
Код определения id оплаченного заказа
<?php
...
// тут я проверяю $_REQUEST['mypay_order_id'], у вас может быть другая.
} else if ($orderId = (int)$this->_jbrequest->get('mypay_order_id')) {
$this->systemType = self::TYPE_MYPAYMENT;
$this->orderId = $orderId;
} else if ( ... ) {
....
?>
Проверяем данные, с которыми к нам пожаловал робот
Снова по аналогии с другими платежными системами вставляем свой код в paymentCallback()
<?php
if ($this->systemType == self::TYPE_MYPAYMENT) {
// подготавливаем свои переменные
$login = JString::trim($this->appParams->get('global.jbzoo_cart_config.mypayment-login'));
$password = JString::trim($this->appParams->get('global.jbzoo_cart_config.mypayment-password'));
$myHash = md5($login . ':' . $password . ':' . $this->orderId);
// берем
$merchantHash = $_REQUEST['mypay_hash']; // без Joomla API, чтобы ничего не стереть
if ($merchantHash === $myHash) { // совпали ли подписи?
// Все отлично, готовим данные для сохранения в наш заказ
$args = array(
'date' => $this->app->date->create()->toSQL(), // текущая дата
'system' => $this->systemType, // имя платежной системы
'additionalState' => null // сюда можно добавить свои произвольные переменные (массиом)
);
// отмечаем заказ как оплаченный
$this->orderDetails->callback('paymentCallback', $args);
// говорим роботу на его языке, что все отлично и он тоже может быть спокоен
jexit('OK' . $this->orderId);
} else {
// прогоняем робота фатальной ошибкой. Валидация не прошла!
throw new AppException('No valid hash');
}
}
?>
Вот и все!
И сразу важные замечания.
- Использовал в качестве примера простейшую выдуманную платежную систему. Поэтому у вас будут свои переменные и свои способы валидации. Возможно что и тех и других будет гораздо больше.
- В качестве рабочего примера рекомендую смотреть реализацию Робокассы. Она имеет очень простое API без наворотов.
- Я лишь описал принцип работы, чтобы дать понять с чего начинать.
Т.к довольно большая часть действий происходит в фоне, то рекомендую использовать какой-нибудь логгер переменных в файл.
Это поможет понять что отправляет робот. Зачастую там есть полезная информация вроде конкретного способа оплаты.
Сам я всегда пользуюсь jbdump
Подключаем класс и дампим
jbdump::log($_REQUEST);
Затем смотрим содержимое папки /logs/ рядом с классом.
Так же на форуме есть другие обсуждения. Вот что вспомнил я
(список на самом деле большой, но у меня действительно нет времени. Поиск на форуме работает
)
http://forum.jbzoo.c...rivat24-liqpay/
http://forum.jbzoo.c...ziny-jbzoo-160/










