nakama/backend/utils/telegram.js

68 lines
1.8 KiB
JavaScript

const crypto = require('crypto');
const config = require('../config');
const MAX_AUTH_AGE_SECONDS = 5 * 60;
function validateAndParseInitData(initData, req) {
if (!config.telegramBotToken) {
throw new Error('TELEGRAM_BOT_TOKEN не настроен');
}
const params = new URLSearchParams(initData);
const hash = params.get('hash');
const authDate = Number(params.get('auth_date'));
if (!hash) {
throw new Error('Отсутствует hash в initData');
}
if (!authDate) {
throw new Error('Отсутствует auth_date в initData');
}
const dataCheck = [];
for (const [key, value] of params.entries()) {
if (key === 'hash') continue;
dataCheck.push(`${key}=${value}`);
}
dataCheck.sort((a, b) => a.localeCompare(b));
const dataCheckString = dataCheck.join('\n');
const secretKey = crypto.createHmac('sha256', 'WebAppData').update(config.telegramBotToken).digest();
const calculatedHash = crypto.createHmac('sha256', secretKey).update(dataCheckString).digest('hex');
if (calculatedHash !== hash) {
throw new Error('Неверная подпись initData');
}
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - authDate) > MAX_AUTH_AGE_SECONDS) {
throw new Error('Данные авторизации устарели');
}
const userParam = params.get('user');
if (!userParam) {
throw new Error('Отсутствует пользователь в initData');
}
let telegramUser;
try {
telegramUser = JSON.parse(userParam);
} catch (error) {
throw new Error('Некорректный формат user в initData');
}
if (!telegramUser || !telegramUser.id) {
throw new Error('Отсутствует ID пользователя в initData');
}
return { params, telegramUser };
}
module.exports = {
validateAndParseInitData
};