9.8 KiB
🔒 Исправление: Имена user_... при trial подписке
📋 Описание проблемы
При оформлении trial (пробной) подписки username генерировался в формате user_1770605873419 (timestamp) вместо реального имени пользователя.
🔍 Причина
Это НЕ баг кода! Telegram WebApp API не передает данные пользователя (tgUser.id, tgUser.username, tgUser.first_name) когда:
- ❌ Приложение открыто в браузере напрямую (не через Telegram бота)
- ❌ Telegram WebApp не инициализирован (например, в dev режиме)
- ❌ Недостаточно прав доступа к Telegram API
Старое поведение (до фикса):
// app/page.tsx (handleActivateTrial)
telegramId: tgUser?.id || Date.now(), // ❌ Fallback на timestamp!
Результат: Если tgUser?.id = undefined → username = user_1770605873419 (таймстамп)
✅ Решение
Добавлена обязательная валидация Telegram ID на всех уровнях:
1. Frontend - app/page.tsx (Trial кнопка)
const tgUser = telegramWebApp?.initDataUnsafe?.user;
// 🔍 DEBUG логирование
console.log('🎁 TRIAL ACTIVATION - Telegram data:', {
hasWebApp: !!telegramWebApp,
hasUser: !!tgUser,
userId: tgUser?.id,
username: tgUser?.username,
firstName: tgUser?.first_name
});
// ⚠️ БЛОКИРУЕМ создание без Telegram ID
if (!tgUser?.id) {
console.error('❌ TRIAL BLOCKED: No Telegram user data!');
showToastNotification('❌ Откройте приложение через Telegram бота');
return;
}
// Теперь tgUser.id 100% есть
const response = await fetch('/api/create-user', {
body: JSON.stringify({
planType: 'trial',
telegramId: tgUser.id, // ✅ Без fallback!
telegramUsername: tgUser?.username,
firstName: tgUser?.first_name,
})
});
2. Frontend - app/plans/page.tsx (3-step flow)
async function createUser(planType, period, locationIds) {
const user = telegramWebApp?.initDataUnsafe?.user;
// ⚠️ БЛОКИРУЕМ без user.id
if (!user?.id) {
console.error('❌ USER CREATION BLOCKED: No Telegram user ID!');
alert('❌ Откройте приложение через Telegram бота\n\nПриложение должно быть открыто в Telegram Mini App.');
return;
}
const requestBody = {
telegramId: user.id, // ✅ 100% существует
telegramUsername: user?.username || null,
firstName: user?.first_name || null,
};
}
3. Backend - app/api/create-user/route.ts
export async function POST(request: NextRequest) {
const { telegramId, telegramUsername, firstName } = await request.json();
// ⚠️ СЕРВЕРНАЯ ВАЛИДАЦИЯ
if (!telegramId) {
logger.error('❌ VALIDATION FAILED: No telegramId provided');
return NextResponse.json(
{
success: false,
error: 'Telegram ID is required. Please open the app through Telegram bot.'
},
{ status: 400 }
);
}
// Генерация username с приоритетами
let username: string;
if (telegramUsername) {
username = telegramUsername.toLowerCase().replace(/[^a-z0-9_]/g, '_');
} else if (firstName && telegramId) {
username = `${firstName.toLowerCase().replace(/[^a-z0-9]/g, '_')}_${telegramId}`;
} else {
username = `user_${telegramId}`; // ✅ Используем реальный ID, не timestamp
}
}
📊 Результат
До фикса:
- ❌
user_1770605873419(timestamp) - когда Telegram не передает данные - ❌ Создается подписка даже без Telegram ID
- ❌ Невозможно отследить пользователя
После фикса:
- ✅ БЛОКИРОВКА создания если нет
tgUser.id - ✅ Понятное сообщение: "Откройте приложение через Telegram бота"
- ✅ Debug логи показывают причину блокировки
- ✅ Все имена генерируются из реальных Telegram данных
🧪 Тестирование
Правильный путь (через Telegram бота):
- Открыть Telegram бот
@Chat_8n8_bot - Нажать "Открыть приложение" /
Start - Telegram WebApp передаст:
{ id: 123456789, username: "john_doe", first_name: "John" } - Username:
john_doe✅
Неправильный путь (в браузере напрямую):
- Открыть
https://app.umbrix.netв Chrome - Telegram WebApp недоступен:
window.Telegram?.WebApp = undefined - Попытка создать trial → БЛОКИРОВКА ❌
- Сообщение: "Откройте приложение через Telegram бота"
📝 Debug логи
При попытке создать trial без Telegram данных в консоли браузера:
🎁 TRIAL ACTIVATION - Telegram data: {
hasWebApp: false,
hasInitData: false,
hasUser: false,
userId: undefined,
username: undefined,
firstName: undefined,
fullData: undefined
}
❌ TRIAL BLOCKED: No Telegram user data!
🚀 Production деплой
Изменения задеплоены:
- ✅ Локальный билд: PASSED
- ✅ Production билд: PASSED
- ✅ PM2 перезапущен: pid 48353
- ✅ Git коммит:
806b668
🔑 Ключевые файлы
- app/page.tsx - handleActivateTrial (строки 188-245)
- app/plans/page.tsx - createUser (строки 171-225)
- app/api/create-user/route.ts - telegramId validation (строки 22-47)
- types/telegram.ts - TelegramWebApp интерфейс
- types/telegram.d.ts - Window.Telegram декларация
- hooks/useTelegramWebApp.ts - Telegram WebApp hook
💡 Важно!
Если пользователь видит имена user_... - это означает, что:
- Приложение открыто не через Telegram бота
- Telegram WebApp не инициализирован
- Нужно переоткрыть через
@Chat_8n8_bot→ "Открыть приложение"
Теперь система автоматически блокирует такие попытки! ✅
🔓 UPDATE: Исключение для n8n переходов (5677b48)
Проблема после первого фикса:
После блокировки создания без Telegram ID - перестали работать переходы из n8n!
n8n workflow отправляет пользователей по прямой ссылке (открывается в браузере), где window.Telegram?.WebApp недоступен.
Решение:
Добавлены URL параметры-исключения для n8n переходов:
// Проверяем источник перехода
const urlParams = new URLSearchParams(window.location.search);
const source = urlParams.get('source') || urlParams.get('utm_source');
const fromN8n = source === 'n8n' || source === 'chat' || urlParams.has('from_n8n');
// Блокируем ТОЛЬКО если нет Telegram ID И это НЕ n8n переход
if (!tgUser?.id && !fromN8n) {
showToastNotification('❌ Откройте приложение через Telegram бота');
return;
}
// Для n8n переходов генерируем временный ID
const userId = tgUser?.id || Date.now();
Поддерживаемые параметры:
?source=n8n- рекомендуемый?utm_source=n8n- для аналитики?utm_source=chat- альтернативный вариант?from_n8n=true- явное указание
Примеры ссылок из n8n:
✅ https://app.umbrix.net/?source=n8n
✅ https://app.umbrix.net/plans?utm_source=chat
✅ https://app.umbrix.net/?from_n8n=true&ref=user123
❌ https://app.umbrix.net/ (без параметров - блокируется)
Итоговая логика:
| Способ входа | Telegram ID | URL параметры | Результат |
|---|---|---|---|
| Telegram Mini App | ✅ Есть | Любые | ✅ Создается с реальным ID |
| n8n workflow | ❌ Нет | ?source=n8n |
✅ Создается с временным ID |
| Прямая ссылка | ❌ Нет | Нет параметров | ❌ БЛОКИРОВКА |
Backend поддержка:
// app/api/create-user/route.ts
const { telegramId, source } = await request.json();
// Разрешаем n8n переходы
const fromN8n = source === 'n8n' || source === 'chat';
if (!telegramId && !fromN8n) {
return NextResponse.json(
{ success: false, error: 'Telegram ID required' },
{ status: 400 }
);
}
Проверка в production:
# 1. Переход через n8n (должен работать)
curl -X POST https://app.umbrix.net/api/create-user \
-H "Content-Type: application/json" \
-d '{"planType":"trial","source":"n8n"}'
# 2. Переход без параметров (должен блокироваться)
curl -X POST https://app.umbrix.net/api/create-user \
-H "Content-Type: application/json" \
-d '{"planType":"trial"}'
Деплой: PM2 перезапущен (pid 50711), коммит 5677b48 ✅