Telegram-бот для своих: как уйти от комиссий агрегаторов
Что вы получите от этого урока
Вы научитесь создавать Telegram‑бота, который будет принимать заказы и платежи напрямую от клиентов, обходя комиссии крупных агрегаторов (Яндекс Еда, Delivery Club и т.п.). После практики вы сможете:
- Спроектировать простую, но надёжную архитектуру бота.
- Подключить Telegram Payments API и настроить собственный платёжный шлюз.
- Автоматизировать процесс обработки заказов, уведомления кухни и расчётов с курьерами.
- Сэкономить от 10 % до 30 % прибыли, удерживая всё в своих руках.
1️⃣ Почему стоит «вывести» продажи из агрегаторов
| Плюсы агрегаторов | Минусы (комиссии) |
|---|---|
| Широкая аудитория | От 15 % до 30 % от стоимости заказа |
| Маркетинговая поддержка | Ограничения на цены и акции |
| Логистика | Доступ к клиентским данным (email, телефон) |
| Контроль над клиентским опытом | Зависимость от правил платформы |
Если вы уже собрали базу постоянных клиентов (например, через Instagram, сайт или личные рекомендации), переход к собственному каналу продаж даст вам полный контроль и сократит издержки.
2️⃣ Основы работы Telegram Bot API
| Компонент | Что делает | Какой запрос |
|---|---|---|
| BotFather | Создаёт токен доступа | /newbot |
| Update | Принимает сообщения от пользователей | getUpdates (веб‑hook) |
| Message | Текст, фото, кнопки | sendMessage, sendPhoto |
| InlineKeyboard | Кнопки‑выборы (меню, «Добавить в корзину») | reply_markup |
| Payments | Приём и проверка платежей | sendInvoice, preCheckoutQuery |
Аналогия: BotFather – это ваш ключ от офиса, а webhook – почтовый ящик, куда приходят все «письма» от клиентов.
Минимальный набор запросов для бота‑магазина
POST https://api.telegram.org/bot<token>/setWebhook
POST https://api.telegram.org/bot<token>/sendMessage
POST https://api.telegram.org/bot<token>/sendInvoice
POST https://api.telegram.org/bot<token>/answerPreCheckoutQuery
3️⃣ Проектирование пользовательского сценария
- Приветствие – «Добро пожаловать! Что хотите заказать?»
- Выбор категории – кнопки «Суши», «Роллы», «Салаты».
- Выбор продукта – карточка с фото, описанием, ценой, кнопка «В корзину».
- Корзина – список выбранных позиций, кнопка «Оформить заказ».
- Ввод данных – телефон, адрес (если доставка).
- Платёж – отправка инвойса через
sendInvoice. - Подтверждение – «Спасибо! Ваш заказ принят».
Трюк: используйте CallbackQuery вместо обычных сообщений, чтобы не «засорять» чат лишними текстами. Пользователь видит только нужные кнопки, а ваш сервер получает короткий JSON‑payload.
4️⃣ Подключение платёжного шлюза
Telegram поддерживает Stripe, PayPal, YooMoney, а также локальные процессоры (например, Qiwi, Tinkoff). Шаги:
| Шаг | Действие | Примечание |
|---|---|---|
| 1 | Зарегистрировать провайдера в BotFather (/setpaymentprovider) |
Укажите provider_token. |
| 2 | Сформировать инвойс (sendInvoice) |
Укажите title, description, payload, provider_token, prices. |
| 3 | Обработать preCheckoutQuery |
Подтвердите, что всё в порядке (answerPreCheckoutQuery). |
| 4 | Получить successfulPayment |
Сохраните в БД, отправьте уведомление на кухню. |
Пример кода (Python + aiogram)
from aiogram import Bot, Dispatcher, types
from aiogram.utils import executor
TOKEN = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
bot = Bot(token=TOKEN)
dp = Dispatcher(bot)
@dp.message_handler(commands=['start'])
async def start(msg: types.Message):
await msg.answer(
"👋 Привет! Выберите категорию:",
reply_markup=types.InlineKeyboardMarkup().add(
types.InlineKeyboardButton("Роллы", callback_data="cat_rolls")
)
)
@dp.callback_query_handler(lambda c: c.data.startswith('cat_'))
async def show_products(cb: types.CallbackQuery):
# здесь берём список роллов из БД
await cb.message.edit_text(
"🍣 Выберите ролл:",
reply_markup=types.InlineKeyboardMarkup().add(
types.InlineKeyboardButton("Калифорния – 350₽", callback_data="prod_california")
)
)
@dp.callback_query_handler(lambda c: c.data.startswith('prod_'))
async def add_to_cart(cb: types.CallbackQuery):
# добавляем в сессию пользователя
await cb.answer("✅ Добавлено в корзину", show_alert=False)
@dp.message_handler(commands=['checkout'])
async def checkout(msg: types.Message):
await bot.send_invoice(
chat_id=msg.chat.id,
title="Ваш заказ",
description="2 ролла Калифорния",
payload="order_12345",
provider_token="PROVIDER_TOKEN",
currency="RUB",
prices=[types.LabeledPrice("Роллы", 70000)] # в копейках
)
Важно: цены в
LabeledPriceуказываются в копейках (1 RUB = 10000).
5️⃣ Хранение и обработка данных
| Таблица | Поля | Описание |
|---|---|---|
users |
telegram_id, phone, address |
Профиль клиента |
orders |
order_id, user_id, status, total, created_at |
Основная запись заказа |
order_items |
order_id, product_id, quantity, price |
Состав заказа |
payments |
payment_id, order_id, provider, amount, status |
Информация о платеже |
Рекомендация: используйте SQLite для прототипа, а при росте – PostgreSQL + Redis для кэша «корзины».
Транзакция: при получении successfulPayment откройте транзакцию, запишите оплату и сразу измените статус заказа на paid. Это исключит двойные списания.
6️⃣ Автоматизация уведомлений
| Событие | Кому отправляем | Как |
|---|---|---|
| Новый заказ | Кухня (Telegram‑канал) | bot.send_message(chat_id=KITCHEN_ID, text=order_summary) |
| Платёж прошёл | Курьер (бот‑чат) | bot.send_message(chat_id=COURIER_ID, text="Забрать заказ #123") |
| Статус «доставлен» | Клиент | bot.send_message(chat_id=user_id, text="✅ Заказ доставлен") |
Трюк: используйте sendPhoto с подписью, чтобы курьер видел фото готового блюда и мог быстро проверить правильность.
7️⃣ Защита от мошенничества
| Угроза | Мера |
|---|---|
Фальшивый payload |
Сравнивайте с хешем, сгенерированным на сервере (SHA‑256). |
| Дублирование платежа | Сохраняйте payment_id и проверяйте уникальность. |
| Сброс сессии | Храните session_id в Redis с TTL = 15 мин. |
| Перехват токена | Храните BOT_TOKEN в переменных окружения, не в репозитории. |
8️⃣ Аналитика и рост
| Показатель | Как измерять | Что делать |
|---|---|---|
| Конверсия (посетители → заказы) | users → orders |
Улучшить меню, добавить акции. |
| Средний чек | SUM(total)/COUNT(orders) |
Предложить наборы «комбо». |
| Повторные покупки | COUNT(DISTINCT user_id WHERE orders>1) |
Запускать loyalty‑программу. |
| Отказ от оплаты | orders со статусом pending > 30 мин |
Отправить напоминание, предложить скидку. |
Для простого дашборда достаточно Google Data Studio (подключаем к PostgreSQL) или Grafana с Prometheus‑метриками из вашего сервера.
9️⃣ Масштабирование
- Веб‑hook вместо
getUpdates– позволяет обрабатывать запросы в реальном времени. - Пул воркеров (Celery, RQ) – отложенные задачи: отправка писем, расчёт статистики.
- Docker‑контейнеры – упрощают деплой на VPS или облако (DigitalOcean, Hetzner).
- Load‑balancer – если планируется более 10 000 активных пользователей, распределяйте запросы между несколькими инстансами бота.
🔧 Практика для закрепления
- Создайте бота в BotFather, получите токен и установите webhook на ваш локальный сервер (используйте ngrok).
- Смоделируйте меню из трёх роллов, реализуйте кнопку «В корзину» и вывод текущей корзины.
- Подключите платежи через тестовый
provider_tokenStripe. Сформируйте инвойс на 500 RUB и обработайтеsuccessfulPayment. - Запишите заказ в SQLite‑таблицу
ordersи отправьте уведомление в отдельный Telegram‑канал (создайте канал и добавьте бота администратором). - Проверьте безопасность: попытайтесь отправить два одинаковых
successfulPaymentс тем жеpayment_id. Убедитесь, что ваш код отклонит дублирование.
Ответьте на вопросы:
- Какие поля
Invoiceобязательны, а какие можно опустить? - Какой механизм Telegram гарантирует, что пользователь действительно оплатил заказ?
- Как вы будете хранить «корзину», если пользователь закрывает чат и открывает его позже?
🎉 Итоги
- Вы построили полностью автономный канал продаж, избавившийся от комиссий агрегаторов.
- Понимаете, как связать Telegram Bot API, Payments API и базу данных.
- Готовы масштабировать решение и получать аналитические данные для роста бизнеса.
Продолжайте экспериментировать, добавляйте новые функции (рекомендации, бонусные баллы, интеграцию с CRM) и ваш Telegram‑бот станет главным драйвером продаж ваших роллов. Удачи!
БЕСПЛАТНЫЙ КУРС: «КАК НАСТРОИТЬ БЭКАП ФОТО И ДОКУМЕНТОВ»
Чат-эксперимент
Чат онлайн с возможностью отправки гифок
Как настроить мантику для идеального суши
Как правильно подготовить стол для суши: базовые стандарты
Оптимизация производительности Битрикс на VDSina
От идеи до поездки: самостоятельный туризм
Подготовка к ОГЭ: разбор типовых заданий
Практическое руководство: как нарубить лосося для суши
Рисунок стрелок и их подписей
Рулетка онлайн с возможностью играть на числа
Сравнение углеводов в различных сортах риса
Субтитры — не нужны, уши — главные: 5 минут на английский
Трубы и фитинги для нефтеперерабатывающей отрасли
Видео чат Екатеринбург
Заработок $1000 в неделю: как использовать Telegram-кликеры