Все статьи
Пакеты обновлений чата в стиле Telegram проходят через защищенный туннель HTTPS в обработчик бота, работающий на ноутбуке разработчика.
Telegram Bot APIwebhookslocalhostbot development

Как протестировать вебхук Telegram-бота на localhost

Чтобы протестировать веб-хук бота Telegram на локальном хосте, откройте свой локальный сервер с помощью общедоступного HTTPS-туннеля, вызовите setWebhook с этим URL-адресом и проверяйте заголовок секретного токена Telegram при каждом запросе. Это дает вам реальные сообщения, запросы обратного вызова и обновления членства без развертывание после каждого изменения кода. Полный цикл таков: запустите обработчик бота, запустите npx portpreview 3000, зарегистрируйте полученный URL-адрес, отправьте боту сообщение и проверьте запрос локально.

Почему Telegram не может отправлять обновления напрямую на локальный хост

API-интерфейс Telegram Bot отправляет обновления веб-перехватчика из инфраструктуры Telegram на URL-адрес, доступный в Интернете. localhost, 127.0.0.1 и частные адреса локальной сети не маршрутизируются из этой инфраструктуры. Туннель localhost завершает HTTPS по публичному адресу и перенаправляет неизмененный HTTP-запрос на ваш локальный порт.

Боты Telegram могут получать обновления двумя взаимоисключающими способами: длинным опросом через getUpdates или веб-перехватчиками. В официальной ссылке setWebhook указано, что getUpdates недоступен, пока настроен исходящий веб-перехватчик. Если процесс опроса все еще выполняется, остановите его, прежде чем оценивать поток веб-перехватчика.

Создание локальной конечной точки веб-перехватчика

В этом примере Express обработчик намеренно сделан маленьким. Он проверяет общий секрет перед обновлением, быстро подтверждает и перемещает работу за пределы пути ответа.

import express from 'express';
import crypto from 'node:crypto';

const app = express();
app.use(express.json({ limit: '1mb' }));

