67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import crypto from 'crypto';
|
|
|
|
interface TelegramUser {
|
|
id: number;
|
|
first_name: string;
|
|
last_name?: string;
|
|
username?: string;
|
|
language_code?: string;
|
|
}
|
|
|
|
interface TelegramInitData {
|
|
query_id?: string;
|
|
user: TelegramUser;
|
|
auth_date: number;
|
|
hash: string;
|
|
}
|
|
|
|
export async function verifyTelegramWebAppData(initData: string): Promise<TelegramInitData | null> {
|
|
try {
|
|
const botToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
if (!botToken) {
|
|
throw new Error('TELEGRAM_BOT_TOKEN is not defined');
|
|
}
|
|
|
|
// Разбираем строку initData
|
|
const searchParams = new URLSearchParams(initData);
|
|
const hash = searchParams.get('hash');
|
|
searchParams.delete('hash');
|
|
|
|
// Сортируем параметры
|
|
const params = Array.from(searchParams.entries())
|
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
.map(([key, value]) => `${key}=${value}`)
|
|
.join('\n');
|
|
|
|
// Создаем секретный ключ
|
|
const secretKey = crypto
|
|
.createHmac('sha256', 'WebAppData')
|
|
.update(botToken)
|
|
.digest();
|
|
|
|
// Вычисляем хеш
|
|
const calculatedHash = crypto
|
|
.createHmac('sha256', secretKey)
|
|
.update(params)
|
|
.digest('hex');
|
|
|
|
// Проверяем хеш
|
|
if (calculatedHash !== hash) {
|
|
return null;
|
|
}
|
|
|
|
// Парсим данные пользователя
|
|
const user: TelegramUser = JSON.parse(searchParams.get('user') || '{}');
|
|
const authDate = parseInt(searchParams.get('auth_date') || '0', 10);
|
|
|
|
return {
|
|
query_id: searchParams.get('query_id') || undefined,
|
|
user,
|
|
auth_date: authDate,
|
|
hash: hash || '',
|
|
};
|
|
} catch (error) {
|
|
console.error('Error verifying Telegram data:', error);
|
|
return null;
|
|
}
|
|
}
|