Демо-проект

Магазин в Telegram Mini App: TemplateForge

Витрина внутри мессенджера, оплата звёздами, выдача товара ботом.

разработка витрины и бота · Go · Next.js 15 · TypeScript · Tailwind · Zustand · Telegram Bot API · Telegram Stars

в работеВитрина не опубликована, живого прогона покупки ещё не было

10шаблонов в каталоге, четыре раздела
5 экрановпуть покупателя от каталога до выдачи
1 звездасчёт за любой заказ, возврат сразу
4 проверкизаказа перед списанием звезды
без дублейповторная оплата не выдаст товар дважды
Первый экран демо: Магазин в Telegram Mini App: TemplateForge

Задача

TemplateForge продаёт готовые шаблоны Notion. У магазина уже есть обычный сайт; задача этого проекта - тот же каталог внутри Telegram, чтобы покупатель не выходил в браузер и не вводил карту. Товар цифровой: десять шаблонов в четырёх разделах, доставка ссылкой. Оплата - Telegram Stars: для них не нужен ни платёжный провайдер, ни договор с банком, что снимает главный порог для одиночного продавца.

Демо-проект: компания и товары вымышлены, платежи демонстрационные. Счёт всегда выставляется на одну звезду независимо от суммы корзины, и звезда возвращается сразу после оплаты. Это сказано покупателю трижды - в приветствии бота, в описании счёта и в сообщении после покупки.

Решение

Две части: витрина как Telegram Mini App на Next.js со статическим экспортом и сервис на Go, в котором живут бот и http-часть для витрины.

  • Путь покупателя целиком внутри мессенджера: каталог с фильтром по категориям и счётчиками, карточка товара с галереей экранов, составом и отзывами, корзина, выбор способа оплаты, экран выдачи. Пять экранов; шестой, страница-дисклеймер, доступен с любого из них.
  • Нижняя кнопка - родная MainButton Telegram: она же добавляет товар, ведёт в корзину и запускает оплату. Вне Telegram витрина рисует на том же месте свою кнопку, поэтому страницы открываются и в обычном браузере - иначе с них не снять кадры и не отладить.
  • Оплата собрана так: витрина просит у бота ссылку на счёт, Telegram открывает счёт поверх приложения, бот перепроверяет заказ перед списанием, после оплаты присылает шаблоны сообщением и тут же возвращает звезду. Если в настройках задан чат владельца, туда уходит карточка покупки.
  • Рублёвая оплата картой на экране есть, но неактивна, с честной подписью «Появится после договора с провайдером платежей». Интерфейс не обещает того, чего пока нет.
  • Пока витрина не опубликована, всю механику покупки закрывает команда /demo: бот собирает демо-корзину, выставляет счёт прямо в чате, выдаёт шаблоны и возвращает звезду. Это разобрано тестами; живьём, за настоящую звезду, ещё не прогонялось.

Детали, которые легко не заметить

  • Данные входа, которые Mini App присылает боту, проверяются подписью по спеке Telegram и имеют срок годности. Это и есть защита эндпоинта счёта: без неё кто угодно попросил бы счёт от чужого имени. Отдельно CORS ограничен адресами витрины из настройки - чужой сайт в браузере покупателя ответ не прочитает.
  • Цена копируется в заказ в момент его создания: правка каталога не переписывает задним числом уже выставленный счёт. Перед списанием бот проверяет заказ четырьмя способами - заказ найден, ещё не оплачен, товары на месте и цены не разъехались, сумма и валюта сходятся. На весь ответ Telegram даёт десять секунд, поэтому проверки короткие и локальные.
  • Дважды за один заказ товар не выдаётся: повторная оплата отсекается проверкой перед списанием, а повторная доставка уведомления об оплате упирается в идентификатор списания - и звезда не возвращается дважды.
  • Заказ, оплата и возврат пишутся построчно в файл-журнал. Базы нет намеренно: постоянного состояния три вида, файл переживает перезапуск, читается глазами и не требует контейнера в тестах.
  • Токен бота не печатается нигде - ни в логах, ни в текстах ошибок. За этим следят отдельные тесты: адрес запроса к Telegram содержит токен целиком, и необработанная ошибка утащила бы его в лог.
  • Отказы покупателю написаны целыми фразами по-русски - «Каталог изменился, пока оформлялся заказ», - а технические подробности остаются в логе.
  • Демо закрыто от поиска: noindex в метаданных и заголовком, отдельная страница-дисклеймер, ссылка на неё на каждом экране. Ссылки выдачи ведут на домен .demo, который не делегирован, - открыть по ним нечего.
  • Стык витрины с ботом проверяется без Telegram: отдельная команда поднимает настоящий http-слой с подставным выставителем счетов, и расхождение в адресе или именах полей видно сразу.

Цифры

Десять шаблонов в четырёх разделах, счётчики в фильтре сходятся с каталогом. Витрина - шесть экранов: пять в пути покупки и страница-дисклеймер. Счёт всегда на одну звезду, четыре проверки заказа перед списанием, три вида записей в журнале: заказ, оплата, возврат.

Что осталось

Живого прогона внутри Telegram - купить за звезду, получить товар, увидеть возврат в «Моих звёздах» - ещё не было: механика закрыта тестами, но настоящей покупки никто не совершал. Витрина не опубликована, поэтому ссылки на живое демо здесь нет: Telegram открывает Mini App только по https, и публичный адрес - следующий шаг. Рублёвая оплата картой ждёт договора с ЮKassa: обработка счёта в рублях будет дописана после него.