В этом руководстве я подробно опишу процесс создания Telegram бота "с нуля" без использования сторонних библиотек с GitHub. Мы пройдем все этапы: создание канала, отправку сообщений через PHP и создание бота.
Если у вас еще нет Telegram, скачайте и установите его:
Для мобильных устройств: App Store или Google Play
Для компьютера: https://desktop.telegram.org/
Откройте Telegram
Нажмите на меню (три горизонтальные линии или кнопка "New Message")
Выберите "New Channel"
Введите название канала (например, "My Test Channel")
Добавьте описание (необязательно)
Установите канал как Public (если хотите, чтобы он был доступен по ссылке) или Private
Если выбрали Public, придумайте уникальное имя для ссылки (например, my_test_channel_123)
Нажмите "Create"
(Мы сделаем это после создания бота в разделе 3)
Для этого нам понадобится:
Веб-хостинг с поддержкой PHP
API-токен бота (мы получим его в разделе 3)
Добавьте своего бота в канал как администратора
Отправьте любое сообщение в канал
Перейдите по ссылке: https://api.telegram.org/bot<ВАШ_ТОКЕН>/getUpdates
Найдите в ответе chat с полем id - это и есть chat_id вашего канала
Создайте файл send_to_channel.php:
<?php
// Конфигурация
$botToken = 'ВАШ_ТОКЕН_БОТА'; // Замените на реальный токен
$chatId = '@my_test_channel_123'; // Или ID канала, например -100123456789
$message = 'Привет из PHP скрипта!';
// URL API Telegram
$apiUrl = "https://api.telegram.org/bot{$botToken}/sendMessage";
// Данные для отправки
$data = [
'chat_id' => $chatId,
'text' => $message,
'parse_mode' => 'HTML'
];
// Инициализация cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Отправка запроса
$response = curl_exec($ch);
// Проверка ошибок
if (curl_errno($ch)) {
echo 'Ошибка cURL: ' . curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode !== 200) {
echo "HTTP ошибка: {$httpCode}\n";
echo "Ответ: {$response}";
} else {
echo "Сообщение успешно отправлено!";
}
}
// Закрытие соединения
curl_close($ch);
?>Откройте Telegram и найдите @BotFather
Начните чат с BotFather и отправьте команду /start
Для создания нового бота отправьте /newbot
Введите имя бота (например, "MyTestBot")
Введите username бота (должен заканчиваться на bot, например "MyTest123Bot")
Получите API-токен (сохраните его в надежном месте)
Создайте файл bot.php:
<?php
// Получаем входящее сообщение
$content = file_get_contents("php://input");
$update = json_decode($content, true);
// Проверяем, есть ли сообщение
if(!isset($update['message'])) {
exit;
}
$message = $update['message'];
$chatId = $message['chat']['id'];
$text = $message['text'] ?? '';
// Токен вашего бота
$botToken = 'ВАШ_ТОКЕН_БОТА';
// Функция для отправки сообщений
function sendMessage($chatId, $text, $botToken) {
$url = "https://api.telegram.org/bot{$botToken}/sendMessage";
$data = [
'chat_id' => $chatId,
'text' => $text,
'parse_mode' => 'HTML'
];
$options = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
// Обработка команд
switch($text) {
case '/start':
$response = "Привет! Я тестовый бот. Отправь мне любое сообщение, и я отвечу.";
break;
case '/help':
$response = "Доступные команды:\n/start - начать общение\n/help - помощь";
break;
default:
$response = "Вы написали: \"{$text}\". Я простой бот и просто повторяю ваши сообщения.";
}
// Отправка ответа
sendMessage($chatId, $response, $botToken);
?>Чтобы Telegram знал, куда отправлять сообщения для вашего бота, нужно установить вебхук.
Создайте файл set_webhook.php:
<?php
$botToken = 'ВАШ_ТОКЕН_БОТА';
$webhookUrl = 'https://ваш-сайт.ру/bot.php'; // Полный URL до вашего bot.php
$apiUrl = "https://api.telegram.org/bot{$botToken}/setWebhook?url={$webhookUrl}";
$response = file_get_contents($apiUrl);
echo "Результат установки вебхука:\n";
var_dump(json_decode($response, true));
?>После запуска этого скрипта Telegram будет отправлять все обновления на указанный URL.
Откройте свой канал
Нажмите на название канала вверху
Выберите "Administrators"
Нажмите "Add Admin"
Введите username вашего бота (например, @MyTest123Bot)
Выберите разрешения (можно оставить все выключенными, кроме "Post Messages")
Нажмите "Save"
Отправьте сообщение в чат с ботом - он должен ответить
Запустите send_to_channel.php - сообщение должно появиться в канале
Проверьте, что бот может отправлять сообщения в канал
Добавьте в начало bot.php проверку секретного токена:
$secretToken = 'ВАШ_СЕКРЕТНЫЙ_ТОКЕН'; // Проверка, что запрос пришел от Telegram if ($_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] !== $secretToken) { http_response_code(403); exit('Unauthorized'); }
И обновите set_webhook.php:
$secretToken = 'ВАШ_СЕКРЕТНЫЙ_ТОКЕН'; $webhookUrl = 'https://ваш-сайт.ру/bot.php'; $apiUrl = "https://api.telegram.org/bot{$botToken}/setWebhook"; $apiUrl .= "?url={$webhookUrl}"; $apiUrl .= "&secret_token={$secretToken}";
Добавьте в bot.php перед обработкой сообщения:
// Логирование $log = date('Y-m-d H:i:s') . ' ' . print_r($update, true) . "\n"; file_put_contents('bot.log', $log, FILE_APPEND);
Это создаст файл bot.log с историей всех запросов.
Теперь у вас есть:
Рабочий Telegram канал
PHP скрипт для отправки сообщений в канал
Telegram бот, который отвечает на сообщения
Вебхук для обработки сообщений бота
Вы можете расширять функционал бота, добавляя новые команды и обработчики сообщений в switch в файле bot.php.
Давайте разберёмся по порядку с вашими вопросами:
В Telegram для мобильных устройств (Android/iOS) процесс немного отличается:
Откройте Telegram
Нажмите на иконку карандаша (Android) или "New Message" (iOS)
Выберите "New Channel" (может быть скрыто под "More" или "Other")
Если действительно нет варианта:
Создайте временную группу
В настройках группы преобразуйте её в канал (опция "Convert to Channel")
Если вы используете Telegram Desktop:
Нажмите на меню (три полоски)
Выберите "New Channel"
Пошаговая инструкция:
Найдите в Telegram пользователя @BotFather
Можно через поиск вверху экрана
Или перейдите по прямой ссылке: t.me/BotFather
Начните диалог с командой:
/start
Для создания бота отправьте:
/newbot
Далее BotFather попросит:
Имя бота (то, что будут видеть пользователи), например: "My Test Bot"
Username бота (должен заканчиваться на "bot"), например: "MyTest12345Bot"
После успешного создания вы получите сообщение вида:
Done! Congratulations on your new bot. You will find it at t.me/MyTest12345Bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. Use this token to access the HTTP API: 123456789:AAFm2eXyzAbCdEfGhIjKlMnOpQrStUvWxYz Keep your token secure and store it safely...
Этот длинный код (в примере 123456789:AAFm2eXyzAbCdEfGhIjKlMnOpQrStUvWxYz) и есть ваш API токен.
Токен - это как пароль от вашего бота:
Никому его не сообщайте
Не публикуйте в открытом доступе
Если токен стал известен посторонним - немедленно замените через @BotFather командой /revoke
Если потеряли токен:
Снова напишите @BotFather
Используйте команду /mybots
Выберите своего бота
Выберите "API Token"
Затем "Reveal Token"
Для тестирования API сразу после получения токена:
Откройте в браузере:
https://api.telegram.org/botВАШ_ТОКЕН/getMe
Должен прийти ответ с информацией о боте
Теперь у вас есть всё необходимое для продолжения работы с API Telegram. Токен нужно подставить во все скрипты, где используется ВАШ_ТОКЕН_БОТА.
Из предоставленного ответа API Telegram видно, что вы уже успешно получили chat_id вашего канала. Давайте разберёмся подробно:
Из ответа видно:
"chat": { "id": -1002759717600, "title": "UniFREE", "username": "unifree2025", "type": "channel" }
Ваш chat_id: -1002759717600
В вашем случае API возвращает только информацию о изменении статуса бота в канале (my_chat_member), а не обычные сообщения. Это происходит потому что:
Вы добавили бота как администратора в канал
Но еще не отправляли обычных сообщений в канал
Убедитесь, что бот добавлен в канал как администратор (у вас это уже сделано)
Отправьте любое сообщение в канал (от вашего имени или от бота)
Снова запросите обновления:
https://api.telegram.org/botВАШ_ТОКЕН/getUpdates
Теперь в ответе должно появиться сообщение с chat_id
Если по какой-то причине обычные сообщения не появляются в getUpdates, используйте этот метод:
Отправьте сообщение в канал от имени бота через API:
<?php
$botToken = 'ВАШ_ТОКЕН';
$chatId = '@unifree2025'; // используйте username канала
$message = 'Тестовое сообщение';
$url = "https://api.telegram.org/bot{$botToken}/sendMessage?chat_id={$chatId}&text=".urlencode($message);
$response = file_get_contents($url);
echo $response;
?>Если сообщение отправилось успешно - в ответе будет chat_id
Для работы с каналом используйте один из вариантов:
ID: -1002759717600
Username: @unifree2025 (если канал публичный)
Пример URL для отправки сообщения:
https://api.telegram.org/botВАШ_ТОКЕН/sendMessage?chat_id=-1002759717600&text=Привет
Для каналов chat_id всегда начинается с -100 и содержит 13 цифр (в вашем случае -1002759717600). Это нормально и именно этот ID нужно использовать для работы с API.
Ошибка SSL возникает, когда cURL не может проверить сертификат SSL вашего сервера. Давайте решим эту проблему несколькими способами:
Замените ваш код в send_to_channel.php:
<?php
$botToken = 'ВАШ_ТОКЕН_БОТА';
$chatId = '-1002759717600'; // Ваш chat_id
$message = 'Привет из PHP скрипта!';
$url = "https://api.telegram.org/bot{$botToken}/sendMessage";
$data = [
'chat_id' => $chatId,
'text' => $message,
'parse_mode' => 'HTML'
];
$options = [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false, // Отключаем проверку SSL
CURLOPT_SSL_VERIFYHOST => 0 // Отключаем проверку хоста
];
$ch = curl_init();
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Ошибка cURL: ' . curl_error($ch);
} else {
echo "Ответ Telegram API: " . $response;
}
curl_close($ch);
?>Скачайте актуальный cacert.pem файл с:
https://curl.se/docs/caextract.html
Сохраните его на сервере (например, в /path/to/cacert.pem)
Модифицируйте код:
// Добавьте в массив $options: $options = [ // ... другие настройки ... CURLOPT_SSL_VERIFYPEER => true, CURLOPT_CAINFO => '/path/to/cacert.pem', CURLOPT_SSL_VERIFYHOST => 2 ];
<?php
$botToken = 'ВАШ_ТОКЕН_БОТА';
$chatId = '-1002759717600';
$message = 'Привет из PHP скрипта!';
$url = "https://api.telegram.org/bot{$botToken}/sendMessage?" . http_build_query([
'chat_id' => $chatId,
'text' => $message,
'parse_mode' => 'HTML'
]);
$context = stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
]
]);
$response = file_get_contents($url, false, $context);
if ($response === FALSE) {
echo "Ошибка при отправке сообщения";
} else {
echo "Сообщение отправлено: " . $response;
}
?>Перед отправкой сообщения проверьте, доступен ли API Telegram:
$testUrl = 'https://api.telegram.org'; $connected = @fsockopen($testUrl, 443); if ($connected) { fclose($connected); echo "Соединение с Telegram API установлено"; } else { echo "Нет соединения с Telegram API. Проверьте интернет-подключение"; }
Для локального тестирования можно использовать первый способ
На боевом сервере обязательно используйте второй способ с правильным сертификатом
Если у вас собственный SSL-сертификат на сервере, убедитесь что он правильно установлен
Проверьте дату и время на сервере - неправильное время может вызывать SSL ошибки
Если после этих изменений ошибка сохраняется, возможно, проблема в настройках сервера. В этом случае обратитесь к вашему хостинг-провайдеру с запросом о проблемах с SSL-сертификатами.
Ошибка "Malformed input to a URL function" в cURL означает, что в URL или данных запроса есть недопустимые символы или неправильное форматирование. Давайте исправим ваш код для корректной отправки сообщения в Telegram.
send_to_channel.php:<?php
// Конфигурация
$botToken = 'ВАШ_ТОКЕН_БОТА'; // Замените на реальный токен
$chatId = '-1002759717600'; // Ваш chat_id канала
$message = 'Тестовое сообщение из PHP';
// URL API Telegram
$apiUrl = "https://api.telegram.org/bot{$botToken}/sendMessage";
// Правильное формирование данных
$postData = [
'chat_id' => $chatId,
'text' => $message,
'parse_mode' => 'HTML'
];
// Инициализация cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); // Кодируем данные
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Только для тестирования!
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // Только для тестирования!
// Отправка запроса
$response = curl_exec($ch);
// Проверка ошибок
if (curl_errno($ch)) {
echo 'Ошибка cURL: ' . curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode !== 200) {
echo "HTTP ошибка: {$httpCode}\n";
echo "Ответ Telegram: {$response}";
} else {
echo "Сообщение успешно отправлено в канал!";
echo "<pre>" . print_r(json_decode($response, true), true) . "</pre>";
}
}
// Закрытие соединения
curl_close($ch);
?>Неправильное формирование URL:
Убедитесь, что токен не содержит лишних символов
Проверьте, что chat_id правильный (ваш: -1002759717600)
Проблемы с передачей данных:
Используйте http_build_query() для правильного кодирования POST-данных
Убедитесь, что в сообщении нет недопустимых символов
Проверка работы без cURL:
$testUrl = "https://api.telegram.org/bot{$botToken}/sendMessage?" . http_build_query(['chat_id' => $chatId, 'text' => 'Test']); $response = file_get_contents($testUrl); echo $response;
Проверьте токен бота:
$testTokenUrl = "https://api.telegram.org/bot{$botToken}/getMe"; $testResponse = file_get_contents($testTokenUrl); echo "Проверка токена: " . $testResponse;
Проверьте права бота в канале:
Бот должен быть администратором канала
Должны быть включены права "Post Messages"
Проверьте chat_id:
echo "Проверяемый chat_id: " . $chatId;
Если проблема сохраняется, попробуйте максимально простой запрос:
$simpleUrl = "https://api.telegram.org/bot{$botToken}/sendMessage?chat_id={$chatId}&text=Test"; $simpleResponse = file_get_contents($simpleUrl); echo $simpleResponse;
Это поможет локализовать проблему - если простой запрос работает, значит проблема в формировании POST-запроса в вашем коде.
Вот подробное объяснение принципа работы вебхука в Telegram:
Установка вебхука (однократно):
Файл set_webhook.php нужно запустить один раз
Он сообщает Telegram: "Все сообщения для моего бота отправляй на этот URL"
После установки Telegram будет отправлять все события боту на указанный URL
Что происходит дальше:
set_webhook.php)$botToken = 'ВАШ_ТОКЕН'; $webhookUrl = 'https://ваш-сайт.ru/bot.php'; $apiUrl = "https://api.telegram.org/bot{$botToken}/setWebhook?url={$webhookUrl}"; // Отправка запроса $response = file_get_contents($apiUrl);
После выполнения этого кода Telegram будет:
Отправлять все события (сообщения, команды) на https://ваш-сайт.ru/bot.php
Больше запускать set_webhook.php не нужно (только если не меняется URL)
bot.php)// Получаем входящее обновление $update = json_decode(file_get_contents('php://input'), true); // Обрабатываем сообщение if(isset($update['message'])) { $chatId = $update['message']['chat']['id']; $text = $update['message']['text']; // Формируем ответ $response = "Вы написали: $text"; // Отправляем ответ file_get_contents("https://api.telegram.org/bot{$botToken}/sendMessage?" . http_build_query(['chat_id' => $chatId, 'text' => $response])); }
Пользователь пишет боту: /start
Telegram отправляет POST-запрос на ваш bot.php с данными:
{ "update_id": 123, "message": { "message_id": 456, "chat": {"id": 123456789, "type": "private"}, "text": "/start", "from": {"id": 987654321} } }
Ваш скрипт обрабатывает данные и формирует ответ
Скрипт отправляет ответ через API Telegram
Типы обновлений:
Личные сообщения боту
Команды в группах (если бот добавлен)
Callback-кнопки
Редактирование сообщений
Проверка подлинности:
// Проверка секретного токена if($_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] !== 'ВАШ_СЕКРЕТ') { http_response_code(403); exit; }
Ограничения:
Telegram ожидает ответ за 1 секунду
Если обработка дольше - нужно сразу ответить 200 OK и обрабатывать асинхронно
$disableUrl = "https://api.telegram.org/bot{$botToken}/deleteWebhook"; file_get_contents($disableUrl);
После этого Telegram перестанет отправлять обновления на ваш сервер.
Всегда проверяйте update_id для избежания повторной обработки
Используйте try-catch для обработки ошибок
Логируйте входящие запросы для отладки
Для длительных операций используйте webhook + polling
Пример улучшенного обработчика:
// Принимаем входящее обновление http_response_code(200); // Сразу отвечаем Telegram // Логируем запрос file_put_contents('webhook.log', file_get_contents('php://input'), FILE_APPEND); // Обрабатываем в фоне ignore_user_abort(true); fastcgi_finish_request(); // Для PHP-FPM // Основная логика обработки...
Если при установке вебхука вы получаете NULL в результате, это указывает на проблему с выполнением запроса. Давайте разберёмся, как правильно диагностировать и решить эту проблему.
NULL результата:1. Проблемы с доступом к API Telegram:
// Проверьте доступность API Telegram $apiTest = file_get_contents("https://api.telegram.org"); if ($apiTest === false) { die("API Telegram недоступен. Проверьте интернет-соединение"); }
2. Неправильный токен бота:
// Проверьте токен командой getMe $tokenCheck = file_get_contents("https://api.telegram.org/bot{$botToken}/getMe"); if ($tokenCheck === false) { die("Неверный токен бота или проблемы с подключением"); }
3. Проблемы с SSL-сертификатом (частая причина):
// Альтернативный вариант с cURL $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/setWebhook", CURLOPT_POST => true, CURLOPT_POSTFIELDS => ['url' => $webhookUrl], CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, // Отключить проверку для теста CURLOPT_SSL_VERIFYHOST => 0 ]); $response = curl_exec($ch); curl_close($ch);
4. Недоступность вашего вебхук-URL:
// Проверьте доступность вашего URL $webhookTest = @file_get_contents($webhookUrl); if ($webhookTest === false) { die("Ваш вебхук URL недоступен извне. Проверьте:\n" . "- Доступность URL из интернета\n" . "- Настройки firewall\n" . "- Правила .htaccess (если используете)"); }
<?php
$botToken = 'ВАШ_ТОКЕН';
$webhookUrl = 'https://ваш-сайт.ru/bot.php';
$secretToken = 'ВАШ_СЕКРЕТНЫЙ_ТОКЕН'; // Для дополнительной безопасности
// Создаем cURL-запрос
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/setWebhook",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'url' => $webhookUrl,
'secret_token' => $secretToken,
'drop_pending_updates' => true
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10
]);
// Для локального тестирования можно отключить SSL проверку
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
// Анализ ответа
if ($response === false) {
die("cURL ошибка: " . $error);
}
$data = json_decode($response, true);
echo "<pre>";
if ($httpCode == 200 && $data['ok'] ?? false) {
print_r($data);
echo "Вебхук успешно установлен!\n";
echo "URL: " . $data['result']['url'] . "\n";
echo "Ожидает обновлений...";
} else {
print_r($data ?? $response);
echo "HTTP код: " . $httpCode . "\n";
echo "Ошибка при установке вебхука";
}
echo "</pre>";Проверьте текущие настройки вебхука:
$info = file_get_contents("https://api.telegram.org/bot{$botToken}/getWebhookInfo"); echo "<pre>Текущие настройки вебхука:\n" . print_r(json_decode($info, true), true) . "</pre>";
Проверьте права на файлы:
if (!is_writable(__FILE__)) { echo "Файл не доступен для записи. Проверьте права chmod"; }
Логирование ошибок:
ini_set('display_errors', 1); error_reporting(E_ALL);
Если после всех проверок проблема сохраняется, попробуйте:
Временно отключить firewall
Проверить доступность API через прокси
Использовать другой метод отправки (например, cURL вместо file_get_contents)
Важно: После успешной установки вебхука все сообщения боту будут приходить на указанный URL, и их нужно обрабатывать в файле bot.php.
Отлично! Ваш вебхук успешно установлен. Разберём, что означает этот результат и что делать дальше:
Array ( [ok] => true // Операция успешна [result] => true // Вебхук установлен [description] => "Webhook was set" // Подтверждение )
Проверьте текущие настройки вебхука:
$webhookInfo = file_get_contents("https://api.telegram.org/bot{$botToken}/getWebhookInfo"); echo "<pre>Текущие настройки вебхука:\n" . print_r(json_decode($webhookInfo, true), true) . "</pre>";
Тестовая отправка сообщения боту:
Напишите любое сообщение вашему боту в Telegram
Проверьте, приходит ли запрос на ваш сервер
Проверка обработки обновлений (добавьте в bot.php):
// В начало файла bot.php file_put_contents('webhook.log', date('Y-m-d H:i:s') . " " . file_get_contents('php://input') . "\n\n", FILE_APPEND);
Если обновления не приходят:
Проверьте URL вебхука:
$info = json_decode(file_get_contents( "https://api.telegram.org/bot{$botToken}/getWebhookInfo" ), true); echo "Текущий URL вебхука: " . ($info['result']['url'] ?? 'не установлен');
Проверьте доступность вашего сервера:
curl -v https://ваш-сайт.ru/bot.php
Проверьте права доступа:
Файл bot.php должен быть доступен для выполнения
Папка должна иметь права на запись (для логов)
Добавьте в bot.php:
// Принимаем входящее обновление $update = json_decode(file_get_contents('php://input'), true); // Логируем входящий запрос file_put_contents('webhook.log', print_r($update, true), FILE_APPEND); // Быстрый ответ Telegram (обязательно) http_response_code(200); // Основная обработка if (isset($update['message'])) { $chatId = $update['message']['chat']['id']; $text = $update['message']['text']; $response = "Вы написали: " . htmlspecialchars($text); file_get_contents("https://api.telegram.org/bot{$botToken}/sendMessage?" . http_build_query([ 'chat_id' => $chatId, 'text' => $response ])); }
Telegram ожидает ответ в течение 1 секунды
Для длительных операций используйте:
// Немедленный ответ http_response_code(200); // Продолжаем обработку в фоне ignore_user_abort(true); fastcgi_finish_request(); // Если используете PHP-FPM
Для отладки проверяйте:
Файл webhook.log
Ошибки PHP в логах сервера
Ответы API Telegram
Если всё настроено правильно, ваш бот теперь будет получать и обрабатывать все сообщения через вебхук!
Вот полностью переработанный код бота с использованием cURL вместо file_get_contents() и с поддержкой $secretToken:
bot.php)<?php
// Конфигурация
$botToken = 'ВАШ_ТОКЕН_БОТА';
$secretToken = 'ВАШ_СЕКРЕТНЫЙ_ТОКЕН';
// Проверка секретного токена
if ($_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] !== $secretToken) {
http_response_code(403);
exit('Unauthorized');
}
// Получаем входящее обновление
$input = file_get_contents('php://input');
$update = json_decode($input, true);
// Быстрый ответ Telegram (чтобы избежать таймаута)
http_response_code(200);
// Логируем входящий запрос
file_put_contents('webhook.log', $input . "\n\n", FILE_APPEND);
// Основная обработка сообщения
if (isset($update['message'])) {
$chatId = $update['message']['chat']['id'];
$text = $update['message']['text'];
// Формируем ответ
$responseText = "Вы написали: " . htmlspecialchars($text);
// Отправляем ответ через cURL
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/sendMessage",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'chat_id' => $chatId,
'text' => $responseText
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded'
]
]);
$response = curl_exec($ch);
curl_close($ch);
// Логируем ответ Telegram API
file_put_contents('bot_response.log', $response . "\n\n", FILE_APPEND);
}
?>set_webhook.php)<?php
$botToken = 'ВАШ_ТОКЕН_БОТА';
$webhookUrl = 'https://ваш-сайт.ру/bot.php';
$secretToken = 'ВАШ_СЕКРЕТНЫЙ_ТОКЕН';
// Настройка cURL
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/setWebhook",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'url' => $webhookUrl,
'secret_token' => $secretToken,
'drop_pending_updates' => true
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: multipart/form-data'
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
// Обработка ответа
if ($response === false) {
die("Ошибка cURL: " . $error);
}
$data = json_decode($response, true);
echo "<pre>";
if ($httpCode == 200 && ($data['ok'] ?? false)) {
print_r($data);
echo "Вебхук успешно установлен!\n";
echo "URL: " . ($data['result']['url'] ?? $webhookUrl) . "\n";
} else {
print_r($data ?? $response);
echo "HTTP код: " . $httpCode . "\n";
echo "Ошибка при установке вебхука";
}
echo "</pre>";
?>get_webhook_info.php)<?php
$botToken = 'ВАШ_ТОКЕН_БОТА';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/getWebhookInfo",
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "<pre>";
print_r($data);
echo "</pre>";
?>delete_webhook.php)<?php
$botToken = 'ВАШ_ТОКЕН_БОТА';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/deleteWebhook",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => ['drop_pending_updates' => true],
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "<pre>";
if ($data['ok'] ?? false) {
echo "Вебхук успешно удален!\n";
}
print_r($data);
echo "</pre>";
?>Полная замена file_get_contents() на cURL
Поддержка secret_token для безопасности
Правильные HTTP-заголовки
Логирование всех запросов и ответов
Обработка ошибок cURL
Быстрый ответ сервера (http_response_code(200))
Для работы с каналом используйте тот же подход, заменив chat_id на ID вашего канала (например, -1001234567890).
Все скрипты теперь используют единый безопасный подход с cURL и проверкой секретного токена.
В Telegram каналах обычные участники не могут писать сообщения (они действительно "muted"), но вы можете реализовать приветствие через бота, когда пользователь присоединяется к каналу. Вот как это сделать:
bot.php)<?php
$botToken = 'ВАШ_ТОКЕН_БОТА';
$secretToken = 'ВАШ_СЕКРЕТНЫЙ_ТОКЕН';
// Проверка секретного токена
if ($_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] !== $secretToken) {
http_response_code(403);
exit('Unauthorized');
}
// Получаем входящее обновление
$input = file_get_contents('php://input');
$update = json_decode($input, true);
http_response_code(200); // Быстрый ответ
// Логируем запрос
file_put_contents('webhook.log', $input, FILE_APPEND);
// Обработка новых участников канала
if (isset($update['channel_post']['new_chat_members'])) {
foreach ($update['channel_post']['new_chat_members'] as $newMember) {
sendWelcomeMessage($botToken, $update['channel_post']['chat']['id'], $newMember['id']);
}
}
// Обработка команд /start и /help из ЛС с ботом
if (isset($update['message'])) {
$chatId = $update['message']['chat']['id'];
$text = $update['message']['text'] ?? '';
if (strtolower($text) === '/start' || strtolower($text) === '/help') {
sendHelpMessage($botToken, $chatId);
}
}
// Функция отправки приветствия
function sendWelcomeMessage($botToken, $channelId, $userId) {
$message = "👋 Добро пожаловать в наш канал!\n\n";
$message .= "Хоть вы и не можете писать здесь, вы можете:\n";
$message .= "1. Написать мне в ЛС команду /start\n";
$message .= "2. Использовать /help для списка команд\n\n";
$message .= "Я отвечу вам в личных сообщениях!";
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/sendMessage",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'chat_id' => $userId, // Отправляем ЛС пользователю
'text' => $message,
'parse_mode' => 'HTML'
]),
CURLOPT_RETURNTRANSFER => true
]);
curl_exec($ch);
curl_close($ch);
}
// Функция отправки помощи
function sendHelpMessage($botToken, $chatId) {
$message = "📌 Доступные команды:\n\n";
$message .= "/start - Начало работы\n";
$message .= "/help - Эта справка\n";
$message .= "/info - Информация о канале\n";
$message .= "/links - Полезные ссылки";
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/sendMessage",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'chat_id' => $chatId,
'text' => $message,
'parse_mode' => 'HTML'
]),
CURLOPT_RETURNTRANSFER => true
]);
curl_exec($ch);
curl_close($ch);
}
?>Дайте боту права администратора в канале:
Зайдите в настройки канала → Администраторы
Добавьте бота как администратора
Включите разрешение "View messages" и "Post messages"
Включите уведомления о новых участниках:
В настройках канала → Разрешения
Включите опцию "Show notifications about new members"
Обновите вебхук (чтобы бот получал события канала):
// В set_webhook.php добавьте: 'allowed_updates' => json_encode(["message", "channel_post"])
Пользователь присоединяется к каналу
Бот получает событие new_chat_member
Бот отправляет приветственное сообщение в личные сообщения пользователю
Пользователь может взаимодействовать с ботом через ЛС командами:
/start - приветствие
/help - справка
Другие ваши команды
Кнопки в сообщении (добавьте в sendWelcomeMessage):
'reply_markup' => json_encode([ 'inline_keyboard' => [ [['text' => '🚀 Начать', 'callback_data' => 'start']], [['text' => '❓ Помощь', 'callback_data' => 'help']] ] ])
Приветственное сообщение в канале (если хотите публичное):
// В sendWelcomeMessage добавьте: $channelMessage = "Поприветствуем нового участника @{$newMember['username']}!"; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/sendMessage", CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'chat_id' => $channelId, 'text' => $channelMessage ]), CURLOPT_RETURNTRANSFER => true ]); curl_exec($ch); curl_close($ch);
Теперь ваши пользователи будут получать персональные приветствия, даже если они не могут писать в канале!
Чтобы протестировать работу приветствия и команд бота, следуйте этому подробному руководству:
Перед тестированием убедитесь, что:
Бот добавлен как администратор канала
Вебхук корректно установлен (проверьте через getWebhookInfo)
В bot.php включено логирование (у вас уже есть webhook.log)
Выйдите из канала (если уже состоите)
Присоединитесь к каналу через ссылку-приглашение
Проверьте:
Логи в webhook.log (должно быть событие new_chat_member)
Личные сообщения от бота (должно прийти приветствие)
// test_welcome.php
<?php
$testUpdate = [
'update_id' => 999999999,
'channel_post' => [
'chat' => [
'id' => -1001234567890, // ID вашего канала
'title' => 'Test Channel',
'type' => 'channel'
],
'new_chat_members' => [
[
'id' => 123456789, // ID тестового пользователя
'first_name' => 'Test',
'username' => 'test_user'
]
],
'date' => time()
]
];
file_put_contents('test_update.json', json_encode($testUpdate));
// Имитируем вебхук запрос
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://ваш-сайт.ru/bot.php',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => file_get_contents('test_update.json'),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Telegram-Bot-Api-Secret-Token: ВАШ_СЕКРЕТНЫЙ_ТОКЕН'
],
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
echo "Результат теста:\n" . $response;
curl_close($ch);
?>Начните чат с ботом в Telegram
Отправьте команды:
/start - должно прийти приветствие
/help - должен отправиться список команд
// test_commands.php
<?php
$commands = ['/start', '/help'];
foreach ($commands as $cmd) {
$testUpdate = [
'update_id' => 999999999,
'message' => [
'chat' => [
'id' => 123456789, // Ваш chat_id
'type' => 'private'
],
'text' => $cmd,
'from' => [
'id' => 123456789,
'first_name' => 'Test'
]
]
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://ваш-сайт.ru/bot.php',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($testUpdate),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Telegram-Bot-Api-Secret-Token: ВАШ_СЕКРЕТНЫЙ_ТОКЕН'
],
CURLOPT_RETURNTRANSFER => true
]);
echo "Тестируем команду {$cmd}:\n";
echo curl_exec($ch) . "\n\n";
curl_close($ch);
}
?>После тестирования проверьте:
webhook.log - должны быть записаны все входящие запросы
bot_response.log - должны быть ответы бота
Для теста в реальном канале создайте тестового пользователя
Проверьте все сценарии:
Вступление в канал
Отправка команд в ЛС
Неправильные команды
Используйте getWebhookInfo для проверки последних ошибок:
$info = file_get_contents("https://api.telegram.org/bot{$botToken}/getWebhookInfo"); echo "<pre>" . print_r(json_decode($info, true), true) . "</pre>";
Тестируем команду /start:
{"ok":true,"result":{"message_id":123,"from":{"id":123456789,"is_bot":true,"first_name":"TestBot","username":"TestBot"},"chat":{"id":123456789,"first_name":"Test","type":"private"},"date":1688659200,"text":"Добро пожаловать!"}}
Тестируем команду /help:
{"ok":true,"result":{"message_id":124,"from":{"id":123456789,"is_bot":true,"first_name":"TestBot","username":"TestBot"},"chat":{"id":123456789,"first_name":"Test","type":"private"},"date":1688659201,"text":"Доступные команды:\n/start - начало\n/help - помощь"}}Если все тесты проходят успешно, ваш бот готов к работе!
Проблема в том, что Telegram не отправляет обновления о новых участниках канала, несмотря на правильно настроенный вебхук. Давайте решим это поэтапно:
Telegram не отправляет события new_chat_members для каналов, только для групп и супергрупп. Это текущее ограничение API.
Вот рабочая альтернатива для приветствия пользователей:
bot.php:<?php
$botToken = 'ВАШ_ТОКЕН';
$secretToken = 'ВАШ_СЕКРЕТ';
$channelId = -1001234567890; // ID вашего канала
// Проверка секретного токена
if ($_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] !== $secretToken) {
http_response_code(403);
exit;
}
// Логирование
file_put_contents('webhook.log', file_get_contents('php://input')."\n\n", FILE_APPEND);
// Обработка команд
$update = json_decode(file_get_contents('php://input'), true);
http_response_code(200);
if (isset($update['message']['text'])) {
$text = strtolower($update['message']['text']);
$chatId = $update['message']['chat']['id'];
// Если пользователь написал /start
if ($text === '/start') {
$user = $update['message']['from'];
$message = "👋 Привет, {$user['first_name']}!\n\n";
$message .= "Добро пожаловать в наш канал!\n";
$message .= "Используй /help для списка команд.";
sendMessage($botToken, $chatId, $message);
}
// Обработка /help
if ($text === '/help') {
sendMessage($botToken, $chatId, "Список команд:\n/start - приветствие\n/help - помощь");
}
}
function sendMessage($token, $chatId, $text) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.telegram.org/bot{$token}/sendMessage",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'chat_id' => $chatId,
'text' => $text,
'parse_mode' => 'HTML'
]),
CURLOPT_RETURNTRANSFER => true
]);
curl_exec($ch);
curl_close($ch);
}
?>Разместите в описании канала и закрепленном сообщении:
Напишите /start боту @YourBotName для приветствия и помощи
Или создайте кнопку "Start" с ссылкой:
t.me/YourBotName?start=welcome
Зайдите в канал как новый пользователь
Начните чат с ботом (не в канале, а в ЛС)
Отправьте /start
Проверьте webhook.log - должно появиться сообщение
Если нужно именно автоматическое приветствие, можно:
Создать группу (не канал)
Включить все нужные уведомления
Преобразовать в супергруппу
Тогда события new_chat_members будут работать
Для каналов приветствие возможно только через ручной запуск (/start)
Логи будут писаться только при реальных запросах к боту
Убедитесь, что в setWebhook указаны правильные allowed_updates
Если проблема сохраняется, проверьте:
Права бота в канале
Настройки конфиденциальности бота
Ошибки в логах сервера (не только webhook.log)
Вот подробное решение по вашим вопросам:
Добавьте обработку callback-запросов в bot.php:
// В начало файла после проверки секретного токена $update = json_decode(file_get_contents('php://input'), true); file_put_contents('webhook.log', print_r($update, true), FILE_APPEND); // Обработка callback-запросов от кнопок if (isset($update['callback_query'])) { $callback = $update['callback_query']; $chatId = $callback['message']['chat']['id']; $data = $callback['data']; if ($data === 'start') { $responseText = "🚀 Добро пожаловать! Вот что я умею:\n\n/help - список команд\n/info - о канале"; } else { $responseText = "Неизвестная команда"; } // Ответ на нажатие кнопки sendMessage($botToken, $chatId, $responseText); // Подтверждение получения callback answerCallbackQuery($botToken, $callback['id']); exit; } // Функция для ответа на callback function answerCallbackQuery($token, $callbackId) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$token}/answerCallbackQuery", CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'callback_query_id' => $callbackId ]), CURLOPT_RETURNTRANSFER => true ]); curl_exec($ch); curl_close($ch); } // Модифицированная функция sendMessage с кнопками function sendMessageWithButtons($token, $chatId, $text) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$token}/sendMessage", CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'chat_id' => $chatId, 'text' => $text, 'parse_mode' => 'HTML', 'reply_markup' => json_encode([ 'inline_keyboard' => [ [ ['text' => '🚀 Начать', 'callback_data' => 'start'], ['text' => '❓ Помощь', 'callback_data' => 'help'] ] ] ]) ]), CURLOPT_RETURNTRANSFER => true ]); curl_exec($ch); curl_close($ch); }
Полностью преобразовать канал в группу нельзя, но есть обходные пути:
Создайте новую супергруппу
В настройках канала:
Скопируйте всех участников
Опубликуйте финальное сообщение с ссылкой на новую группу
Преимущества группы:
Полноценные уведомления о новых участниках
Возможность общения участников
Создайте группу-обсуждение для канала:
Настройки канала → Обсуждение → Добавить группу
Преимущества:
Сохраняется канал для публикаций
Группа для обсуждений
Бот сможет приветствовать новых участников группы
Если нужно оставить канал:
Используйте закрепленное сообщение с инструкцией:
Нажмите кнопку ниже, чтобы получить приветствие: [Кнопка с ссылкой t.me/YourBot?start=welcome]
Добавьте бота в описание канала
Для тестирования:
Отправьте команду, которая вызывает сообщение с кнопками
Нажмите кнопку - должно появиться всплывающее уведомление
Проверьте webhook.log - должен появиться callback-запрос
Пример ответа бота при нажатии кнопки:
// В обработчике callback_query: if ($data === 'help') { $responseText = "📌 Помощь:\n\n"; $responseText .= "/start - начать работу\n"; $responseText .= "/links - полезные ссылки\n"; $responseText .= "/feedback - обратная связь"; // Можно также редактировать исходное сообщение editMessageText($botToken, $chatId, $callback['message']['message_id'], $responseText); } function editMessageText($token, $chatId, $messageId, $text) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$token}/editMessageText", CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'chat_id' => $chatId, 'message_id' => $messageId, 'text' => $text, 'parse_mode' => 'HTML' ]), CURLOPT_RETURNTRANSFER => true ]); curl_exec($ch); curl_close($ch); }
Для inline-кнопок обязательно:
Обрабатывать callback_query
Отправлять answerCallbackQuery
В setWebhook нужно разрешить callback_query:
'allowed_updates' => json_encode(["message", "callback_query"])
Кнопки работают только в:
Личных чатах с ботом
Группах/супергруппах
Закрепленных сообщениях канала (но нажатие будет открывать чат с ботом)
Вот правильный способ одновременно обрабатывать channel_post, message и callback_query в одном вебхуке:
В файле set_webhook.php укажите все необходимые типы обновлений в одном массиве:
$allowedUpdates = [ "message", // Личные сообщения "channel_post", // Сообщения в канале "callback_query" // Нажатия inline-кнопок ]; // Установка вебхука $setWebhookUrl = "https://api.telegram.org/bot{$botToken}/setWebhook?" . http_build_query([ 'url' => $webhookUrl, 'secret_token' => $secretToken, 'allowed_updates' => json_encode($allowedUpdates) ]);
$update = json_decode(file_get_contents('php://input'), true); // Логируем все входящие обновления file_put_contents('webhook.log', print_r($update, true), FILE_APPEND); // Определяем тип обновления if (isset($update['message'])) { // Обработка личных сообщений handleMessage($update['message']); } elseif (isset($update['channel_post'])) { // Обработка сообщений в канале handleChannelPost($update['channel_post']); } elseif (isset($update['callback_query'])) { // Обработка нажатий кнопок handleCallbackQuery($update['callback_query']); } // Функции обработчики function handleMessage($message) { global $botToken; if (isset($message['text'])) { $text = strtolower($message['text']); if ($text === '/start') { // Отправка сообщения с кнопками $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🚀 Старт', 'callback_data' => 'start'], ['text' => '❓ Помощь', 'callback_data' => 'help'] ] ] ]; sendMessage($botToken, $message['chat']['id'], "Выберите действие:", json_encode($keyboard)); } } } function handleChannelPost($post) { global $botToken; // Обработка новых сообщений в канале if (isset($post['new_chat_members'])) { foreach ($post['new_chat_members'] as $member) { // Логика приветствия (если поддерживается каналом) } } } function handleCallbackQuery($callback) { global $botToken; $data = $callback['data']; $chatId = $callback['message']['chat']['id']; $messageId = $callback['message']['message_id']; switch ($data) { case 'start': editMessage($botToken, $chatId, $messageId, "Вы выбрали Старт!"); break; case 'help': editMessage($botToken, $chatId, $messageId, "Помощь:\n/start - начало\n/help - помощь"); break; } // Обязательно подтверждаем callback answerCallbackQuery($botToken, $callback['id']); }
Для каналов ограничения:
События new_chat_members не работают в каналах
Inline-кнопки в канале будут открывать чат с ботом при нажатии
Альтернатива для приветствий:
// В handleChannelPost можно добавить: if (isset($post['text']) && strpos($post['text'], '/start') === 0) { sendMessage($botToken, $post['chat']['id'], "Добро пожаловать в канал!"); }
Оптимальная структура обработки:
После настройки проверьте:
Отправьте боту /start - должны появиться кнопки
Нажмите кнопку - должно прийти обновление
Проверьте webhook.log - должны быть все типы событий
Если channel_post не приходит, убедитесь что:
Бот является администратором канала
В канале есть активность (новые сообщения)
Не установлены фильтры в allowed_updates
Вот полный код с недостающими функциями editMessage и sendMessage, интегрированными в обработчики:
// bot.php // Основные функции для работы с API Telegram function sendMessage($botToken, $chatId, $text, $replyMarkup = null) { $postData = [ 'chat_id' => $chatId, 'text' => $text, 'parse_mode' => 'HTML' ]; if ($replyMarkup) { $postData['reply_markup'] = $replyMarkup; } $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/sendMessage", CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Content-Type: multipart/form-data'] ]); $response = curl_exec($ch); curl_close($ch); return $response; } function editMessage($botToken, $chatId, $messageId, $newText) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/editMessageText", CURLOPT_POST => true, CURLOPT_POSTFIELDS => [ 'chat_id' => $chatId, 'message_id' => $messageId, 'text' => $newText, 'parse_mode' => 'HTML' ], CURLOPT_RETURNTRANSFER => true ]); $response = curl_exec($ch); curl_close($ch); return $response; } function answerCallbackQuery($botToken, $callbackId) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.telegram.org/bot{$botToken}/answerCallbackQuery", CURLOPT_POST => true, CURLOPT_POSTFIELDS => [ 'callback_query_id' => $callbackId ], CURLOPT_RETURNTRANSFER => true ]); $response = curl_exec($ch); curl_close($ch); return $response; } // Обработчики сообщений function handleMessage($message) { global $botToken; if (isset($message['text'])) { $text = strtolower($message['text']); $chatId = $message['chat']['id']; if ($text === '/start') { $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🚀 Старт', 'callback_data' => 'start'], ['text' => '❓ Помощь', 'callback_data' => 'help'] ] ] ]; sendMessage($botToken, $chatId, "Выберите действие:", json_encode($keyboard)); } } } function handleCallbackQuery($callback) { global $botToken; $data = $callback['data']; $chatId = $callback['message']['chat']['id']; $messageId = $callback['message']['message_id']; switch ($data) { case 'start': editMessage($botToken, $chatId, $messageId, "Вы выбрали Старт!\n\nТеперь вы можете:\n• Получать уведомления\n• Использовать команды\n• Получать помощь"); break; case 'help': editMessage($botToken, $chatId, $messageId, "📌 Помощь:\n\n" . "/start - Начало работы\n" . "/help - Эта справка\n" . "/info - Информация\n\n" . "Нажмите кнопки ниже для действий"); break; } answerCallbackQuery($botToken, $callback['id']); } // Основной обработчик вебхука $update = json_decode(file_get_contents('php://input'), true); file_put_contents('webhook.log', print_r($update, true), FILE_APPEND); if (isset($update['message'])) { handleMessage($update['message']); } elseif (isset($update['callback_query'])) { handleCallbackQuery($update['callback_query']); } http_response_code(200);
Полноценная функция sendMessage:
Поддержка обычных сообщений и сообщений с клавиатурой
Автоматическое преобразование клавиатуры в JSON
Улучшенная функция editMessage:
Возможность редактирования существующих сообщений
Поддержка разметки HTML
Оптимизированная функция answerCallbackQuery:
Обязательное подтверждение обработки callback
Предотвращение "висячих" состояний кнопок
Глобальная доступность $botToken:
Все функции имеют доступ к токену бота
При отправке /start бот пришлет сообщение с кнопками:
sendMessage($botToken, $chatId, "Текст сообщения", $keyboard);
При нажатии кнопки сообщение будет обновлено:
editMessage($botToken, $chatId, $messageId, "Новый текст");
Все callback-запросы подтверждаются:
answerCallbackQuery($botToken, $callbackId);
Этот код обеспечит полную функциональность для работы с:
Личными сообщениями
Inline-кнопками
Редактированием сообщений
Обработкой callback-запросов
Вот полная реализация команды /feedback с обработкой обратной связи, включая сохранение в базу данных и ответ пользователю:
/feedback в handleMessage()function handleMessage($message) { global $botToken; if (isset($message['text'])) { $text = strtolower($message['text']); $chatId = $message['chat']['id']; $userId = $message['from']['id']; // Обработка команды /feedback if (strpos($text, '/feedback') === 0) { // Проверяем, есть ли текст после команды $feedbackText = trim(str_replace('/feedback', '', $text)); if (!empty($feedbackText)) { // Если текст есть сразу - сохраняем processFeedback($userId, $chatId, $feedbackText); } else { // Если нет - просим прислать текст sendMessage($botToken, $chatId, "📝 Пожалуйста, напишите ваш отзыв после команды /feedback\n\n" . "Пример:\n<code>/feedback Мне нравится этот бот, но нужно добавить...</code>", json_encode(['force_reply' => true])); // Сохраняем состояние ожидания feedback setUserState($userId, 'awaiting_feedback'); } } // Обработка состояния ожидания feedback elseif (getUserState($userId) === 'awaiting_feedback') { processFeedback($userId, $chatId, $text); clearUserState($userId); } } }
// Обработка и сохранение feedback function processFeedback($userId, $chatId, $text) { global $botToken; // Сохраняем в базу данных $db = new PDO('mysql:host=localhost;dbname=bot_db', 'username', 'password'); $stmt = $db->prepare("INSERT INTO feedback (user_id, message, date) VALUES (?, ?, NOW())"); $stmt->execute([$userId, $text]); // Отправляем подтверждение пользователю sendMessage($botToken, $chatId, "✅ Спасибо за ваш отзыв! Мы его рассмотрим."); // Отправляем админу $adminId = 123456789; // Ваш chat_id sendMessage($botToken, $adminId, "📩 Новый отзыв от пользователя $userId:\n\n" . "<code>$text</code>"); } // Функции для управления состоянием пользователя (можно заменить Redis или другой БД) function setUserState($userId, $state) { file_put_contents("user_states/$userId.txt", $state); } function getUserState($userId) { $file = "user_states/$userId.txt"; return file_exists($file) ? file_get_contents($file) : null; } function clearUserState($userId) { $file = "user_states/$userId.txt"; if (file_exists($file)) { unlink($file); } }
CREATE TABLE feedback ( id INT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, message TEXT NOT NULL, date DATETIME NOT NULL, status ENUM('new', 'processed') DEFAULT 'new' );
// В команде /start добавляем кнопку обратной связи $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🚀 Старт', 'callback_data' => 'start'], ['text' => '❓ Помощь', 'callback_data' => 'help'] ], [ ['text' => '📝 Обратная связь', 'callback_data' => 'feedback'] ] ] ];
// В switch($data) добавляем: case 'feedback': sendMessage($botToken, $chatId, "📣 Обратная связь\n\n" . "Пожалуйста, напишите ваши предложения или замечания одной сообщением.\n\n" . "Можно использовать команду:\n" . "<code>/feedback ваш текст</code>", json_encode(['force_reply' => true])); setUserState($userId, 'awaiting_feedback'); break;
Пользователь нажимает "📝 Обратная связь" или пишет /feedback
Бот просит прислать текст отзыва
Пользователь отправляет сообщение с текстом
Бот:
Сохраняет отзыв в базу данных
Подтверждает получение
Пересылает админу
Валидация feedback:
if (strlen($text) < 10) { sendMessage($botToken, $chatId, "❌ Слишком короткий отзыв. Минимум 10 символов."); return; } if (strlen($text) > 1000) { sendMessage($botToken, $chatId, "❌ Слишком длинный отзыв. Максимум 1000 символов."); return; }
Ответ администратора пользователю:
// Админ может ответить командой /reply USER_ID ТЕКСТ if (strpos($text, '/reply') === 0 && $chatId == $adminId) { $parts = explode(' ', $text, 3); if (count($parts) >= 3) { $targetUserId = $parts[1]; $replyText = $parts[2]; sendMessage($botToken, $targetUserId, "📨 Ответ администратора:\n\n" . $replyText); } }
Просмотр всех отзывов:
// Команда /view_feedback для админа if ($text === '/view_feedback' && $chatId == $adminId) { $db = new PDO('mysql:host=localhost;dbname=bot_db', 'username', 'password'); $feedbacks = $db->query("SELECT * FROM feedback ORDER BY date DESC LIMIT 10"); $messages = []; foreach ($feedbacks as $fb) { $messages[] = "#{$fb['id']} [User: {$fb['user_id']}]\n{$fb['message']}\n"; } sendMessage($botToken, $chatId, "Последние 10 отзывов:\n\n" . implode("\n", $messages)); }
Вот как обработать параметр start=welcome в команде /start:
bot.php:function handleMessage($message) { global $botToken; if (isset($message['text'])) { $text = $message['text']; $chatId = $message['chat']['id']; // Обработка команды /start с параметрами if (strpos($text, '/start') === 0) { $parts = explode(' ', $text); $param = isset($parts[1]) ? $parts[1] : ''; // Обработка start=welcome if ($param === 'welcome') { sendWelcomeMessage($chatId, true); // true - расширенное приветствие } else { sendWelcomeMessage($chatId, false); // Обычное приветствие } } } }
function sendWelcomeMessage($chatId, $isExtendedWelcome) { global $botToken; $message = "👋 Добро пожаловать!"; if ($isExtendedWelcome) { $message .= "\n\nВы перешли по специальной ссылке и получаете расширенное приветствие!"; $message .= "\n\nЗдесь вы можете:"; $message .= "\n• Получить помощь - /help"; $message .= "\n• Оставить отзыв - /feedback"; $message .= "\n• Узнать о возможностях - /features"; } else { $message .= "\nИспользуйте /help для списка команд"; } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🚀 Начать', 'callback_data' => 'start'], ['text' => '❓ Помощь', 'callback_data' => 'help'] ] ] ]; sendMessage($botToken, $chatId, $message, json_encode($keyboard)); }
Сформируйте ссылку в формате:
https://t.me/Robot2025free_bot?start=welcome
Логирование источников переходов:
// В обработчике /start $source = 'direct'; if (isset($message['entities'])) { foreach ($message['entities'] as $entity) { if ($entity['type'] === 'bot_command' && $entity['offset'] === 0) { $source = 'command'; break; } } } logUserEntry($message['from']['id'], $source, $param);
Функция логирования:
function logUserEntry($userId, $source, $param) { $db = new PDO('mysql:host=localhost;dbname=bot_db', 'username', 'password'); $stmt = $db->prepare("INSERT INTO user_entries (user_id, entry_source, start_param, entry_date) VALUES (?, ?, ?, NOW())"); $stmt->execute([$userId, $source, $param]); }
SQL для таблицы логирования:
CREATE TABLE user_entries ( id INT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, entry_source VARCHAR(20) NOT NULL, start_param VARCHAR(50), entry_date DATETIME NOT NULL );
В описании канала:
Напишите боту: /start Или перейдите по ссылке для приветствия: t.me/Robot2025free_bot?start=welcome
В сообщениях канала:
[Специальное приветствие](t.me/Robot2025free_bot?start=welcome)В inline-кнопках:
'reply_markup' => json_encode([ 'inline_keyboard' => [ [ ['text' => 'Получить приветствие', 'url' => 'https://t.me/Robot2025free_bot?start=welcome'] ] ] ])
Telegram передает параметр как часть команды:
Пользователь переходит по t.me/bot?start=welcome
Бот получает сообщение: /start welcome
Параметр может содержать:
Простые значения: welcome
Референсные коды: ref123
Промо-коды: promoSUMMER2023
Ограничения:
Максимальная длина параметра - 64 символа
Разрешены только буквы, цифры и подчеркивание
Теперь ваш бот будет различать обычный /start и переход по специальной ссылке, отправляя соответствующее приветственное сообщение.