Files
aiform_prod/docs/TELEGRAM_MINIAPP_FLOW.md

123 lines
8.0 KiB
Markdown
Raw Normal View History

feat: Telegram Mini App integration and UX improvements - Добавлена полная интеграция с Telegram Mini App (динамическая загрузка SDK) - Отдельный компактный дизайн для Telegram Mini App - Добавлен loader при инициализации (предотвращает мелькание SMS-авторизации) - Улучшена навигация: кнопки "Назад" и "К списку заявок" теперь сохраняют авторизацию - Telegram Mini App: кнопка "Выход" просто закрывает приложение - Telegram Mini App: заявки "В работе" скрыты из списка - Веб-версия: для заявок "В работе" добавлена кнопка "Просмотреть в Telegram" (ссылка на @klientprav_bot) - Telegram Mini App: кнопки действий в черновиках расположены вертикально - Веб-версия: убрано отображение номера телефона в приветствии - Исправлена проблема с возвратом к списку черновиков (не требует повторной SMS-авторизации) - Заблокировано удаление и редактирование заявок со статусом "В работе" - Добавлена документация по Telegram Mini App интеграции
2026-01-29 16:12:48 +03:00
# Как срабатывает 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.