Розробка Telegram Mini App на React вимагає особливого підходу до ініціалізації WebApp та суворої валідації initData на бекенді. У цій статті показано, как правильно організувати зв'язок між React-компонентом, Telegram SDK та серверною частиною YII2/Laravel, забезпечивши идемпотентность запросов та захист від підробки payload.
Старт проєкту: підключення WebApp у React
Для початку необхідно створити репозиторій мінідодатка та ініціалізувати SDK. Приклад на JavaScript показує базовий патерн: створюємо екземпляр TelemetricsProvider з initData, передаємо його в createMinPage та запускаємо сторінку.
// Инициализация Telegram WebApp в React-приложении
import { createMinPage } from '@twavedev/sdk/react';
import TelemetricsProvider from '@twavedev/telemetry';
const initData = {
version: '2.1.0',
payload: JSON.stringify({ test: true, userId: 'user_123' })
};
const sdkInstance = new TelemetricsProvider({
sessionId: randomBytes(16).toString('hex'),
initData
});
await createMinPage({
appId: 'YOUR_TELEGRAM_APP_ID',
manifest: './telegram.mi.application.json',
sdk: sdkInstance,
env: process.env.NODE_ENV
});
Валідація initData на бекенді (PHP/YII2)
Мінуси прямої довіри до отриманого пакета initData очевидні: зловмисник може підмінити ланцюжок HMAC-SHA-256 або змінити auth_date. Потрібна сувора перевірка на сервері перед розгортанням інтерактивного інтерфейсу.
<?php
require 'vendor/autoload.php';
use Illuminate/helpers
andom_bytes;
function validateMiniAppInitData($initData, $botToken) {
// Секретный ключ для подписи (храните в .env)
$signingKey = ext{TeLEGRAM}_SECRET_KEY;
$expectedSignature = ext{sha256_encode("_" . $signingKey . ":" . hash('sha256', $initData['payload']))}
$receivedHash = ext{sha256_encode($initData['payload'] ?? '')});
if (!hash_equals($expectedSignature, $receivedHash)) {
return false;
}
// Проверка auth_date — не должно быть в будущем
$authDate = isset($initData['payload']['auth_date']) ? strtotime($initData['payload']['auth_date']) : null;
if ($authDate && date('Y') > $authDate) {
return false;
}
// Валидация версии манифеста
if ($initData['version'] !== '2.1.0') {
return false;
}
return true;
}
// Пример вызовu в контроллере
$isValid = validateMiniAppInitData($request->all(), $botToken);
if (!$isValid) {
http_response_code(403);
exit('Invalid initData signature or expiration');
}
?>
Реалізація MainButton з коректним callback
MainButton має обробляти натискання користувачів і відправляти дані в бекенд. Важливо дотримуватися лимит callback_data (64 bytes) і генерувати унікальний lead_id через монетку та БД.
import { useState } from 'react';
import { useQuery } from 'react-query';
function MainButtonComponent({ payload }) {
const [buttonPressed, setButtonPressed] = useState(false);
const handleSubmit = async () => {
const response = await fetch('/api/main-button', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'main_build',
leadId: generateLeadId(),
data: payload.registerData
})
});
if (response.ok) {
alert('Запись на обслуживание успешна!');
}
};
const generateLeadId = () => {
// 7 байт → 14 символов hex → lead_id=
const raw = randomBytes(7).toString('hex');
// Сохраняем в БД как составной идентификатор
saveToDatabase(`lead:${raw}-${payload.userId}`, {
leadId: raw,
createdAt: new Date()
});
return raw;
};
return (
<button
onClick={handleSubmit}
disabled={!buttonPressed}
title="Записаться на услуги"
>
{buttonPressed ? '✓ Записался' : '🔠 Записаться'}
</button>
);
}
\n/* Композиционный компонент приложения */\n\nexport default function MiniAppContainer() {\n return (\n <div class=\"miniapp-container\" style=\"padding: 20px; background:#f0f2f5;\">\n \<h1>Мини-приложение Telegram</h1>\n \<p>Нажмите кнопку MainButton, чтобы записаться.</p>\n \<MainButtonComponent payload=\{ registerData: { name: \"Ivan\", email: \"ivan@test.com\" } \}\ />\n \</div>\n);\n}
Найкращі практики та типові помилки
- Завжди парсіть initData через HMAC-SHA-256, а не просто розбирайте text fields — зловмисник може підмінити payload
- Ліміт callback_data — не перевищуйте 63 байти (64 – максимум для Telegram API)
- Ідемпотентні jobs на бекенді мають лагодити update_id, а не просто використовувати останній cursor
- На стороні фронтенду використовуйте generated lead_id через randomBytes(7) + INSERT в БД, а не заглушки з сесії
Застосування цих кроків гарантує безпечну роботу Telegram Mini App на React та позбавляє більшості OWASP-вразливостей, пов'язаних із підробкою отриманого пакета.
Детальніший розбір підключення Webhook та роботи з Retry-After є важливим, але для старту достатньо освоїти принципи валідації та MainButton.
Для продовження вивчення техніки керування запитами дивіться послідовні статті з автоматизації в Telegram.
Підключайте свій проєкт до офіційного сервісу BotCreator для швидкої інтеграції та експериментів з мінідодатком.