Как создать Telegram-бота с авторизацией через сайт

Author Автор: Роман Чернышов    Опубликовано: 5 декабря 2022

Telegram bot Telegram-боты стали неотъемлемой частью любого онлайн сервиса, интернет-магазина, информационного портала или блога — это удобный и быстрый способ дать своим пользователям дополнительный функционал, от получения контента, до совершения каких либо процессов, напрямую относящихся к вашей услуге, товару или бизнесу в целом. С помощью Telegram-ботов, реализуют даже CMR системы, что уж говорить о простых решениях типовых задач. В этой статье-заметке, я хочу рассказать о том, как быстро создать Telegram-бота на PHP с авторизацией пользователей в чате с ботом, через ваш сайт. Далее обо всем подробно.

Регистрация бота в Telegram

Первый этап, самый простой и быстрый, это зарегистрировать нового бота в самом Telegram, для этого ищем в мессенджере, пользователя с ником @BotFather, затем добавляемся в чат с данным ботом, отправляя команду /start, после чего получаем список всех доступных команд, которые мы можем ему отправлять. Вместе со списком команд, мы также получим меню, которое позволяет общаться с ботом просто путем нажатия кнопок в нём(ну это уже классика).

Первая и основная команда /newbot — Она позволяет создать бота и указать его имя, при этом имя бота должно иметь окончание «bot», если вы что-то введете неверно, то @BotFather, вам подскажет. Также здесь нам становятся доступны другие команды, позволяющие задать описание и аватар для нашего нового бота. Это можно сделать и потом. Самое главное, что мы получим после создания бота, это уникальный Token, по которому мы в последующем будем обращаться к боту из нашего кода на PHP.

И так, бот создан, двигаемся дальше.

Настройка Webhook

