Кейсы
Telegram-бот AI-агент Автоматизация

AI-бот с подпиской в MAX: GPT-4o, ЮKassa и 54-ФЗ за 10 дней

Подписочный SaaS внутри MAX: GPT-4o, веб-поиск, ЮKassa с 54-ФЗ, авто-продление, админка и cron-логика жизненного цикла.

2026 4 мин. чтения
Клиент AI-бот в MAX
Срок 10 дней
Стек Node.js 20 · TypeScript · Express · Prisma · PostgreSQL
Результат Production-продукт на iiibt.ru: от /start до оплаченной подписки — 30 секунд, email-чек, авто-продление через 30 дней, админ видит метрики и транзакции в MAX.
  • вручную авто + email
    Фискализация чеков 54-ФЗ
  • 4 Cron-задачи жизненного цикла подписки
  • 71 Автотест бизнес-логики

Проблема

Проблема

Запрос: не MVP-прототип, а полноценный SaaS внутри мессенджера MAX — с платной подпиской, налоговыми чеками по 54-ФЗ, авто-продлением и админкой. Всё, что есть у взрослых продуктов — но в закрытой экосистеме без привычных инструментов.

Задача

Клиент пришёл с запросом построить полноценный подписочный AI-бот в российском мессенджере MAX. Не MVP, не «тест идеи», а production-продукт: оплата картой или СБП, налоговые чеки по 54-ФЗ на email, авто-продление через 30 дней, напоминания об окончании, админка с метриками. Всё, что есть у взрослых SaaS — но внутри закрытой экосистемы, где нет привычных инструментов и обширной документации.

Сложность: MAX — относительно новая платформа, long polling вместо вебхуков, слабая публичная документация Bot API, нет готовых библиотек для интеграции с ЮKassa под MAX-контекст. Нужно было собрать production-стек с нуля и за разумные сроки — без права на «потом допилим».

Решение

1. MAX Bot API через long polling

Бот работает через long polling — постоянный блокирующий GET-запрос к MAX API. Выбор в пользу polling, а не вебхука: не нужно разворачивать публичный endpoint для бота, проще локальная отладка, Express используется только для вебхуков ЮKassa и статики.

Все сообщения проходят через единый обработчик message_created → троттлинг 3 секунды → сохранение в сессию → вызов LLM → ответ. Команды (/start, /new, /history, /status, /subscribe, /cancel, /admin) обрабатываются отдельным роутером.

2. GPT-4o через OpenRouter с веб-поиском

Запросы к LLM идут через OpenRouter — OpenAI-совместимый шлюз, который поддерживает десятки моделей. По умолчанию работает openai/gpt-4o, но модель можно менять через переменные окружения без деплоя. Включён встроенный веб-поиск через openrouter:web_search: когда пользователь спрашивает про актуальные события, бот подтягивает свежие данные с источниками.

Контекст передаётся последними 100 парами сообщений — достаточно для связного диалога, не взрывает токены.

3. Память диалогов и лимиты

Каждая сессия — отдельная запись в PostgreSQL с массивом сообщений в формате JSON. Пользователь может:

  • Продолжать текущий диалог (память сохраняется между сообщениями).
  • Начать новый /new — старая сессия остаётся в истории.
  • /history — последние 10 непустых диалогов с возможностью вернуться к любому.

Лимиты считаются в символах (input + output): 4 000 символов/день на бесплатном тарифе, 150 000 на платном. Сброс каждый день в 00:00 МСК через cron. Учёт и input, и output — чтобы нельзя было обойти лимит короткими промптами и длинными ответами.

4. ЮKassa, 54-ФЗ и авто-продление

Оплата через ЮKassa — карты, СБП, банковские переводы. Стоимость подписки — 70 ₽/мес, срок — 30 дней.

Фискализация 54-ФЗ. Перед оплатой бот запрашивает email пользователя. В метаданные платежа передаётся состав чека (наименование услуги, сумма, НДС, email получателя) — ЮKassa формирует фискальный чек и сама отправляет его на почту. Никаких сторонних сервисов чеков.

Вебхук с двойной проверкой. POST /api/yookassa/webhook валидирует IP источника (allowlist ЮKassa из SDK), затем перезапрашивает статус платежа напрямую в API ЮKassa — чтобы исключить подделку. Идемпотентность обеспечена уникальным yookassaId в таблице транзакций.

Авто-продление. Если у способа оплаты есть сохранённый payment_method_id (карта, не СБП), cron в 00:01 МСК списывает следующий период за 24 часа до истечения текущей подписки. Если платёж не прошёл — подписка деактивируется в 00:10, пользователь получает уведомление.

5. Cron-оркестрация жизненного цикла

Четыре задачи, все в таймзоне Europe/Moscow:

ВремяЗадача
00:00Сброс дневных лимитов всем пользователям
00:01Авто-продление подписок, истекающих в ±24ч
00:10Деактивация истёкших подписок
09:00Напоминания об окончании (за 3 дня, не чаще раза в 2 дня)

Порядок важен: сброс лимитов → попытка продлить → деактивация неоплаченных → утренние напоминания. Авто-продление идемпотентно, повторный запуск не создаёт дубликаты транзакций.

6. Админ-панель прямо в боте

Команда /admin (доступна только пользователям с флагом isAdmin) открывает мини-панель внутри MAX:

  • Статистика — всего пользователей, активных подписок, оборот.
  • Список пользователей — пагинация по 10, сортировка по дате.
  • Карточка пользователя — email, тариф, последние 10 транзакций, общая сумма платежей.

Первые админы задаются через переменную ADMIN_MAX_USER_IDS в .env — список maxUserId через запятую. Флаг обновляется при каждом взаимодействии (upsert), так что новых админов можно добавлять без перезапуска.

7. Деплой и надёжность

Весь бот — один Node.js-процесс: Express + MAX long polling + cron + Prisma pool. Монолит оправдан: cron требует единственного инстанса, горизонтальное масштабирование усложнило бы архитектуру без выигрыша.

Graceful shutdown: SIGTERM → остановка cron → остановка бота → закрытие HTTP → дисконнект Prisma. Никаких брошенных платежей и оборванных диалогов.

Docker Compose: два контейнера (bot + postgres), volume для БД, рестарт unless-stopped. Nginx с Let’s Encrypt на хосте, SSL обновляется certbot автоматически. 71 автотест бизнес-логики через Vitest с моками Prisma — тесты не требуют реальной БД.

Результат

Production-бот на iiibt.ru: пользователь пишет /start, за 30 секунд оформляет подписку, получает фискальный чек на email. Через 30 дней подписка продлевается автоматически — или деактивируется, если оплата не прошла. Админ в том же MAX видит метрики, пользователей и транзакции.

10 дней от первого коммита до production. Полноценный SaaS внутри закрытой экосистемы, без компромиссов в архитектуре или соответствии российскому законодательству.

Технологии Node.js 20 TypeScript Express Prisma PostgreSQL MAX Bot API OpenRouter GPT-4o YooKassa Docker Nginx
Итог

Production-продукт на iiibt.ru: от /start до оплаченной подписки — 30 секунд, email-чек, авто-продление через 30 дней, админ видит метрики и транзакции в MAX.

Следующий кейс

Офлайн-конверсии Bitrix24 → Яндекс Метрика: лиды привязаны к рекламе

Интеграция CRM и аналитики для юридической компании: смена статуса лида в Битрикс24 автоматически фиксируется как конверсия в Яндекс Метрике — без сервера, через b242ya.