Обновления

С polling на webhook

Перевод бота с getUpdates на webhook: вызов setWebhook, drop_pending_updates, остановка polling-скрипта и чек-лист миграции.

Если бот начинал работу через 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 — отправляем первый ответ пользователю.