Updates
From polling to webhook
Если бот начинал работу через getUpdates с long polling, перед переходом на webhook нужно учесть два момента: переключение режима и очистку старых update_id.
Переключение setWebhook
Telegram разрешает использовать только один режим приёма апдейтов. Любой вызов setWebhook автоматически отключает polling, отдельный метод не нужен. Обратное действие — deleteWebhook с опциональным drop_pending_updates=true, если хотите сбросить очередь необработанных update.
Минимальный переход с polling на webhook:
$secret = bin2hex(random_bytes(16));
$resp = telegramApi($token, 'setWebhook', [
'url' => 'https://example.com/telegram/webhook',
'secret_token' => $secret,
'drop_pending_updates' => true,
'allowed_updates' => ['message', 'callback_query'],
]);
if ($resp['ok'] === false) {
// Часто: "Webhook can be set only on port 80, 88, 443 or 8443"
// или "SSL certificate is invalid"
throw new RuntimeException($resp['description'] ?? 'setWebhook failed');
}drop_pending_updates=true полезен именно при миграции с polling: апдейты, которые ваш long polling-скрипт не успел обработать, не прилетят повторно на webhook.
Перенос состояния
В polling-режиме вы храните last_update_id в файле или БД и инкрементируете его на каждом getUpdates. В webhook-режиме этот механизм не нужен: каждый входящий Update уже доставлен один раз, а порядок гарантирует сам Telegram. Старый last_update_id просто перестаёт использоваться — очищать БД необязательно, достаточно перестать его читать.
Если же вы хотите погасить накопленный offset, выполните последний getUpdates с offset=-1 — это пометит все непрочитанные апдейты как подтверждённые.
telegramApi($token, 'getUpdates', [
'offset' => -1,
'timeout' => 0,
]);Чек-лист миграции
- Подготовлен публичный HTTPS с валидным сертификатом и поддержким POST до 1 МБ+.
- Endpoint отвечает 200 OK быстро (тяжёлая логика — в очередь через
php-fpm + cronили отдельный воркер). - Проверяется заголовок
X-Telegram-Bot-Api-Secret-Tokenчерезhash_equals. - Выполнен
setWebhookсdrop_pending_updates=true. - Long polling-скрипт остановлен (cron/systemd unit), иначе два процесса будут гонять один и тот же апдейт.
После этого бот работает в webhook-режиме: Telegram сам доставляет Update на ваш URL.
Дальше: sendMessage — отправляем первый ответ пользователю.