# Как срабатывает Telegram Mini App (по шагам) Ты в Telegram нажимаешь кнопку «Открыть мини-апп» → открывается **aiform.clientright.ru**. Ниже — что происходит дальше и где. --- ## 1. Где открывается страница - **Кто:** Telegram (клиент на телефоне/десктопе). - **Что:** Открывает aiform.clientright.ru **в своём встроенном браузере (WebView)** как Mini App. - **Важно:** В этом режиме Telegram сам подставляет в страницу свой скрипт и объект `window.Telegram.WebApp` с полем **initData** (подпись пользователя и данные). В обычном браузере по прямой ссылке этого объекта нет. --- ## 2. Загрузка фронта (aiform.clientright.ru) - Загружается твой SPA (React): главная страница — форма заявки **ClaimForm**. - Рендерится первый экран формы (шаг 0). - Сразу при монтировании компонента запускается **useEffect** с функцией `tryTelegramAuth()` (в `ClaimForm.tsx`). **Где в коде:** `frontend/src/pages/ClaimForm.tsx`, блок «Telegram Mini App: попытка авторизоваться через initData при первом заходе». --- ## 3. Проверка: это Mini App или обычный сайт? Фронт делает: 1. Смотрит, есть ли `window.Telegram?.WebApp?.initData`. 2. Если нет — ждёт 300 ms (на случай асинхронной подгрузки скрипта Telegram) и проверяет снова. 3. Если после этого **нет** `initData` → в консоль пишется «Telegram WebApp не обнаружен», авторизация по Telegram **не вызывается**, форма ведёт себя как обычный веб-сайт (SMS, сессия из localStorage и т.д.). 4. Если **есть** `initData`: - Проверяет, есть ли уже в **localStorage** ключ `session_token`. - Если **есть** → считаем, что пользователь уже залогинен, tg/auth не вызываем, дальше работает обычное восстановление сессии. - Если **нет** → идём в шаг 4. **Итого:** срабатывание tg/auth **только** когда: - страница открыта **из Telegram** (есть `initData`), - и в localStorage **нет** сохранённого `session_token`. --- ## 4. Запрос на бэкенд: POST /api/v1/tg/auth - **Кто:** фронт (ClaimForm). - **Куда:** на тот же домен aiform.clientright.ru → запрос уходит на твой backend (через nginx/proxy на порт 8200). - **URL:** `POST /api/v1/tg/auth`. - **Тело:** `{ "init_data": "<строка initData от Telegram>" }`. **Где в коде:** `ClaimForm.tsx` — `fetch('/api/v1/tg/auth', { method: 'POST', body: JSON.stringify({ init_data: webApp.initData }) })`. --- ## 5. Обработка на бэкенде (tg/auth) - **Где:** `backend/app/api/telegram_auth.py`, эндпоинт `POST /api/v1/tg/auth`. Последовательно: 1. **Валидация initData** (`backend/app/services/telegram_auth.py`): - Проверка подписи через **TELEGRAM_BOT_TOKEN** из `.env`. - Если токена нет или подпись не совпадает → ответ **400** (или 500), фронт пишет «Telegram auth failed» и ведёт себя как обычный сайт. 2. **Извлечение пользователя Telegram:** из initData достаются `id`, `username`, `first_name`, `last_name`. 3. **Запрос в n8n:** - Бэкенд дергает **N8N_TG_AUTH_WEBHOOK** (URL из `.env`). - Передаёт: `telegram_user_id`, `username`, `first_name`, `last_name`, `session_token`, `form_id`. - Ожидает в ответе минимум **unified_id** (и при необходимости contact_id, phone, has_drafts). 4. **Создание сессии в Redis:** - По `session_token` + `unified_id` (+ phone, contact_id) создаётся запись сессии (как после SMS-логина). 5. **Ответ фронту:** `{ success: true, session_token, unified_id, contact_id?, phone?, has_drafts? }`. Если на любом шаге ошибка (нет токена, n8n не вернул unified_id и т.д.) — бэкенд отдаёт ошибку, фронт считает tg/auth неуспешным и продолжает как обычный веб. --- ## 6. Что делает фронт после успешного ответа - Сохраняет **session_token** в **localStorage** и в `sessionIdRef`. - Обновляет состояние формы: `unified_id`, `phone`, `contact_id`, `session_id`. - Ставит **isPhoneVerified = true** (шаг «телефон» считаем пройденным). - Если в ответе **has_drafts === true** → показывает экран выбора черновиков. - Если **has_drafts** нет или false → переводит на **шаг 1** (описание проблемы). Дальше пользователь идёт по форме как обычно: описание → черновик/визард → подтверждение → оплата и т.д., но уже без ввода телефона и SMS, потому что он «залогинен» через Telegram. --- ## Сводка: где что срабатывает | Шаг | Где | Что происходит | |-----|-----|----------------| | 1 | Telegram | Открывает aiform.clientright.ru в WebView, подставляет WebApp и initData | | 2 | Браузер (WebView) | Загружается SPA, монтируется ClaimForm | | 3 | ClaimForm.tsx (фронт) | Проверка: есть ли Telegram.WebApp.initData и нет ли session_token в localStorage | | 4 | ClaimForm.tsx (фронт) | POST /api/v1/tg/auth с init_data | | 5 | telegram_auth.py (бэкенд) | Валидация initData, запрос в n8n, создание сессии в Redis | | 6 | ClaimForm.tsx (фронт) | Сохранение session_token, переход на шаг черновиков или описание | --- ## Если открыть aiform.clientright.ru не из Telegram - В обычном браузере (Chrome, Safari по прямой ссылке) **нет** `window.Telegram.WebApp`. - Фронт пишет в консоль «Telegram WebApp не обнаружен» и **не вызывает** /api/v1/tg/auth. - Работает обычный сценарий: ввод телефона → SMS → сессия и т.д. --- ## Что должно быть настроено 1. **В Telegram:** у бота должна быть кнопка/меню, открывающее Mini App с URL **https://aiform.clientright.ru** (или с путём на эту форму). 2. **Backend .env:** - **TELEGRAM_BOT_TOKEN** — токен этого же бота (для проверки initData). - **N8N_TG_AUTH_WEBHOOK** — URL webhook в n8n, который по telegram_user_id возвращает unified_id (и при необходимости contact_id, phone, has_drafts). 3. **n8n:** workflow по этому webhook принимает JSON с telegram_user_id и т.д. и отдаёт JSON с полем **unified_id** (обязательно). Если что-то из этого не настроено, цепочка обрывается на шаге 5 (бэкенд/n8n), и пользователь остаётся в «обычном» режиме формы без авторизации через Telegram.