В этой статье я расскажу, как сделать оплату в Ваших 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>
Вот и все. Оказывается сделать оплату в приложениях очень просто!