mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-09-14 16:53:08 +00:00
retrieveRawInitData() ищет параметры запуска по цепочке location.href -> запись performance о навигации -> кэш tapps/launchParams в sessionStorage, записывая удачный результат обратно. Последние два источника привязаны к документу, а не к текущему запуску мини-аппы: как только SPA сменила маршрут и hash с tgWebAppData ушёл из адреса, остаются данные ПЕРВОГО запуска в этой сессии WebView. На iOS WebView переживает переоткрытия, и SDK молча отдаёт старую копию. Бэкенд принимает initData с auth_date не старше 30 суток, поэтому застрявшая копия рано или поздно пересекает порог и вход отваливается с «Invalid or expired Telegram authentication data». Спрашиваем ещё и window.Telegram.WebApp.initData (официальный мост, telegram-web-app.js из index.html) и берём вариант со свежим auth_date: какой источник протух, зависит от платформы, «самый свежий» верен всегда. Все три места чтения initData сведены в один модуль.
64 lines
3.2 KiB
TypeScript
64 lines
3.2 KiB
TypeScript
import { retrieveRawInitData } from '@telegram-apps/sdk-react';
|
||
|
||
/**
|
||
* Сырая строка initData Telegram, прочитанная в момент вызова.
|
||
*
|
||
* Почему мало одного `retrieveRawInitData()` из @telegram-apps/sdk: он ищет
|
||
* параметры запуска по цепочке `location.href` → запись performance о навигации
|
||
* → собственный кэш `tapps/launchParams` в sessionStorage, записывая удачный
|
||
* результат обратно в кэш. Последние два источника привязаны не к текущему
|
||
* запуску мини-аппы, а к документу: как только SPA сменила маршрут и hash с
|
||
* `tgWebAppData` ушёл из адреса, остаются запись о навигации исходного
|
||
* документа и кэш — оба из ПЕРВОГО запуска в этой сессии WebView. На iOS такой
|
||
* WebView переживает переоткрытия мини-аппы, и SDK молча отдаёт initData
|
||
* недельной давности, без единой ошибки.
|
||
*
|
||
* Цена — отказ входа: бэкенд принимает initData с `auth_date` не старше 30
|
||
* суток, и застрявшая копия рано или поздно пересекает порог, после чего
|
||
* логин отвечает «Invalid or expired Telegram authentication data».
|
||
*
|
||
* Поэтому спрашиваем ещё и `window.Telegram.WebApp.initData` — его пишет
|
||
* официальный мост Telegram (telegram-web-app.js, подключается в index.html),
|
||
* и он не завязан на кэш SDK. Какой из источников протух, зависит от платформы
|
||
* и способа открытия, поэтому берём не «первый доступный», а тот, у которого
|
||
* `auth_date` больше.
|
||
*/
|
||
export function getTelegramInitData(): string | null {
|
||
if (typeof window === 'undefined') return null;
|
||
|
||
const candidates = [fromTelegramBridge(), fromSdk()].filter((value): value is string =>
|
||
Boolean(value),
|
||
);
|
||
if (candidates.length === 0) return null;
|
||
|
||
// При равном или неразобранном auth_date побеждает мост: он ближе к
|
||
// источнику, чем кэш SDK.
|
||
return candidates.reduce((best, candidate) =>
|
||
authDateOf(candidate) > authDateOf(best) ? candidate : best,
|
||
);
|
||
}
|
||
|
||
function fromTelegramBridge(): string | null {
|
||
return window.Telegram?.WebApp?.initData || null;
|
||
}
|
||
|
||
function fromSdk(): string | null {
|
||
try {
|
||
return retrieveRawInitData() || null;
|
||
} catch {
|
||
// Вне Telegram параметров запуска нет — это не ошибка.
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/** Метка времени выдачи initData; 0, если её не удалось разобрать. */
|
||
function authDateOf(initData: string): number {
|
||
try {
|
||
const raw = new URLSearchParams(initData).get('auth_date');
|
||
const parsed = Number(raw);
|
||
return raw && Number.isFinite(parsed) ? parsed : 0;
|
||
} catch {
|
||
return 0;
|
||
}
|
||
}
|