В этой статье я расскажу, как сделать оплату в Ваших IFrame-приложениях в ВКонтакте.
Все предельно просто, нужно сделать какую-нибудь внутреннюю валюту для Вашего приложения и продавать ее за голоса. Я назвал свою валюту просто — «монетки». Когда определились с своей валютой, нужно реализовать ее покупку. Для удобства разработки ВК сделали два режима оплаты: тестовая и «боевая». Тестовый режим доступен сразу после создания приложения, а рабочий, только после прохождения модерации.
Начнем писать код. В первую очередь нужно написать callback.php — этот скрипт указывается в приложении(во вкладке «Платежи») для обратного вызова. Callback.php — будет обрабатывать запросы от ВК, и отдавать информацию о нашем товаре(монетках) и обрабатывать статус заказа. В приведенном ниже коде все понятно, где нужно я написал комментарии. В коде я обращался к базе данных через модели, но Вы можете переписать под себя.
<?php
header("Content-Type: application/json; encoding=utf-8");
$secret_key = 'TPZbwTcE5I**********'; // Защищенный ключ приложения
$input = $_POST;
// Проверка подписи
$sig = $input['sig'];
unset($input['sig']);
ksort($input);
$str = '';
foreach ($input as $k => $v) {
$str .= $k.'='.$v;
}
if ($sig != md5($str.$secret_key)) {
$response['error'] = array(
'error_code' => 10,
'error_msg' => 'Несовпадение вычисленной и переданной подписи запроса.',
'critical' => true
);
} else {
// Подпись правильная
switch ($input['notification_type']) {
case 'get_item':
// Получение информации о товаре
$item = $input['item'];
if ($item == 'item1') {
$response['response'] = array(
'item_id' => 3,
'title' => '3 монетки',
'photo_url' => 'http://bestmems.vk-book.ru/img/maney_coin.png',
'price' => 3
);
} elseif ($item == 'item2') {
$response['response'] = array(
'item_id' => 5,
'title' => '5 монеток',
'photo_url' => 'http://bestmems.vk-book.ru/img/maney_coin.png',
'price' => 5
);
}
break;
case 'get_item_test':
// Получение информации о товаре в тестовом режиме
$item = $input['item'];
if ($item == 'item1') {
$response['response'] = array(
'item_id' => 3,
'title' => '3 монетки (тестовый режим)',
'photo_url' => 'http://bestmems.vk-book.ru/img/maney_coin.png',
'price' => 3
);
} elseif ($item == 'item2') {
$response['response'] = array(
'item_id' => 5,
'title' => '5 монеток (тестовый режим)',
'photo_url' => 'http://bestmems.vk-book.ru/img/maney_coin.png',
'price' => 5
);
}
break;
case 'order_status_change':
// Изменение статуса заказа в тестовом режиме
if ($input['status'] == 'chargeable') {
$order_id = intval($input['order_id']);
$user_id = intval($input['user_id']);
$item_id_c = intval($input['item_id']);
require_once '../classes/Bootstrap.php';
$date_time = date('Y-m-d') . ' ' . date('H:i:s');
// проверяем, может такой заказ уже есть
$select = OrdersPeer::getInstance()->select()->setIntegrityCheck(false)
->where(OrdersPeer::ORDER_ID . ' = 1234')
->limit(1);
$selectRow = MemsPeer::getInstance()->fetchRow($select);
if(count($selectRow)>0){
// если есть такой заказ, то ни чего не делаем
}elseif(count($selectRow)==0){
// если такго заказа нет, то записываем его в бд и увеличиваем счет пользователя
$db = Db::getConnection ();
$sql = "
INSERT INTO `orders` (`vk_uid`, `order_id`, `item_id`, `date`) VALUES ({$user_id}, {$order_id}, {$item_id_c}, '{$date_time}');
UPDATE `autors` SET `money`=`money`+{$item_id_c} WHERE `autors`.`id_vk`='{$user_id}';
";
$result = $db->query($sql);
}
$app_order_id = 1; // Тут фактического заказа может не быть - тестовый режим.
$response['response'] = array(
'order_id' => $order_id,
'app_order_id' => $app_order_id,
);
} else {
$response['error'] = array(
'error_code' => 100,
'error_msg' => 'Передано непонятно что вместо chargeable.',
'critical' => true
);
}
break;
case 'order_status_change_test':
// Изменение статуса заказа в тестовом режиме
if ($input['status'] == 'chargeable') {
$order_id = intval($input['order_id']);
$user_id = intval($input['user_id']);
$item_id_c = intval($input['item_id']);
require_once '../classes/Bootstrap.php';
$date_time = date('Y-m-d') . ' ' . date('H:i:s');
// проверяем, может такой заказ уже есть !!! Это обязательно, поскольку ВК может послать один запрос несколько раз
$select = OrdersPeer::getInstance()->select()->setIntegrityCheck(false)
->where(OrdersPeer::ORDER_ID . ' = 1234')
->limit(1);
$selectRow = MemsPeer::getInstance()->fetchRow($select);
if(count($selectRow)>0){
// если есть такой заказ, то ни чего не делаем
}elseif(count($selectRow)==0){
// если такго заказа нет, то записываем его в бд и увеличиваем счет пользователя
$db = Db::getConnection ();
$sql = "
INSERT INTO `orders` (`vk_uid`, `order_id`, `item_id`, `date`) VALUES ({$user_id}, {$order_id}, {$item_id_c}, '{$date_time}');
UPDATE `autors` SET `money`=`money`+{$item_id_c} WHERE `autors`.`id_vk`='{$user_id}';
";
$result = $db->query($sql);
}
$app_order_id = 1; // Тут фактического заказа может не быть - тестовый режим.
$response['response'] = array(
'order_id' => $order_id,
'app_order_id' => $app_order_id,
);
} else {
$response['error'] = array(
'error_code' => 100,
'error_msg' => 'Передано непонятно что вместо chargeable.',
'critical' => true
);
}
break;
}
}
echo json_encode($response);
?>
Теперь сделаем кнопки для вызова оплаты и напишем js, который будет обрабатывать статусы выполнения оплаты:
<input type="button" value ="Купить 3 монетки" id="item1"/> <input type="button" value ="Купить 5 монеток" id="item2"/>
<script type="text/javascript">
$(document).ready(function(){
$('#item1').click(function(){
order('item1');
});
$('#item2').click(function(){
order('item2');
});
});
function order(item_num) {
var params = {
type: 'item',
item: item_num
};
VK.callMethod('showOrderBox', params);
}
VK.addCallback('onOrderSuccess', function(order_id) {
// оплата прошла успешно, order_id - id заказа
alert("Оплата прошла успешно. ID заказа: " + order_id);
// тут можно сделать, ajax запрос, который вытащит из бд обновленное количество монеток.
});
VK.addCallback('onOrderFail', function() {
alert('Ошибка оплаты, попробуйте повторить позже');
});
VK.addCallback('onOrderCancel', function() {
alert('Оплата отменена пользователем');
});
</script>
Вот и все. Оказывается сделать оплату в приложениях очень просто!
