Я бы хотел рассказать об одном из простых способов.
Рассмотрим пример оплаты и прокомментируем каждый этап исходным кодом на 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
здравствуйте! есть еще варианты реализации на друпале?
ОтветитьУдалить