function sameSecret(received = '', expected = '') {
  const a = Buffer.from(received);
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post('/webhooks/telegram', (req, res) => {
  const received = req.get('x-telegram-bot-api-secret-token') || '';
  if (!sameSecret(received, process.env.TELEGRAM_WEBHOOK_SECRET)) {
    return res.sendStatus(401);
  }

  const update = req.body;
  res.sendStatus(200);
  queueMicrotask(() => handleUpdate(update));
});

app.listen(3000, () => console.log('Listening on http://localhost:3000'));

Telegram отправляет Update в формате JSON. В отличие от поставщиков на базе HMAC, функция Telegram secret_token не подписывает тело сообщения. Выбранное вами значение помещается в X-Telegram-Bot-Api-Secret-Token. Токен доказывает, что отправителю известно значение, использованное при регистрации веб-перехватчика, но он не предоставляет дайджест полезной нагрузки. TLS защищает запрос при передаче.

Предоставить конечную точку с помощью HTTPS

  1. Запустите приложение и подтвердите, что curl -i http://localhost:3000/webhooks/telegram достигает сервера, даже если GET вернет 404.
  2. Откройте второй терминал и запустите npx portpreview 3000.
  3. Скопируйте общедоступный источник HTTPS и добавьте /webhooks/telegram.
  4. Оставьте процесс туннеля запущенным, пока Telegram доставляет обновления.

API бота принимает URL-адреса веб-перехватчиков HTTPS. Telegram документирует поддержку веб-перехватчиков на портах 443, 80, 88 и 8443; общедоступная конечная точка управляемого туннеля обычно использует 443, даже если перенаправленный локальный процесс прослушивает 3000.

Безопасная регистрация веб-перехватчика Telegram

Создайте случайный секрет, содержащий только буквы, цифры, символы подчеркивания или дефисы. Telegram допускает длину от 1 до 256 символов. Не используйте повторно токен бота в качестве этого значения.

export TELEGRAM_WEBHOOK_SECRET="$(openssl rand -hex 32)"

curl -sS -X POST \
  "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/setWebhook" \
  -d "url=https://YOUR-TUNNEL.portpreview.dev/webhooks/telegram" \
  -d "secret_token=${TELEGRAM_WEBHOOK_SECRET}" \
  -d 'allowed_updates=["message","callback_query"]' \
  -d "drop_pending_updates=true"

allowed_updates уменьшает шум и должен перечислять только типы обновлений, которые обрабатывает бот. drop_pending_updates=true полезен при запуске нового локального сеанса, но он навсегда отбрасывает обновления в очереди, поэтому опускайте его, когда эти события имеют значение. Обновленная документация Telegram описывает такие поля, как message, callback_query и my_chat_member.

Подтвердите регистрацию перед отладкой кода

Используйте getWebhookInfo, чтобы отделить ошибки конфигурации от ошибок обработчика:

curl -sS "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getWebhookInfo"

Проверьте url, pending_update_count, last_error_message и last_error_date. Пустой URL-адрес означает, что регистрация не сохранилась. Растущее количество ожидающих запросов обычно означает, что Telegram не может подключиться или ваша конечная точка возвращает статус, отличный от 2xx. Отправьте сообщение боту в директ после регистрации; простое открытие чата не обязательно приводит к обновлению.

Обработка обновлений без повторных попыток

Подтвердить перед медленной работой

Вернуть ответ 2xx, как только запрос будет аутентифицирован и окончательно принят. Экспорт базы данных, вызовы искусственного интеллекта и сторонние API должны выполняться асинхронно. Telegram повторяет неудачные запросы после ответов, отличных от 2xx, поэтому медленная синхронная работа может создавать дубликаты.

Дедупликация с update_id

Каждое обновление имеет update_id. Сохраняйте обработанные идентификаторы с указанием срока действия или используйте уникальный ключ базы данных. При повторной попытке не следует отправлять вторую квитанцию об оплате, создавать дубликат заявки или дважды выполнять один и тот же обратный вызов.

Моделируйте каждый тип обновления явно

Не каждое обновление содержит message.text. Кнопки обратного вызова находятся под callback_query; Публикации на канале и изменения в членстве имеют другие поля. Разветвляйтесь по текущему полю верхнего уровня и обрабатывайте неизвестные типы как допустимые пустые операции, а не выбрасывающие.

Правила безопасности для локального тестирования ботов Telegram

  • Сначала проверьте секретный заголовок. Отклоняйте отсутствующие или неправильные значения перед регистрацией или анализом конфиденциальных полей.
  • Не допускайте попадания токенов в URL-адреса и журналы. Токен Bot API в команде регистрации является учетными данными. Избегайте истории оболочки в общих системах и меняйте открытый токен через BotFather.
  • Используйте неугаданный и секретный маршрут. Маршрут представляет собой глубокоэшелонированную защиту; секретный заголовок — это фактическая проверка приложения.
  • Ограничить перехват данных. Сообщения могут содержать имена, имена пользователей, номера телефонов, файлы и текст частной беседы. Отредактируйте журналы и удалите локальные записи, когда закончите.
  • Никогда не отключайте аутентификацию в процессе разработки. Публичный туннель является общедоступным. Локальный код должен выполнять те же проверки, что и производственный.

См. более подробное руководство по безопасности туннеля локального хоста для получения информации о методах контроля доступа и хранения данных.

Устранение распространенных неполадок веб-перехватчика Telegram

Telegram сообщает об ошибке сертификата или соединения

Используйте URL-адрес HTTPS туннеля, а не его локальную цель HTTP. Убедитесь, что туннель активен и URL-адрес не изменился. Если вместо этого вы предоставите собственный самозаверяющий сертификат, Telegram потребует загрузить общедоступный сертификат в виде файла; управляемая конечная точка TLS позволяет избежать такой настройки.

Конечная точка возвращает 401

Сравните секрет, переданный в setWebhook, с переменной среды, используемой процессом. Имена заголовков не чувствительны к регистру, но прокси-серверы или промежуточное программное обеспечение могут удалять пользовательские заголовки. Проверьте входящие заголовки, не печатая секретное значение.

Запросы не поступают

Запустите getWebhookInfo, убедитесь, что зарегистрированный путь точно соответствует вашему маршруту, и убедитесь, что никакой брандмауэр не блокирует локальное соединение туннеля. Если вы недавно использовали опрос, убедитесь, что URL-адрес веб-перехватчика теперь заполнен. Запустите актуальное обновление, отправив сообщение боту.

Обновления приходят неоднократно

Состояние журнала и время ответа. Исключения после получения запроса могут превратить запланированное 200 в 500. Возвращайте 200 сразу же, делайте обработку идемпотентной и используйте контролируемое воспроизведение веб-перехватчика вместо ожидания повторных попыток поставщика во время отладки.

Проверка запросов обратного вызова и файлов, а не только текста

Полезная матрица тестирования ботов охватывает более message.text. Отправьте фотографию с подписью, поделитесь контактом, отредактируйте сообщение и нажмите кнопку на встроенной клавиатуре. Для запросов обратного вызова немедленно вызовите answerCallbackQuery, чтобы клиент перестал показывать индикатор выполнения, а затем выполните более медленную работу отдельно. Обновления файлов содержат идентификаторы; загрузка байтов — это вторая операция API бота, которая не должна задерживать ответ веб-перехватчика.

Сохраняйте исправления, созданные из очищенных обновлений для модульных тестов, но сохраняйте полный путь транспортировки хотя бы для одного теста каждого поддерживаемого типа. Крепеж доказывает, что ваш диспетчер понимает полезную нагрузку; реальная туннельная доставка также подтверждает регистрацию, TLS, заголовки, анализ тела и поведение подтверждения. При добавлении новой записи allowed_updates снова вызовите setWebhook и убедитесь, что getWebhookInfo отражает предполагаемую конфигурацию.

Удалить вебхук после локального сеанса

curl -sS -X POST \
  "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/deleteWebhook" \
  -d "drop_pending_updates=false"

Удаление веб-перехватчика позволяет вернуться к getUpdates. Если URL-адрес туннеля изменится при следующем сеансе, позвоните по номеру setWebhook еще раз. Для дополнительной диагностики следуйте общему рабочему процессу отладки локального веб-перехватчика.

.

Часто задаваемые вопросы

Может ли Telegram отправить вебхук бота непосредственно на локальный хост?
Нет. Telegram не может перенаправлять запросы на локальный хост или частный адрес локальной сети. Используйте общедоступный HTTPS-туннель, который перенаправляет запросы на ваш локальный бот-сервер.
Как аутентифицировать запросы веб-перехватчика бота Telegram?
Передайте случайный secret_token в setWebhook и сравните заголовок X-Telegram-Bot-Api-Secret-Token каждого запроса с этим значением, используя безопасное по времени сравнение.
Почему мой вебхук Telegram получает повторяющиеся обновления?
Telegram повторяет неудачную попытку доставки. Быстро верните 2xx и выполните дедупликацию работы с помощью update_id, чтобы при повторных попытках не повторялись побочные эффекты.
Могу ли я использовать getUpdates, когда вебхук Telegram активен?
Нет. API-интерфейс Telegram Bot не позволяет получать обновления, пока настроен исходящий веб-перехватчик. Удалите вебхук, прежде чем вернуться к длинному опросу.