Telegram Mini App на Vue 3 открывает возможности для создания конкурентоспособного интерфейса прямо внутри Telegram, минуя классический чат. В отличие от обычного бота, Mini App работает как веб-приложение с собственным viewport, что позволяет использовать все функциональность JavaScript и даже выполнять локальные операции.
Подключение WebApp JS через Official SDK
Для начала интеграции необходимо подключить Telegram WebApp SDK. В Vue 3 это реализуется через реактивный компонент, который инициализирует WebApp в момент загрузки страницы или после получения callback_data.
// Vue 3 компонент для инициализации Telegram Mini App
import { reactive, onMounted } from 'vue';
import * as WebAppSDK from 'telemetry-web-apps-js';
export default {
setup() {
const containerEl = reactive({
initialState: {},
isInitialized: false
});
async function initializeWebApp(botToken) {
const client = WebAppSDK();
try {
await client.initialize({
url: `https://api.telegram.org/bot${encodeURIComponent(botToken)}`,
version: '8.1',
config: {
actionType: 'set_viewport',
viewport: {
width: 360,
height: 640
}
}
});
console.log('Mini App успешно инициализирован');
containerEl.isInitialized = true;
} catch (error) {
console.error('Failed to initialize WebApp:', error);
}
}
onMounted(() => {
// Инициализируем при загрузке компонента
initializeWebApp(process.env.BOT_TOKEN);
});
return { containerEl, isInitialized };
}
};
Deep Linking с t.me/Bot?start=
При обработке входящего запроса от Telegram важно правильно парсить t.me/Bot?start=payload. Payload должен соответствовать максимальному лимиту в 64 байта. В нашем случае используется уникальный lead_id, генерируемый на стороне бота, чтобы избежать конфликтов при параллельной работе нескольких экземпляров приложения.
Безопасная передача данных через sendData
После инициализации WebApp бот может отправлять пользователям данные через sendData-операцию. Этот механизм предполагает передачу JSON-объекта от бота к приложению. Критически важно валидировать received data на сервере перед сохранением.
// PHP валидация initData на сервере (PHP/Yii2)
<?php
function validateTelegramInitData($initDataString, $botToken) {
// Декодируем base64-строку из initData
$decoded = base64_decode($initDataString, true);
// Получаем хэш подписи (HMAC-SHA256)
$expectedSignature = hash_hmac('sha256', $decoded, $botToken);
// Вычисляем ожидаемую подпись от бота
$computedSignature = hash('sha256', $botToken . $decoded);
// Проверяем корректность сигнатуры
if ($computedSignature !== $expectedSignature) {
return ['error' => 'Invalid signature'];
}
// Проверяем наличие auth_date и проверку свежести (30 минут)
if (!isset($decoded['auth_date'])) {
return ['error' => 'Missing auth_date'];
}
$date = pdtoTimestamp($decoded['auth_date']);
if (time() - $date > 300) { // 5 минут window
return ['error' => 'Session expired'];
}
return ['ok' => true];
}
// Пример вызова перед отправкой данных
$result = validateTelegramInitData($_REQUEST['init_data'], $BOT_TOKEN);
if (!in_array($result['ok'], [true])) {
http_response_code(400);
exit(json_encode(['error' => $result['error']], JSON_THROW_ON_ERROR));
}
// После успешной валидации отправляем данные в mini app
$transaction = ['type' => 'create', 'data' => $userRegistered];
$response = file_get_contents($WP_INSTALLED_PLUGIN_DIR . '/telegram_send.php')
->json_decode(file_get_contents("https://api.telegram.org/bot${BOT_TOKEN}/sendMessage", True));
echo $response->get('messageId');
// PHP конфиг для отправки (Yii2)
<?php
/**
* Консольная команда для обслуживания Telegram-бота
*/
class ManagerController extends Controller {
public function index() {
// Set webhook
yii
base::setWebhook(
$url => "https://yourdomain.com/bot/webhook",
secret_token => "_TELEGRAM_SECRET_TOKEN"
);
// Получить ID обработанного сообщения
$updateId = $this->getLastUpdateId();
// Удалить вебхук, если он больше не нужен
if ($updateId) {
yii
base::deleteWebhook($updateId);
}
// Получить текущего владельца обновления
$leadId = $this->getLeadFromUpdateId($updateId);
echo sprintf(
"Server status\n- Last update ID: %s\n- Lead ID: %s\n",
$updateId ?? 'N/A',
$leadId ?: 'N/A'
);
}
protected function getLastUpdateId() {
// В реальном проекте используем session или DB
return $_SESSION['last_update_id'] ?? null;
}
protected function getLeadFromUpdateId($updateId) {
// Логика извлечения lead_id из update
return 'lead_' . substr($updateId, 20, 5);
}
}
<?php
Идемпотентность и защиту от спуфинга
Каждый запрос от Telegram Mini App подписывается HMAC‑средством bot token. Это гарантирует, что данные не могут быть изменены злоумышленником между отправкой и обработкой. Кроме того, идемпотентность достигается сохранением last_update_id в базе данных — при повторной отправке одного и того же payload'а система просто перезаписывает результат вместо дублирования.
Рекомендации по best practices
- Всегда декодируйте initData с использованием base64_decode с флагом true для безопасности.
- Храните secret_token (webhook secret) в защищённой переменной окружения, никогда не вставляйте его в коде.
- Валидируйте auth_date — отклоняйте данные, связанные со старыми сессиями (>5 минут).
- Используйте cURL для HTTP-запросов к Telegram API с проверкой HTTP-кода и json_last_error.
Следуя описанным шагам, вы сможете построить стабильный Telegram Mini App на Vue 3 с надёжной отправкой данных и защитой от несанкционированных действий.