/** * n8n Code node: парсинг сырого init_data из Telegram WebApp * * Вход: объект с полем init_data (строка query string от Telegram). * Выход: тот же объект + поля init_data_parsed и user_decoded. * * Подключение: после Webhook — в Code передаётся $input.item.json. * init_data должен быть в $json.init_data (как шлёт наш бэкенд). */ const item = $input.first().json; // Сырая строка init_data (query string) const rawInitData = item.init_data || item.body?.init_data || ''; if (!rawInitData) { return [{ json: { ...item, init_data_error: 'init_data отсутствует' } }]; } /** * Парсит query string в объект (значения URL-декодированы) */ function parseQueryString(qs) { const result = {}; const pairs = qs.split('&'); for (const pair of pairs) { const [key, value] = pair.split('=').map(s => decodeURIComponent(s || '')); if (key) result[key] = value; } return result; } const parsed = parseQueryString(rawInitData); // user приходит как URL-encoded JSON строка let userDecoded = null; if (parsed.user) { try { userDecoded = JSON.parse(parsed.user); } catch (e) { userDecoded = { _parse_error: String(e), raw: parsed.user }; } } return [{ json: { ...item, init_data_parsed: { query_id: parsed.query_id || null, auth_date: parsed.auth_date ? parseInt(parsed.auth_date, 10) : null, hash: parsed.hash || null, signature: parsed.signature || null, user_raw: parsed.user || null, }, user_decoded: userDecoded, // удобные поля для маппинга в CRM telegram_user_id: userDecoded?.id ?? null, telegram_username: userDecoded?.username ?? null, telegram_first_name: userDecoded?.first_name ?? null, telegram_last_name: userDecoded?.last_name ?? null, }, }];