Я бы хотел рассказать об одном из простых способов.
Рассмотрим пример оплаты и прокомментируем каждый этап исходным кодом на PHP.
0. Размещению на сайте оплаты через смс предшествует заключение договора с компанией предоставляющей эти услуги.
1. Пользователь заходит на страничку, где ему предлагается скачать приложение, предварительно отослав смс с текстом на указанный номер.
Реализация: Выводится статичные текст с текстом и телефоном, который предоставила на предыдущем этапе организация
2. Клиент отправляет СМС. Ему приходит ответная с уникальным кодом на доступ
Реализация: Сервер смс компании, получает сообщение с нужным тектом на номер. Генерируется событие, вызывающее произвольную (настраиваемую) страницу на нашем сайте. На это странице мы произвольны сделать, что угодно.
Генерируем код, и записываем в БД:
function getCOde() { $code = sprintf("%06x", rand(1000000, 10000000)); //рандомное число, преобразованное в hex //проверяем на повторения $res = db_query("SELECT COUNT(*) AS cnt FROM {sms_pay} WHERE code = '%s'", $code); $codes = db_fetch_array($res); if($codes['cnt'] > 0) { getCode(); //генерируем еще раз } db_query("INSERT INTO {sms_pay} (code) VALUES('%s')", rand(), $code); //записываем код в БД return $code; }Сгенерированный код, вываливается через echo в браузер, а сервер весь сгенерированый текст отправляет в виде смс обратно клиенту.
На данном этапе код еще не привязан ни к одному материалу и его можно активировать на любом.
3. Клиент получил код, вводит его, чтобы получить доступ к материалу
Реализация: Сервер сайт получает код, проверяет его наличие в БД. Если код верный, то в БД вносятся данные о файле к которому был получен доступ, также для защиты от передачи кода третьим лицам в бд заносится ip адрес клиента и ставится кука.
Файл может быть скачан не сразу, а по частям. В этом случае пользователю дается несколько часов на скачку файла: в бд заносим также время первого обращения к файлу.
После этого пользователю файл стримится прямо в браузер с утановкой необходимых хеадреов, чтобы у клиента не было прямого доступа к файлу (Об этом можно почитать отдельно, я пользуюсь стандартными функциями Drupal)
4. Клиент повторно обращается к этому же файлу.
Реализация: При повторном обращении к файлу, снова проверять код не обязательно. Необходимо сверить лишь куки и ip пользователя, а также id файла к которому идет обращение.
5. Если пользователь пытается обратится к другому файлу с этим же кодом, то это ему не удастся, т.к. он не пройдет проверку по id файла.
6. Код был передан третьим лицам. Пользователь не пройдет проверку по ip и куке.
Примерный код для предыдущих пунктов можно видеть в листинге: (php/Drupal, точка входа функция sms_pay_file_download)
function checkNumber($code, $fid) { //сверяемся с БД $res = db_query("SELECT COUNT(*) AS cnt FROM {sms_pay} WHERE code = '%s' AND (fid = %d OR fid = 0)", $code, $fid); $sms = db_fetch_array($res); if($sms['cnt'] > 0) return true; return false; } /* Проверка прав на скачку файла */ function isAllowDownload($file) { $node = getNodeFile($file); $hash = $_COOKIE['game_hash_'.$node['fid']]; $result = db_query("SELECT * FROM {sms_pay} WHERE hash = '%s' AND ip = '%s'", $hash, ip_address()); $file = db_fetch_array($result); if(!empty($file['id'])) { if($file['dl_time'] < time() - variable_get('sms_time', 3) * 3600) { db_query("DELETE FROM {sms_pay} WHERE hash = '%s' AND ip = '%s'", $hash, ip_address()); echo theme('page', t("Время доступа к файлу вышло. Отправьте СМС заново. У Вас было !hours часов с !date", array('!hours' => variable_get('sms_time', 3), '!date' => format_date($file['dl_time'])))); exit; } return true; } return false; } function sms_pay_genCode($nid, $fid) { return substr(sprintf("%x", $nid.$fid), 0, 6); } /* Уникальная строка для пользователя */ function getHash() { return md5($node['fid'].ip_address().time().rand()); } /* Получить данные о ноде по файлу */ function getNodeFile($file) { $result = db_query("SELECT n.nid nid, n.title game, u.fid fid, a.dst path ". "FROM {node} n ". "INNER JOIN {upload} u ". "ON u.nid = n.nid ". "INNER JOIN {files} f ". "ON(f.fid = u.fid)". "LEFT JOIN {url_alias} a ". "ON a.src = CONCAT('node/',n.nid) ". "WHERE f.filepath = '%s'", "sites/default/files/".$file); return db_fetch_array($result); } /* Hook File Download */ function sms_pay_file_download($filepath) { $mime = substr($filepath, -3); if(in_array($mime, explode(" ", variable_get('pay_ext', 'exe zip swf rar')))) { $node = getNodeFile($filepath); if(!isAllowDownload($filepath)) { if(!empty($_POST['code'])) { //ввели какойто код if(checkNumber($_POST['code'], $node['fid'])) { //он верный setAllowSmsPay($filepath); } else { echo theme('page', "Вы ввели не верный код скачки или уже активировали его на другой игре."); exit; } } } $res = db_query("SELECT totalcount FROM node_counter WHERE nid = %d", $node['fid']); $cnt = db_fetch_array($res); //увеличим счетчик скачивания if($cnt['totalcount'] > 0 ) { db_query("UPDATE node_counter SET totalcount = totalcount + 1 WHERE nid = %d", $node['fid']); } else { db_query("INSERT INTO node_counter (nid, totalcount) VALUES(%d, 1)", $node['fid']); } } } /* Установка возможности скачки файла для текущего пользователя */ function setAllowSmsPay($file) { $node = getNodeFile(basename($file)); $hash = getHash(); setcookie("game_hash_".$node['fid'], $hash, time() + variable_get('sms_time', 3) * 3600, "/"); db_query("UPDATE {sms_pay} SET dl_time = %d, hash = '%s', ip = '%s', fid = %d", time(), $hash, ip_address(), $node['fid']); }
Метод имеет недостаток: нет взаимосвязи между отсылаем сообщение и пришедшим кодом, т.к. на странице генерации кода мы еще не знаем для какого файла будет применен код. Нельзя будет сделать бонусные или привязанные к файлу коды.
Пример реализации можно видеть на сайте mobipad.ru
здравствуйте! есть еще варианты реализации на друпале?
ОтветитьУдалить