APP_TELEGRAM_TOKEN из одного и того же .env: процесс бота ведёт чат, API проверяет входы и
создаёт счета Stars, а воркер списывает продления через адаптер Stars. Раздельные токены позволили
бы им разойтись во мнении о том, с каким ботом разговаривает клиент.
Эта страница — про настройку. Что бот на самом деле делает для клиента — каждая команда, экран и
сценарий — описано в Telegram-боте.
Создание бота
1
Поговорите с BotFather
Откройте @BotFather, отправьте
/newbot и ответьте отображаемым
именем и именем пользователя, оканчивающимся на bot. BotFather пришлёт токен.2
Положите токен в .env
telegram bot disabled because APP_TELEGRAM_TOKEN is empty и простаивает. Это сделано
намеренно — установке, которая продаёт только через веб-панель, бот для запуска не нужен.3
Запустите стек и посмотрите лог
Бот пишет
telegram bot started с выбранным режимом обновлений. При старте он также
вызывает getMe, чтобы узнать собственное имя пользователя, — именно это делает возможными
реферальные ссылки и веб-виджет Login Widget. Если этот вызов не удался — Telegram ненадолго
недоступен во время старта контейнера, — лог сообщит об этом, а бот спросит снова, когда имя
понадобится экрану рефералов: не раньше чем через 30 секунд, затем с удваивающейся паузой до
одного раза в час, так что перезапуск не нужен.4
Привяжите веб-домен, если вы запускаете клиентскую панель
Отправьте BotFather
/setdomain и укажите хост, с которого раздаётся ваша клиентская панель.
Telegram отрисовывает Login Widget только на домене, привязанном к боту. Без этого экран
входа сообщает telegram: false и не показывает кнопку Telegram — честно, но не то, чего вы
хотели.setMyCommands, на английском и русском: /start, /menu, /plans, /orders, /wallet,
/settings, /support, /login и /cancel. Правка списка в BotFather будет перезаписана при
следующем перезапуске. /ops намеренно отсутствует в опубликованном списке — см.
Операторские инструменты.
Длинные опросы или вебхук
Длинные опросы — режим по умолчанию, и он остаётся поддерживаемым как явный режим разработки и запасной вариант. Бот выбирает режим по тому, задан ли URL вебхука; третьей настройки, которую пришлось бы держать в согласии, нет.Включение вебхука
APP_TELEGRAM_WEBHOOK_URLдолжен разбираться и использовать https, иначе бот завершается сAPP_TELEGRAM_WEBHOOK_URL must be an HTTPS URL.APP_TELEGRAM_WEBHOOK_SECRETдолжен соответствовать^[A-Za-z0-9_-]{32,256}$— набору символов, который принимает сам Telegram, — иначе бот завершается с сообщением, называющим правило.
setWebhook с URL, секретным токеном и явным списком
allowed_updates из message, edited_message, callback_query, pre_checkout_query,
my_chat_member и chat_member. Сбой регистрации фатален: бот, который молча продолжал бы
опрашивать, пока оператор считает, что он на вебхуке, был бы хуже, чем бот, отказавшийся
стартовать. Перечисление типов обновлений вместо приёма всего подряд означает, что Telegram не
доставляет виды обновлений, которые никто не обрабатывает.
Секретный токен — это вся история аутентификации для этого маршрута. Telegram присылает его в
заголовке при каждой доставке, и библиотека проверяет его до разбора обновления, поэтому
запрос без него не доходит ни до одного обработчика. Эндпоинт также ограничивает тело 1 MiB.
Направьте обратный прокси на APP_BOT_HTTP_ADDR и терминируйте TLS там; см.
обратный прокси.
Возврат назад
ОчиститеAPP_TELEGRAM_WEBHOOK_URL и перезапустите. Telegram хранит ранее зарегистрированный
вебхук, пока его что-нибудь не удалит, поэтому удалите его ещё и через Bot API (deleteWebhook),
иначе бот будет опрашивать и по-прежнему ничего не получать.
Mini App и Login Widget
Клиентская веб-панель входит от имени клиента из Telegram двумя способами, и оба проверяют полезную нагрузку, а не доверяют ей. Login Widget — это кнопка на/account/sign-in. Telegram подписывает её поля через
HMAC-SHA256 с ключом SHA-256 от токена бота, поэтому полезная нагрузка, которая вообще
проверяется, доказывает, что Telegram создал её для этого бота. Виджет загружается по имени
пользователя бота, которое Omniflow получает из getMe при первом обращении и кэширует, — одной
переменной окружения меньше, которую пришлось бы держать в согласии с токеном. Если имя
пользователя получить не удалось, экран входа сообщает telegram: false и не показывает кнопку,
вместо того чтобы рисовать ту, которая никогда не появится.
Mini App входит вообще без кнопки. При открытии внутри Telegram окружающий клиент передаёт
странице подписанную строку initData, которую страница отправляет в
POST /v1/account/auth/telegram/miniapp. Проверка отличается ровно в одном существенном месте:
ключ HMAC здесь — HMAC-SHA256("WebAppData", botToken), а не простой SHA-256 от токена. Эти два
пути остаются раздельными в коде, а не делят один хелпер, который угадывал бы, что есть что,
потому что ключ виджета здесь не проверил бы ничего.
Обе проверки ограничивают auth_date одной минутой (с допуском в 30 секунд на спешащие часы
клиента). Хеш сам по себе не истекает, поэтому без этого ограничения однажды перехваченная
полезная нагрузка — из истории браузера, из реферера, со снимка экрана с URL — аутентифицировала
бы вечно.
1
Задайте домен виджета
/setdomain в BotFather, с хостом, который отдаёт /account. Именно это заставляет Login
Widget вообще отрисовываться.2
Зарегистрируйте Mini App, если он вам нужен
Команда
/newapp у BotFather привязывает URL веб-приложения к боту. Клиентской панели
Omniflow ничего дополнительно не требуется: открытая внутри Telegram, она обнаруживает
initData и входит автоматически, а открытая в обычном браузере — откатывается к виджету.3
Проверьте
GET /v1/account/auth/methods сообщает, что эта установка предлагает на самом деле:
{telegram, telegramBot, magicLink, oidc[]}. Экран входа отрисовывается ровно по этому,
поэтому то, что вы там видите, — это то, что API считает настроенным./login. По умолчанию он выключен —
APP_CUSTOMER_MAGIC_LINK_ENABLED=false — потому что это второй предъявительский credential,
путешествующий через чат. Для включения нужны APP_PUBLIC_URL и, на боте, 32-байтовый
APP_DATA_ENCRYPTION_KEY. Веб-панель описывает все три пути со стороны
клиента.
Операторская группа
Операторские уведомления идут в одну группу Telegram с включёнными Топиками. Бот создаёт и привязывает по одному форумному топику на каждый вид события и пересоздаёт удалённый; от вас нужна только группа.1
Создайте группу и включите Топики
Именно группу, а не канал. Включите Топики в настройках группы — бот не может создать
форумный топик в группе, где их нет.
2
Добавьте бота и выдайте право Manage topics
Повысьте бота до администратора как минимум с правом Manage topics. Без него создание
топика падает и записывается как
missing_manage_topics_permission.3
Задайте идентификатор чата
0, нотификатор пишет в лог
operator notifications are disabled because no group is configured, а постановка в очередь
становится пустой операцией — уведомления даже не сохраняются, поэтому включение группы
позже не проиграет историю заново.4
Убедитесь
Следите за
operator topic could not be created в логе бота или читайте
operator_topics.status и last_error_code. Классифицированные коды:
missing_manage_topics_permission, chat_not_found, forum_topics_disabled,
bot_not_in_group и telegram_error — сырое сообщение Telegram отбрасывается, потому что
оно может отражать содержимое запроса.APP_OPERATOR_NOTIFICATION_CAP сообщений одного вида за
APP_OPERATOR_NOTIFICATION_WINDOW_MINUTES (по умолчанию 30 и 5) дальнейшие уведомления
завершаются как suppressed с volume_cap, и в лог пишется предупреждение. Ключ дедупликации
схлопывает повторные срабатывания по одному событию — повторно доставленный вебхук, второй проход
сверки — в одно сообщение. Операторские уведомления
описывают саму очередь.
Операторские инструменты в чате
Резервное копирование и восстановление — единственные административные действия, которые несёт Telegram, и только для явно названных аккаунтов.APP_OPERATOR_TELEGRAM_IDS — это список ID
пользователей Telegram через запятую, которым разрешено выполнять /ops; пустое значение
полностью отключает команду, а некорректная запись — фатальная ошибка конфигурации, а не молча
отброшенный оператор. Команды нет в опубликованном списке команд, поэтому она не появляется в
меню ни у кого. См. резервные копии и восстановление.
Обязательные каналы
Если вы ограничиваете доступ членством в канале, отвечает на этот вопрос именно бот, черезgetChatMember. Добавьте бота в каждый обязательный канал администратором, чтобы он мог читать
членство. Участник в режиме без права голоса (restricted) всё равно считается участником, пока
Telegram сообщает is_member, — ограниченный аккаунт, покинувший канал, участником не считается, — а
ошибка трактуется как «не смог ответить», а не как «нет»: воркер записывает unknown и ждёт, а
контроль при покупке пропускает продажу. Ни то, ни другое не гадает.
Обязательные каналы описывают политику.
Справочник по конфигурации
Ничто не перечитывает окружение: изменение любой из этих переменных означает перезапуск процесса.
О надёжности стоит знать
- Значимые колбэки — подтверждение, отмена, выбор способа оплаты, счёт, удаление устройства,
ротация ссылки — захватываются ровно один раз на каждый callback query в Valkey, а само
нажатие (чат, сообщение, кнопка) захватывается на десять секунд, поэтому повторно
доставленное обновление или двойное нажатие не могут повторить действие. Именно
поэтому бот отказывается стартовать без
APP_VALKEY_URL. - Сбои доставки классифицируются: ожидание из-за флуда, заблокировавший бота пользователь и удалённый аккаунт — разные проблемы. Заблокировавший или удалённый аккаунт перестаёт тратить повторы и исключается из дальнейшей доставки, пока не восстановится.
- Каждое обновление несёт идентификатор корреляции, который логируется вместе с заказом, платежом, задачей и запросом к Remnawave, который оно вызвало, поэтому одна строка связывает сообщение клиента со всем, чего оно коснулось.
APP_METRICS_ENABLEDне применяется к боту: он строит свой реестр метрик безусловно. То, что решает, доступны ли они, — этоAPP_BOT_METRICS_ADDR.