Всем привет. Только закончил прикручивать оплату через Tinkoff Bank и пока еще не все забыл хочу поделить наработками.
Предполагается, что у вас уже настроен Shopkeeper и остается только прикрутить оплату. В Тинькове вы тоже зарегались и получили Идентификатор терминала и Пароль.
В репозитарии ModX есть модуль Тинькова, но он там очень сырой и без документации, в общем то его я и переписал почти полностью.
Первым делом необходимо перейти на страницу Оформления заказа или Корзину и установить в вызове снипета FormIt параметр &redirectTo=100
равным ID страницы где вызывается снипет Тинькова. У меня эта страница называется Оплата и содержит вызов снипета [[!Tinkoff]]
Добавим в настройки Shopkeeper`a способ оплаты Картой (card).
payment.zip
Качаем архив и закидываем в папку /assets/components/ там же и распакуем. Появится папка payment в которой найдите файл config.php и настройте под себя
Содержимое файла config.php
<?php
define('PAY_URL', 'https://securepay.tinkoff.ru/rest/Init');// URL запроса
define('TERMINAL_KEY', '1479721120904DEMO');// Идентификатор терминала
define('PAY_PASSWORD', '73mq7zfg30hhhwde'); // пароль Тинькова
define('PAY_NETMASK', '91.194.226.0/23'); // подсеть с которой приходит нотификация
Содержимое файла result.php
<?php
require_once '/home/u67838/foodseasons.ru/www/config.core.php'; // указать ваш абсолютный путь до файла
require_once MODX_CORE_PATH.'model/modx/modx.class.php';
require_once MODX_CORE_PATH.'../assets/components/payment/config.php';
$ip = ip2long($_SERVER['REMOTE_ADDR']);
list($net,$mask) = explode('/',PAY_NETMASK);
$net = ip2long($net);
$mask = pow(2, 32 - $mask) - 1;
$net = $net&~$mask;
if (!(($ip^$net)&~$mask)) { // Проверяем принадлежит ли IP к подсети Тинькова
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if($_POST["TerminalKey"] == TERMINAL_KEY) { // Сверяем Идентификатор терминала
$modx = new modX();
$modx->initialize('web');
$modx->addPackage('shopkeeper3', $modx->getOption('core_path').'components/shopkeeper3/model/');
$order_id = $_POST['OrderId'];
$order = $modx->getObject('shk_order', $order_id);
if ( (isset($order)) && ($order > 0) ) {
$order_status = $order->get('status');
$amount = $order->get('price');
$amount = $amount*100; // Сумма в копейках
$email = $order->get('email');
$args['OrderId'] = $order_id;
$args['Amount'] = $amount;
$args['Description'] = "Оплата счета №".$order_id;
$args['DATA'] = "Email=".$email;
$args['TerminalKey'] = TERMINAL_KEY;
$args['Password'] = PAY_PASSWORD;
// генерируем наш токен, чтобы сверить с тем что пришел в нотификации
$token = '';
ksort($args);
foreach ($args as $arg){$token .= $arg;}
//echo '<p>'.$token.'</p>';
$token = hash('sha256', $token);
unset($args);
if( ($_POST["Token"] == $token) && ($_POST["ErrorCode"] == 0) && ($_POST["Success"]) ){ // Сверяем токены наш и нотификации из банка
$change_status = $order->set('status', 6);
$order->save();
$modx->invokeEvent('OnSHKChangeStatus',array('order_id'=>$order_id,'status'=>6));
echo "OK";
}
} else {
echo "Order not found";
}
}
}
}
Далее создаем сам снипет Tinkoff
<?php
if ( ($_SESSION['shk_lastOrder']['payment'] != 'card') && (!$_GET['ord_id']) ){ // Проверяем что у нас способ оплаты указан card
$modx->sendRedirect('/checkout/success.html', 0, 'REDIRECT_HEADER'); // иначе редиректим на страницу какую хотите
}
if ( ($_GET['ord_id']) && ($_GET['payment'] == 'card') ){
$order_id = $_GET['ord_id'];
}else{
$order_id = $_SESSION['shk_lastOrder']['id']; // получаем ID заказа
}
require_once MODX_BASE_PATH."assets/components/payment/config.php"; подтягиваем конфиг Тинькова
$order = $modx->getObject('shk_order', $order_id);
if ( isset($order) ){
$order_status = $order->get('status');
$amount = $order->get('price');
$amount = $amount*100; // Сумма в копейках
$email = $order->get('email');
$args['OrderId'] = $order_id?:'';
$args['Amount'] = $amount?:'';
$args['Description'] = "Оплата счета №".$order_id;
$args['DATA'] = "Email=".$email;
$args['TerminalKey'] = TERMINAL_KEY;
$args['Password'] = PAY_PASSWORD;
//token generation
$token = '';
ksort($args);
foreach ($args as $arg){$token .= $arg;}
//echo '<p>'.$token.'</p>';
$token = hash('sha256', $token);
$args['Token'] = $token;
unset($args['Password']);
$args = http_build_query($args);
//return print_r($args,true);
if ($curl = curl_init()){
curl_setopt($curl, CURLOPT_URL, PAY_URL);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $args);
$out = curl_exec($curl);
$json = json_decode($out);
//echo '<p>'.print_r($json,true).'</p>';
curl_close($curl);
if ($json->PaymentURL){
$change_status = $order->set('status', 2);
$order->save();
$modx->invokeEvent('OnSHKChangeStatus',array('order_id'=>$order_id,'status'=>2));
$modx->sendRedirect($json->PaymentURL);
}
return $json->PaymentURL?:$out;
}else{
$modx->sendRedirect('/checkout/error.html', 0, 'REDIRECT_HEADER');
}
}
В личный кабинет Тинькова добавим URL для нотификации http://site.ru/assets/components/payment/result.php
Вот собственно и вся настройка. Теперь идем в магазин, добавляем товар в корзину, выбираем способ оплаты Картой (card) и попадаем на страницу где Тиньков просит ввести данные карты, после успешной оплаты статус заказа изменится на Оплачен