Files
please-pay-me/context/2026-09-20_01-20-00_telegram-webview-login.md
T
2026-09-21 04:06:43 +03:00

70 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-09-20 — Вход через WebView + Telegram Login Widget
## Запрос
Реализовать нативный вход: открыть кабинет в WebView и забрать JWT через
JS-канал. Бэкенд не менять.
## Почему не «просто открыть страницу»
Telegram Login Widget в обычном браузере работает через iframe + `data-onauth`.
В Android/iOS WebView этот путь ломается:
- popup (`window.open` на `oauth.telegram.org`) не возвращает `opener`;
- iframe режется third-party cookies и User-Agent с маркером `; wv`;
- callback `onTelegramAuth` просто не вызывается.
Поэтому в WebView виджет переключается на **redirect-режим** (`data-auth-url`),
а Flutter забирает уже готовый JWT, который кабинет и так кладёт в
`localStorage.ppm_session_jwt`. API (`POST /api/auth/telegram`) не трогали.
## Поток
1. Экран входа на iOS/Android показывает «Войти через Telegram».
2. Открывается fullscreen WebView на `{cabinet}/login`.
3. Кабинет видит канал `window.PpmAuth` → ставит виджету `data-auth-url=/login`.
4. Пользователь логинится в Telegram; редирект приходит на `/login?id&hash&…`.
5. `telegramPayloadFromQuery` собирает payload, кабинет зовёт тот же
`loginWithTelegram` / `POST /api/auth/telegram`.
6. `setSession` пишет JWT в `localStorage` и зовёт `PpmAuth.postMessage`.
7. Flutter парсит сообщение, закрывает WebView, проверяет токен через
`GET /api/me`, кладёт сессию в `SharedPreferences`.
Запасные пути, если кабинет ещё не задеплоен с мостом:
- JS в WebView хукает `localStorage.setItem('ppm_session_jwt')` и поллит ключ;
- на Windows/web WebView нет — форма «вставить токен»;
- «Демо-режим» по-прежнему без сети.
## Что изменилось
### Web (не API)
- `web/src/auth/telegramRedirect.ts` — разбор query и `postTokenToNativeApp`.
- `TelegramLoginButton``data-auth-url` только если есть `window.PpmAuth`.
- `LoginPage` — автологин, если в URL уже лежит telegram-payload.
- `setSession` — после записи токена шлёт его в канал.
### Mobile
- `TelegramLoginScreen` (`webview_flutter`): канал `PpmAuth`, Chrome UA без
`; wv`, third-party cookies на Android, `tg://` уходит во внешнее приложение,
кнопка «назад» после oauth.telegram.org.
- `resolveCabinetLoginUri` всегда открывает `/login`.
- `INTERNET` в main `AndroidManifest` (раньше был только в debug).
- iOS: `LSApplicationQueriesSchemes` для `tg` / `telegram`.
- `PPM_WEB_URL` по умолчанию = `PPM_API_BASE_URL` (один origin за nginx).
## Тесты
- `resolveApiBaseUrl` / `resolveCabinetLoginUri` / парсер канала.
- виджет: инжектированный launcher отдаёт JWT → `GET /api/me` → signed in.
- 32 теста приложения, 102 в Widgetbook, `flutter analyze` чистый.
## Запуск против живого кабинета
```powershell
cd mobile
.\run.ps1 -Device windows # на Windows будет форма токена
# на телефоне:
.\run.ps1 -ApiBaseUrl https://<домен-кабинета>
```
Нужен публичный HTTPS и BotFather `/setdomain` на этот домен — как для веба.