Webhook — Это вызов мессенджером Telegram, указанного вами URL, который ссылается на ваш PHP скрипт бота, с передачей на него массива с данными, содержащего информацию о произошедших событиях в чате. Например, пользователь отправил команду /help, Telegram активирует запрос на URL Webhook`а, с передачей данных о том, что написал пользователь. Далее, в свою очередь уже ваш PHP скрипт, обработав пришедшую информацию, может отправить в чат с пользователем определенный ответ. На этом вся суть Webhook…

Для того, чтобы Telegram знал по какому URL отправлять данные для вашего PHP скрипта, нужно ему это явно указать. Все, что для этого нужно сделать, это открыть в браузере определенную ссылку, следующего вида:

https://api.telegram.org/bot{TOKEN}/setwebhook?url={URL}

Где вместо {TOKEN} нужно указать ранее полученный код токена для вашего бота, при его создании, а вместо {URL} соответственно нужно указать ваш URL адрес PHP скрипта. Конечный вид ссылки которую нужно открыть в браузере будет выглядеть так:

https://api.telegram.org/bot2390843234:AAFRopig58905Nt4hfzhQ74YR0fJ61INSBA98/setwebhook?url=https://mysite.ru/telegrambot.php

Важное замечание, URL должен иметь протокол HTTPS.

Webhook задан, теперь мы из скрипта на PHP, можем «видеть» всё что происходит у пользователя в чате с ботом, двигаемся дальше.

Алгоритм авторизации пользователей

Как происходит авторизация пользователя в чате с ботом, через ваш сайт? Рассмотрим следующий алгоритм:

1. Пользователь инициализирует чат с ботом
2. Бот проверяет, авторизирован ли данный пользователь (по уникальному ID пользователя), отправляя запросы путем Webhook на скрипт PHP
3. Если пользователь не авторизирован, предлагает ему выполнить авторизацию, для этого он присылает пользователю ссылку на внешний(ваш) сайт, перейдя по которой он сможет авторизироваться(если нужно там же, зарегистрироваться). При этом, ссылка содержит уникальный ID пользователя чата — таким образом, сайт, сможет сопоставить пользователя в чате с учетной записью на сайте, после авторизации.
4. После авторизации на сайте, пользователь будет переброшен обратно в чат с ботом.

Для того, чтобы всё это работало, на вашем сайте должна быть реализована соответствующая система поддержки, такой сквозной авторизации приходящих пользователей из Telegram, с последующим их возвращением обратно в мессенджер. Звучит сложно? Но не стоит напрягаться, на самом деле, реализовать такую систему на любом сайте достаточно просто, будь то популярная CMS типа WordPress, Joomla, Bitrix, DLE или любой другой в том числе самописный движок. Вся суть заключается, в том, чтобы добавить в стандартный механизм авторизации на сайте, распознавание пришедшего пользователя по URL содержащему ID чата из Telegram, и после успешной авторизации внести данные о нем в дополнительную таблицу в БД(создадим таблицу bot_telegram_autorize, её mysql код будет ниже), после чего вернуть обратно в мессенджер простым 301-редиректом. Всё просто.

Скрипт бота на сервере

Несмотря на то, что эта часть с одной стороны является самой сложной, на самом деле тут тоже все предельно просто. Скрипт на PHP, представляет собой просто скрипт принимающий данные присланные от Telegram(выше мы настроили для этого Webhook), осуществляющий определенные(нужные нам действия) и отвечающий пользователю, путем ответного запроса к BOT API Telegram.

Пример скрипта:

// !!! В этом примере используются функции, которые работают с глобальными переменными, скрипт не рефакторился и приводится для примера в том виде, в котором он работает у меня на одном из проектов. Более новую версию скрипта, где все организованно в класс, выложу позже
 
// !!! Работа с БД, осуществляется с помощью стороннего класса, тут оставлен как есть для примера, в реальном проекте его следует изменить
 
// !!! Скрипт не содержит части кода отвечающего за подключение к БД
 
$botToken = '2390843234:AAFRopig58905Nt4hfzhQ74YR0fJ61INSBA98'; // Токен бота, полученный при его создании
$website = "https://api.telegram.org/bot" . $botToken; // URL API для взаимодействия с Telegram
$fileStorage = "https://api.telegram.org/file/bot" . $botToken; // URL API для взаимодействия с Telegram по части загрузки файлов, изображений
 
$responce = file_get_contents('php://input'); // Получаем из входящего потока данных PHP, тело входящего запроса(посланного Telegram), как правило оно в формате JSON
 
$responce = json_decode($responce, TRUE); // Преобразуем JSON в массив
 
if(isset($responce["callback_query"])) { // Тип пришедших данных, от этого зависит лишь структура приходящего массива
	$message = trim($responce["callback_query"]["data"]); // Текст сообщения пришедший от пользователя
	$chatId = $responce["callback_query"]["message"]["chat"]["id"]; // ID пользователя в чате
} else {
	$message = trim($responce["message"]["text"]); // Текст сообщения пришедший от пользователя
	$chatId = $responce["message"]["chat"]["id"]; // ID пользователя в чате
}
 
// Имея $chatId(ID пользователя в чате), проверим авторизован он или нет
$autorize = getAutorize($chatId); // Если пользователь авторизован, функция getAutorize() вернут массив с данными его аккаунта на сайте и статусом текущей авторизации
 
// Основной контроллер. Выбор действия бота, в зависимости от пришедшего сообщения от пользователя
switch($message) {
 
    case "/start": // Если пользователь, прислал команды /start
 
	// Отправляем пользователю в ответ приветственное сообщение
        sendMessage($chatId, "Вас приветствует чат-бот сайта www.rche.ru!");
	// Отправляем пользователю Меню (состоящее из кнопок, на которые он сможет нажимать, отправляя нам новые команды)
	sendGenericMenu($chatId);
 
        break;
 
    case "/help": // Вызов подсказки по командам бота
	// Отправляем пользователю в ответ сообщение
        sendMessage($chatId, "Текст помощи по командам");
	// Отправляем пользователю Меню
	sendGenericMenu($chatId);
        break;
 
    case "/login": // Если пользователь прислал команду для авторизации
	if($autorize[0]['group_id'] == 0) { // Проверяем, был ли пользователь ранее авторизован?
		// Если не авторизирован, отправляем пользователю ссылку для перехода на наш сайт для авторизации
	        sendMessage($chatId, "Авторизуйтесь в чате через наш сайт, для этого перейдите по ссылке: https://{$_SERVER['HTTP_HOST']}/login?tlgr={$chatId}, после авторизации вы сможете продолжить общение в Телеграм чате.");
	} else {
		// Если авторизирован, посылаем пользователю приветствие
	        sendMessage($chatId, "Добро пожаловать, {$autorize[0]['username']}! Вы уже авторизированы.");
	}
        break;
 
    case "/logout": // Если пользователь прислал команду для выхода
	if($autorize[0]['group_id'] > 0) { // Проверяем, был ли пользователь действительено авторизован? 
	        sendMessage($chatId, "До свидания, {$autorize[0]['username']}! ");
		// Деавторизируем пользователя
	        setLogout($chatId);
	}
        break;
 
    case "/menu": // Если пользователь прислал команду для отображения меню
	sendGenericMenu($chatId);
        break;
 
    default:
	// Тут выполняем действия, по умолчанию, если пришедшая команда от пользователя нам не известна, например можно вывести подсказку по командам
	// Отправляем пользователю в ответ сообщение
        sendMessage($chatId, "Текст помощи по командам");
	// Отправляем пользователю Меню
	sendGenericMenu($chatId);
	break;
}
 
// Функция проверки, авторизирован ли пользователь
function getAutorize($chatId) {
 
        global $DB; // Глобальный объект работы с БД. Вы можете заменить объект работы с БД на свой. Тут, используется просто типовое решение для примера
 
	$sql = "SELECT * FROM `bot_telegram_autorize` WHERE `chatId` = '$chatId' LIMIT 1";
	$items = $DB->getAll($sql);
 
	// Ответ, если не авторизирован пустой массив
        $autorize = array();
 
        // Если в таблице БД есть запись с ID данного пользователя значит он авторизован
	if(count($items) > 0) {
		// Если пользователь авторизирован, то функция вернет массив содержащий данные его учетной записи на сайте 
		$sql = "SELECT * FROM `users` WHERE `id` = '{$items[0]['user']}' LIMIT 1";
		$autorize = $DB->getAll($sql);
	} else {
 
	}
	return $autorize;
}
 
// Деавторизируем пользователя
function setLogout($chatId) {
 
        global $autorize, $DB;
        // Удаляем из таблицы запись о пользователя, это будет означать что НЕ авторизирован
	$sql = "DELETE FROM `bot_telegram_autorize` WHERE `chatId` = '$chatId' LIMIT 1";
	$items = $DB->execute($sql);
 
        $autorize = array();
	sendGenericMenu($chatId);
}
 
// Показать пользователю меню
function sendGenericMenu ($chatId) {
 
        global $autorize; // $autorize - массив с данными учетной записи авторизованного на сайте пользователя
 
	if($autorize[0]['group_id'] == 0) { // Если пользователь не авторизован, то показываем ему один тип меню
 
	  $replyMarkup = array(
	     "inline_keyboard" => array(
		  array(
			array(
			"text" => "Войти в чат",
			"callback_data" => "/login"
			),
 
		  )
	     )
	  ); 
 
	} 
 
	if($autorize[0]['group_id'] == 1) { // Если пользователь авторизован, то показываем ему другой тип меню
	  $replyMarkup = array(
	     "inline_keyboard" => array(
		  array(
			array(
			"text" => "Помощь",
			"callback_data" => "/help"
			),
 
			array(
			"text" => "Статистика",
			"callback_data" => "/stats"
			),
 
			array(
			"text" => "Выйти",
			"callback_data" => "/logout"
			)
 
		  )
	     )
	  ); 
	}
 
	$encodedMarkup = json_encode($replyMarkup);
 
	$content = array(
	    'chat_id' => $chatid,
	    'reply_markup' => $encodedMarkup,
	    'text' => "$text"
	);
 
    	$url = $GLOBALS['website']."/sendMessage?chat_id=".$chatId;
    	url_get_contents($url, $content);
}
 
// Отправляем сообщения в чат с пользователем
function sendMessage ($chatId, $message) {
 	global $website;
    	$url = $website . "/sendMessage?chat_id=".$chatId."&text=".urlencode($message);
    	url_get_contents($url);
}
 
// CURL получить контент по ссылке
function url_get_contents($Url, $post = null) {
 
    if(!function_exists('curl_init')) {
        die('CURL is not installed!');
    }
 
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $Url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    if($post) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
    }
    $output = curl_exec($ch);
    curl_close($ch);
 
    return $output;
}

База данных бота

Пример таблицы в базе данных, которая будет отвечать за авторизацию пользователя на сайте. Если в данной таблице есть запись с ID пользователя значит он авторизован. В ином случае нет. Для деавторизации, просто удаляем запись о пользователи из данной таблицы.

CREATE TABLE `bot_telegram_autorize` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user` int(11) NOT NULL COMMENT 'ID пользователя на сайте',
  `chatId` int(11) NOT NULL COMMENT 'ID пользователя в чате с ботом в Телеграм',
  PRIMARY KEY (`id`),
  KEY `user` (`user`),
  KEY `chatId` (`chatId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Cопоставление Телеграм ID чата с пользователем на сайте';

Заключение

Мы рассмотрели пример Telegram бота на PHP с авторизацией пользователей в чате, через ваш сайт. Приведенный код, не включает класс работы с БД и часть кода отвечающую за подключение к БД, но вы с легкостью можете заменить код работы с БД на PDO. Также, можно реструктуризировать код и привести его к классу. Если эта тема вам интересна, то могу выложить также собственный плагин для WordPress, реализующий как функционал авторизации так и бота, который вы сможете использовать как основу, для своей собственной разработки. Авторизация пользователей в чате таким образом, открывает ряд дополнительных возможностей, например доступ к функциям сайта из чата с ботом и многое другое.

Если вам нужна помощь по написанию Telegram ботов, то пожалуйста обращайтесь, буду рад сотрудничеству!

1 Comment to “Как создать Telegram-бота с авторизацией через сайт”

Оставить комментарий

Автор блога
Роман Чернышов
Веб-разработчик,
Full Stack
Senior, Architect
PHP, JavaScript, Node.JS, Python, HTML 5, CSS 3, MySQL, Bash, Linux Admin
Заказать работу
предложить оффер

Моя книга
Книга. Веб-разработчик. Легкий вход в профессию
Печатная книга
Веб-разработчик.
Легкий вход в профессию
Купить за 159₽
Последние вопросы
Список вопросов
Последние комментарии
Меню

Archive

Мои проекты
Insurance CMS Love Crm CMS Совместные покупки Мой PHP Framework Хостинг для моих клиентов Лицензии на мой софт и поддержка