Интеграция с ботом
Бот — это серверная часть вашего Mini App, обеспечивающая бизнес-логику, авторизацию и взаимодействие с блокчейном. Без бота Mini App — это просто статический фронтенд без бэкенда. Бот обрабатывает webhook-и, валидирует платежи, отправляет уведомления и управляет состоянием пользователя.
Каждое Mini App привязано к боту Telegram. Бот — это серверная сторона: он принимает данные, валидирует авторизацию, обрабатывает платежи и отправляет уведомления. В этом уроке разберём архитектуру взаимодействия бота и Mini App.
Бот как бэкенд
Mini App не может существовать без бота — бот регистрируется через BotFather, и URL Mini App привязывается к нему:
Способы запуска Mini App
1. Menu Button (кнопка меню)
Постоянная кнопка в чате с ботом — пользователь видит её всегда:
// Настройка через BotFather:
// /mybots -> Выбрать бота -> Bot Settings -> Menu Button
// Указать URL Mini App
Контекст: chat_type, chat_instance доступны в initData.
2. Inline Button (кнопка в сообщении)
Кнопка внутри сообщения бота — гибкий вариант для контекстных действий:
// Bot API: отправка сообщения с inline-кнопкой
bot.sendMessage(chatId, 'Откройте приложение:', {
reply_markup: {
inline_keyboard: [[
{
text: 'Открыть Mini App',
web_app: { url: 'https://your-mini-app.com' }
}
]]
}
});
3. Direct Link (прямая ссылка)
Ссылка формата t.me/botname/appname — работает из любого контекста:
https://t.me/your_bot/app_name?startapp=custom_param
custom_param передаётся в initData как start_param — используется для deep linking (открытие конкретного экрана или контента).
4. Keyboard Button (кнопка клавиатуры)
Кнопка в reply-клавиатуре бота:
bot.sendMessage(chatId, 'Выберите действие:', {
reply_markup: {
keyboard: [[
{
text: 'Открыть приложение',
web_app: { url: 'https://your-mini-app.com' }
}
]],
resize_keyboard: true,
}
});
Выбор способа запуска
Menu Button — для основного приложения бота (всегда доступно). Inline Button — для контекстных действий в конкретном сообщении. Direct Link — для шаринга в социальных сетях и мессенджерах. Keyboard Button — для действий в reply-клавиатуре.
web_app_data: отправка данных боту
Mini App может отправить данные обратно боту через sendData():
// В Mini App (frontend)
WebApp.sendData(JSON.stringify({
action: 'order',
items: ['item_1', 'item_2'],
total: 500,
}));
Бот получает эти данные как web_app_data в сообщении:
// В боте (backend)
bot.on('message', (msg) => {
if (msg.web_app_data) {
const data = JSON.parse(msg.web_app_data.data);
console.log('Получено от Mini App:', data);
// { action: 'order', items: [...], total: 500 }
}
});
sendData() закрывает Mini App
Вызов sendData() немедленно закрывает Mini App и отправляет данные боту. Используйте его только для финальной отправки, не для промежуточного состояния. Для общения с бэкендом в процессе работы используйте обычные HTTPS-запросы.
Валидация initData: детальный разбор
Серверная валидация initData — обязательный шаг безопасности. Разберём алгоритм пошагово.
Входные данные
initData = "query_id=AAH...&user=%7B%22id%22...%7D&auth_date=1234567890&hash=abcdef..."
Шаг 1: Парсинг и извлечение hash
# Python pseudocode
import hmac
import hashlib
from urllib.parse import parse_qs
params = parse_qs(init_data)
received_hash = params.pop('hash')[0]
Шаг 2: Формирование data_check_string
Сортируем оставшиеся параметры по алфавиту и объединяем через \n:
# Сортировка по ключу
pairs = sorted(params.items())
# Формирование строки
data_check_string = '\n'.join(
f'{key}={value[0]}' for key, value in pairs
)
# Результат:
# "auth_date=1234567890\nquery_id=AAH...\nuser={...}"
Шаг 3: Вычисление секретного ключа
# Ключ = HMAC-SHA256("WebAppData", bot_token)
secret_key = hmac.new(
b'WebAppData',
bot_token.encode(),
hashlib.sha256
).digest()
Шаг 4: Вычисление и сравнение hash
# Hash = HMAC-SHA256(data_check_string, secret_key)
computed_hash = hmac.new(
secret_key,
data_check_string.encode(),
hashlib.sha256
).hexdigest()
# Сравнение
is_valid = hmac.compare_digest(computed_hash, received_hash)
Шаг 5: Проверка auth_date
import time
auth_date = int(params['auth_date'][0])
now = int(time.time())
# Отклоняем данные старше 1 часа (защита от replay attack)
if now - auth_date > 3600:
is_valid = False
Валидация initData обязательна для продакшена
Без серверной валидации HMAC-SHA256 любой клиент может подделать initData, представившись другим пользователем. Это основа безопасности Mini App.
Когда бот, когда Mini App?
| Задача | Бот (команды) | Mini App |
|---|---|---|
| Простой ответ на вопрос | Команда /help | Избыточно |
| Заполнение формы (3+ полей) | Неудобно | Удобный UI |
| Каталог товаров | Inline-режим | Полноценный интерфейс |
| Оплата | sendInvoice | Stars через openInvoice |
| Дашборд с графиками | Невозможно | Полный React/Vue UI |
| Настройки с переключателями | Неудобно | Нативный интерфейс |
Правило: если действие укладывается в одно сообщение — используйте бота. Если нужен интерфейс — используйте Mini App.
Паттерн: бот + Mini App + TON
Полная архитектура приложения с блокчейн-интеграцией:
Итоги
| Компонент | Роль | Коммуникация |
|---|---|---|
| Бот | Бэкенд, Bot API, уведомления | Bot API (HTTP) |
| Mini App | Фронтенд, UI, UX | initData, sendData, HTTPS |
| Telegram | Платформа, платежи, доставка | WebView bridge |
| Backend | Валидация, бизнес-логика | HTTPS API |
В следующем уроке разберём деплой и продакшен — HTTPS-требования, BotFather, производительность и безопасность.
Частые ошибки
- Не валидируют initData от Telegram на сервере бота: данные можно подделать на клиенте, что позволяет выдавать себя за другого пользователя.
- Хранят BOT_TOKEN в коде фронтенда: токен бота даёт полный контроль над ботом и должен храниться только на сервере.
- Не используют inline-кнопки для запуска Mini App: отправка ссылки текстом выглядит непрофессионально и снижает конверсию.
- Забывают обрабатывать команду /start с параметрами: deep links через бота позволяют открывать Mini App на конкретной странице.
Проверка знанийПочему sendData() не подходит для промежуточного обмена данными между Mini App и бэкендом?
Check Your Understanding
Finished the lesson?
Mark it as complete to track your progress
Войдите чтобы оценить урок