Telegram Mini App на Vue 3: інтеграція WebApp JS та ідемпотентне надсилання даних

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 з надійною відправкою даних та захистом від несанкціонованих дій.

Нові статті — у Telegram

Розбираємо, що автоматизувати в бізнесі та як це працює на практиці. Без спаму.