Вебхук для бота в MAX: порт 443, сертификат Минцифры и повторные события
Вебхук — самая частая причина, по которой перенос бота в MAX затягивается. Код отправки сообщений переписывается за вечер, а потом бот то молчит, то отвечает дважды. Ниже пять мест, где это происходит.
1. Только HTTPS на порту 443
Подписка на события создаётся через POST /subscriptions. Адрес вебхука должен работать по HTTPS на порту 443 с сертификатом доверенного центра. Самоподписанный сертификат и нестандартный порт не подойдут. Если бот жил на сервере без домена, понадобится домен и сертификат, например от Let’s Encrypt.
2. Сертификат Минцифры на стороне бота
Это обратная сторона: не MAX стучится к вам, а ваш бот стучится в API MAX. Сертификат API выпущен цепочкой Минцифры, которой нет в стандартных хранилищах сертификатов. Поэтому HTTP-клиент бота падает на проверке. Решение — добавить корневой сертификат Минцифры в доверенные в образе или контейнере бота. Отключать проверку сертификатов не стоит.
3. Ответ 200 за 30 секунд
MAX ждёт ответ на вебхук не дольше 30 секунд. Если бот сначала идёт в CRM или считает что-то долгое, а потом отвечает 200, событие может считаться недоставленным. Правило простое: сразу отвечайте 200, а тяжёлую работу делайте в фоне.
4. Повторная доставка и дубли
Если MAX не получил 200 вовремя, он доставит событие ещё раз. Без проверки бот ответит пользователю дважды, создаст две заявки или спишет два бонуса. Нужна дедупликация: храните идентификаторы обработанных событий и пропускайте повторы.
seen = set() # в бою: Redis с TTL
def handle(update):
key = (update['update_type'], update['timestamp']) # упрощённо
if key in seen:
return # повтор, уже обработали
seen.add(key)
process(update)
5. Long polling молчит при активной подписке
Для отладки удобно запускать бота на long polling через GET /updates. Но если на бота уже есть подписка на вебхук, long polling молча ничего не получает. Перед отладкой удалите подписку через DELETE /subscriptions, а перед запуском в бой верните её.
Как обойтись без всего этого
Шлюз BotHop сам держит вебхук MAX на 443, доверяет цепочке Минцифры, отвечает MAX вовремя и отсекает повторы. Бот получает события так, как привык в Telegram: через getUpdates или на свой вебхук. Меняется только адрес API — api.bothop.ru вместо api.telegram.org.
| Проблема | Вручную | Через BotHop |
|---|---|---|
| Вебхук | Поднять HTTPS на порту 443 с сертификатом доверенного центра | Держит шлюз |
| Сертификат MAX | Добавить цепочку Минцифры, иначе клиент падает на проверке | Уже настроено |
| Повторные апдейты | Написать защиту, иначе бот отвечает дважды | Дубли отсекаются |
| Длинные сообщения | Резать текст: в MAX лимит 4 000 символов | Режутся по абзацам |
| Связь с Telegram | Держать отдельный сервер для связи с Telegram | Стабильная связь через BotHop |
Частые вопросы
Можно ли в MAX использовать long polling?
Можно, через `GET /updates`. Но пока активна подписка на вебхук, long polling ничего не получает, а для работы в бою MAX требует вебхук.
Почему бот в MAX отвечает дважды?
MAX повторяет доставку события, если не получил ответ 200 вовремя. Без проверки на дубли бот обрабатывает одно и то же событие два раза.
Зачем нужен сертификат Минцифры?
Сертификат API MAX выпущен цепочкой Минцифры, которой нет в стандартных хранилищах. Без неё HTTP-клиент бота не доверяет серверу MAX и падает на проверке.