Почему бота нельзя «запрограммировать прямо в Telegram»
Как программировать Telegram-бота через внешний PHP-скрипт
Полное руководство: архитектура, настройка, безопасность и пошаговый запуск. Без готового кода — только логика и принципы.
1 Почему бота нельзя «запрограммировать прямо в Telegram»
Когда вы создаёте бота через @BotFather, вы получаете только токен — цифровой ключ доступа к API. BotFather — это реестр имён и настроек профиля (имя, аватар, описание, кнопки команд). Логика там не хранится и не исполняется.
BotFather умеет только:
- выдать токен и разрешить сменить его;
- задать имя, аватар, описание, команды в меню;
- включить/выключить inline-режим, платежи, групповые функции;
- установить или удалить webhook-адрес.
BotFather не умеет:
- хранить состояние диалога (кто на каком вопросе остановился);
- обрабатывать входящие сообщения и отвечать на них;
- вести базу данных, считать статистику, делать рассылки;
- писать сообщения в группу по триггеру;
- работать с файлами, платежами, картинками.
2 Почему именно внешний скрипт (и почему PHP)
Есть несколько способов «оживить» бота, но у внешнего скрипта есть принципиальные преимущества.
- Полный контроль над логикой. Вы решаете, что делать с каждым сообщением: сохранять в БД, отправлять в группу, читать файл, вызывать внешние API. Никакой визуальный конструктор этого не даст.
- Постоянное хранение состояния. Бот помнит, на каком шаге опроса остановился каждый клиент. Это делается через файлы, БД или кэш — то, чего нет у Telegram.
- Работа с вашей инфраструктурой. Бот может писать в вашу БД, обращаться к CRM, отправлять email, запускать скрипты на сервере. Никакой облачный конструктор этого не позволит.
- Отсутствие ежемесячной платы сервису-конструктору. Вы платите только за хостинг, который у вас, скорее всего, уже есть.
- Отсутствие привязки к чужому вендору. Бот не «умрёт», если конструктор закроется или поднимет цену. Всё в ваших руках.
- Безопасность и приватность данных. Переписка и данные клиентов не проходят через сторонние серверы — только между вашим сервером и Telegram.
- Производительность и масштаб. Можно оптимизировать, кэшировать, балансировать нагрузку. Конструктор такой гибкости не даёт.
Почему PHP, а не Python/Node
Если у вас уже есть хостинг с PHP
Ничего не нужно разворачивать — файл bot.php просто кладётся в корень и работает.
Никаких долгоживущих процессов
Webhook-модель: Telegram сам вызывает скрипт при новом сообщении. Не нужно держать демона 24/7.
Встроенные функции для HTTP
curl, file_get_contents, работа с JSON и MIME «из коробки».
Простой деплой
Загрузили файл по FTP — бот обновился. Никаких сборок и зависимостей.
3 Две архитектуры: polling и webhook
Есть два принципиально разных способа получать сообщения от Telegram. Выбор определяет всю структуру бота.
Polling — «бот сам спрашивает»
- Скрипт должен работать непрерывно — как демон или через cron каждую секунду.
- Требует VPS или хостинг, который разрешает долгоживущие процессы.
- Проще в отладке: видно, что именно делает бот.
Webhook — «Telegram сам стучится»
- Ваш скрипт вызывается только при новом сообщении — не нужно держать процесс.
- Идеально для обычного хостинга с PHP и HTTPS.
- Требует SSL-сертификат и валидный домен.
- Быстрее и дешевле в ресурсах.
4 Что понадобится
| Компонент | Назначение |
|---|---|
| Токен от @BotFather | Идентификатор и ключ доступа к API бота. |
| Хостинг с PHP 7.4+ | Где будет исполняться скрипт. |
| Домен + SSL (HTTPS) | Обязательно для webhook — Telegram не принимает HTTP. |
| Папка для хранения состояний | Файлы на диске или БД для запоминания шагов диалога. |
| ID целевой группы (при пересылке) | Отрицательное число вида -100…. |
| Права на запись | Для логов и файлов состояний. |
5 Логика работы скрипта: пошагово
Каждый раз, когда приходит новое сообщение, ваш bot.php проходит один и тот же цикл. Поймите его — и вы сможете написать любого бота.
- Приём запроса. Скрипт читает тело POST-запроса (это JSON от Telegram) через
php://input. - Разбор данных. Из JSON извлекаются: ID чата, ID пользователя, текст, username, тип сообщения.
- Защита. Проверяется, что запрос действительно от Telegram (можно по IP или секретному заголовку).
- Загрузка состояния. Скрипт смотрит: на каком шаге диалога находится этот пользователь. Состояние хранится в отдельном файле или в БД по ID пользователя.
- Определение действия. По состоянию и тексту определяется, что делать: приветствие, следующий вопрос, обработка ответа, финал.
- Отправка ответа. Скрипт формирует сообщение и отправляет его обратно через Telegram Bot API методом
sendMessage. - Обновление состояния. Новый шаг записывается на диск/в БД.
- Побочные действия. Если нужно — отправляется копия заявки в группу, записывается лог, вызывается внешний сервис.
- Ответ Telegram. Скрипт возвращает
HTTP 200 OK— этим он говорит Telegram, что сообщение обработано.
200 OK. Любой другой код или таймаут — и он повторит запрос. Это может привести к дублированию заявок, если не защититься.6 Хранение состояния — обязательный элемент
Telegram не помнит, что вы спросили у пользователя минуту назад. Значит, это должны помнить вы. Есть три варианта:
Файлы (проще всего)
- Для каждого пользователя — отдельный файл
states/<ID>.json. - Плюсы: не нужна БД, легко отлаживать глазами.
- Минусы: при большом потоке — медленно, есть риск коллизий.
База данных (для серьёзных ботов)
- Таблица
usersс полями: ID, имя, телефон, шаг, последнее действие. - SQLite — для небольших, MySQL/PostgreSQL — для крупных проектов.
- Плюсы: надёжно, транзакции, аналитика.
- Минусы: надо уметь работать с БД.
Redis / Memcached (для скорости)
- Состояния в памяти, миллисекундный доступ.
- Плюсы: молниеносно, автоочистка по TTL.
- Минусы: требует отдельного сервиса на сервере.
7 Установка webhook: ключевой шаг
После того как bot.php загружен и доступен по HTTPS, нужно сообщить Telegram: «присылай новые сообщения сюда».
- Убедитесь, что скрипт открывается в браузере и возвращает пустой ответ или статус (не 404, не 500).
- Убедитесь, что сертификат SSL валиден (не самоподписанный) — иначе Telegram откажется.
- Сформируйте запрос к методу
setWebhookBot API, указав полный HTTPS-URL до вашего файла. - Проверьте ответ — должно быть
"ok": true. - Проверьте
getWebhookInfo— там будет видно, правильно ли установлен webhook, сколько было ошибок, когда последний раз приходил запрос.
8 Как выглядит полный жизненный цикл заявки
9 Безопасность
- Токен — это пароль. Никому не показывать, не коммитить в Git, не публиковать на скриншотах.
- Хранить токен отдельно от кода — в переменных окружения или отдельном конфиге вне корня сайта.
- Проверять источник запроса. Telegram публикует список своих IP-диапазонов — можно фильтровать по ним.
- Секретный токен в URL. При установке webhook можно передать
secret_token— Telegram будет добавлять его в заголовок, что позволит отсеять подделки. - Ограничивать частоту. Не давать одному пользователю слать сотни заявок в минуту — иначе спам.
- Валидировать всё. Телефон, email, номер заказа — проверять регулярными выражениями.
- Логировать ошибки, но не данные клиентов. В логи — только ID, код ошибки, время. Телефоны и имена — в защищённую БД.
- Права на файлы состояний. Папка
states/должна быть доступна только PHP, не браузеру.
10 Отладка и типовые проблемы
| Симптом | Причина и что делать |
|---|---|
| Бот не отвечает вообще | Webhook не установлен, URL недоступен, SSL-ошибка. Проверить через getWebhookInfo. |
| Бот молчит после нескольких сообщений | Скрипт упал с ошибкой 500. Смотреть error_log, лог PHP-FPM, лог Nginx. |
| Сообщения приходят дважды | Запущен polling-скрипт параллельно с webhook. Отключить polling. |
| В группу ничего не приходит | Бот не админ группы, либо неверный chat_id, либо бот не добавлен. |
| Кракозябры вместо украинского/русского | Файл не в UTF-8 или отсутствует charset в заголовках. |
| Ошибки «Too Many Requests» | Telegram ограничивает ~30 сообщений/сек на бота. Добавить очередь или задержки. |
| Состояние сбрасывается | Папка состояний недоступна для записи, или скрипт не сохраняет после ответа. |
| Дубли заявок | Telegram повторяет webhook, если не получил 200. Проверить, что скрипт всегда отвечает 200. |
Инструменты диагностики
getWebhookInfo— состояние webhook: URL, ошибки, время последнего запроса.getMe— проверка, что токен рабочий.- Логи Nginx и PHP-FPM — где именно падает скрипт.
- Собственный лог
bot_errors.log— точечная запись только ошибок бота.
11 Чек-лист запуска
- Получен токен от @BotFather.
- Есть хостинг с PHP 7.4+ и HTTPS.
- Создан файл
bot.phpсо всей логикой. - Создана папка
states/с правами на запись. - В настройках указан токен, ID группы, путь к состояниям.
- Файл открывается в браузере без ошибок 500.
- Установлен webhook через
setWebhook. - Проверено через
getWebhookInfo. - Бот добавлен в группу и назначен админом.
- Проверен полный цикл:
/start→ 4 ответа → заявка в группе → «спасибо» клиенту. - Настроен бэкап папки состояний и логов.
- Настроена ротация логов (иначе файл вырастет до гигабайтов).
12 Когда стоит уходить с PHP
PHP отлично подходит для типовых сценариев: опросы, заявки, уведомления, каталоги, автоворонки. Но есть случаи, когда PHP становится узким местом:
- Массовые рассылки десяткам тысяч пользователей за раз.
- Асинхронные задачи: длительные запросы, ожидание внешних API.
- Высокая нагрузка: сотни сообщений в секунду.
- Сложная логика с параллелизмом: WebSocket, real-time, стриминг.
В этих случаях переходят на Python (aiogram, python-telegram-bot) или Node.js (telegraf, grammY), которые изначально асинхронны и держат тысячи соединений.
13 Краткое резюме
Telegram — это транспорт
BotFather даёт токен, но не исполняет код. Вся логика — на вашем сервере.
Webhook — оптимален для PHP
Telegram вызывает скрипт при новом сообщении. Не нужен демон.
Состояние — обязательно
Без файлов или БД бот не сможет вести диалог.
Безопасность — прежде всего
Токен, SSL, проверка IP и секретный заголовок — минимум.
