Как я сделал Telegram SuperApp для ресторанов с нуля: WebApp, iiko, WordPress и живой чат в одной системе

Больше года назад я начал замечать одну и ту же картину: ресторан платит агрегатору 20–30% с каждого заказа, не имеет своей базы гостей, не может запустить акцию без согласования с платформой. При этом у каждого руководителя есть Telegram — и он им пользуется каждый день.

Так появилась идея: сделать полноценный ресторанный SuperApp прямо внутри Telegram — без скачивания приложений, без комиссий агрегаторов, с полным контролем данных.

Получилось объёмнее, чем я планировал. В этой статье — честный рассказ о том, что я построил, почему именно так, и какие решения оказались нетривиальными.

Telegram WebApp — почему это работает

Платформа состоит из трёх параллельных процессов:

  • main_admin.py — веб-сервер Flask + Waitress: панель администратора и WebApp API
  • main_bot.py — асинхронный Telegram-бот на python-telegram-bot v20
  • main_jobs.py — планировщик APScheduler: рассылки, синхронизация с iiko, фоновые задачи

Архитектура — «модульный монолит». Каждый модуль живёт в modules//, включается одной строкой в .env, может быть отключён без изменения остального кода.

Что реализовано:

  • booking — бронирование столиков с выбором зала и схемы;
  • menu — интерактивное меню с корзиной и модификаторами;
  • loyalty — бонусная система, уровни, реферальная программа, сертификаты;
  • mailing — рассылки: сегментация, медиа, inline-кнопки, статистика;
  • reviews — сбор и модерация отзывов, ответы из админки;
  • support — live-чат (WebSocket + fallback уведомления в Telegram);
  • metrics — аналитика, NPS-опросы после закрытия брони;
  • iiko — синхронизация меню, стоп-листов и лояльности;
  • wordpress — плагин для WP-сайтов: бронь и отзывы прямо на странице.

Telegram WebApp — почему это работает

Telegram WebApp — это способ открыть веб-страницу прямо в мессенджере. Пользователь видит полноценный интерфейс, никуда не уходит. Авторизация происходит автоматически через Telegram, без паролей и форм.

Для ресторана это означает: гость добавляет бот в контакты один раз и дальше — меню, бронь, история визитов, бонусный баланс — всё в одном месте.

Я реализовал WebApp на чистом Vanilla JS — никаких React/Vue. Причина простая: Telegram WebApp открывается на слабых устройствах, и тяжёлый фреймворк даёт заметный лаг при загрузке. Vanilla JS + правильные HTTP-кеши = мгновенный старт.

iiko — самая сложная часть

iiko — лидер российского рынка POS-систем для ресторанов. У них есть API, но работа с ним требует понимания их модели данных.

Я реализовал три уровня интеграции:

1. Синхронизация меню Получение категорий, блюд, модификаторов и стоп-листов. Главная сложность — стоп-листы обновляются в реальном времени, а у разных заведений они разные. Решение: отдельный APScheduler-джоб, который каждые N минут тянет дельту и обновляет локальный кеш.

2. Синхронизация лояльности Это двусторонний процесс: списание баллов через iiko (при оплате за стойкой) и начисление через бота (за визиты, рефералов). Матчинг пользователей идёт по номеру телефона с нормализацией (российский формат +7/8).

3. Защита от дублей При рестарте джоба синхронизация не должна начислять баллы дважды. Реализован идемпотентный dry-run режим и таблица processed_sync_ids.

WordPress-плагин — неочевидная ценность

Почти у каждого ресторана есть сайт на WordPress. Я написал плагин (PHP), который:

  • Добавляет шорткоды [dakuta_booking_button] и [dakuta_review_button]
  • При нажатии открывает всплывающую форму бронирования/отзыва
  • Форма отправляет данные через WordPress AJAX → наш Flask API
  • API валидирует настройки (часы работы, лимиты гостей, окно дат) и записывает бронь в общую БД

Авторизация между плагином и ботом — HMAC-SHA256 подпись с nonce и TTL. Защита от replay-атак реализована через таблицу использованных nonce с очисткой по TTL.

Это означает: ресторан получает единую базу броней и отзывов и из Telegram, и с сайта.

Live-чат поддержки

Самая сложная часть с точки зрения real-time:

Пользователь открывает WebApp → чат в браузере через Socket.IO. Администратор видит входящий запрос в своей панели и отвечает там же. Всё это — WebSocket через Flask-SocketIO.

Проблема: Telegram WebApp закрывают → юзер уходит из сокета. Как не потерять ответ администратора?

Решение: при разрыве соединения сервер переключается в fallback-режим и отправляет следующее сообщение администратора уже как обычное уведомление в Telegram-бот пользователя.

Для надёжной детекции разрыва уменьшен ping_interval до 10 сек и ping_timeout до 15 сек (дефолтные значения Socket.IO слишком медленные для мобильных браузеров).

Модульность: как это устроено изнутри

Каждый модуль — стандартная структура:

modules/booking/ ├── __init__.py # setup(): регистрирует Blueprint, создаёт таблицы ├── admin.py # Flask Blueprint для панели администратора ├── database.py # SQL-запросы, бизнес-логика ├── handlers.py # Telegram-обработчики ├── services.py # Фоновые сервисы (напоминания, авто-статусы) ├── templates/ # HTML для WebApp и Admin └── static/ # CSS/JS для этого модуля

Ядро (core/loader.py) при старте сканирует папку modules/, вызывает setup() у каждого активного модуля. Модуль сам регистрирует свои Blueprint'ы и обработчики.

Это позволяет добавить новый модуль без изменения ядра: создаёте папку, пишете init.pyсsetup(), добавляете в ENABLED_MODULES — и он работает.

Что я бы сделал иначе

SQLite → PostgreSQL раньше. SQLite отлично работает в WAL-режиме для одного заведения. Но как только появляется несколько одновременных пишущих процессов — нужен PostgreSQL. Я написал запросы на чистом SQL без ORM специально для облегчения миграции, но сам переход всё равно потребует времени.

Реальный очередь для уведомлений. Сейчас рассылки и уведомления идут через APScheduler. Для надёжности лучше RabbitMQ или Redis Queue. Для одного заведения — хватает. Для SaaS-платформы с сотнями клиентов — нет.

Тесты с самого начала. Smoke-тесты появились уже на финале. В следующий раз начну с тест-фикстур.

Итог

Система получилась рабочей и использует её в качестве основы. Архитектурные решения — модульность, отдельные процессы, чистый SQL, Vanilla JS — были осознанными компромиссами между скоростью разработки и возможностью поддержки.

Если вы работаете в HoReCa или занимаетесь автоматизацией ресторанов — буду рад обсудить как технические детали, так и опыт интеграции с iiko.

Видеодемо системы (5 минут):

Telegram-платформа для HoReCa

Вопросы — в комментариях или Telegram: @dakutacanmore12

2 комментария