Оплата в Telegram-боте устроена так: бот не принимает деньги сам, а просит ваш backend создать платёж и присылает пользователю кнопку со ссылкой. Человек платит через СБП или картой, ваш сервер получает подписанное событие и в ту же секунду выдаёт то, что купили, — файл, ключ, инвайт в закрытый канал.
Такая схема нужна ботам-магазинам, ботам с подписками и доступом к сообществам, сервисам бронирования и мастерам, которые продают консультации прямо в переписке. Ниже — что придётся решить до кода, сколько времени займёт запуск и какие грабли ждут после сотого платежа.
Stars или внешняя оплата: что вам подойдёт
Telegram требует продавать цифровое содержимое внутри своего интерфейса за Stars: доступ к каналу, платные посты, внутренние функции самого бота. Внешние платёжные ссылки в этих сценариях использовать нельзя, и обход правил заканчивается блокировкой бота.
Внешняя оплата остаётся штатным путём там, где товар живёт за пределами Telegram: физическая доставка, вебинар на своей платформе, лицензия к десктопной программе, услуга офлайн, аккаунт в вашем SaaS. Разбор пограничных случаев — в материале Stars или внешняя оплата.
Определитесь с этим до вёрстки меню бота. Переезд между Stars и внешней оплатой задним числом означает переделку каталога, кнопок и логики выдачи.
Из чего собирается оплата в боте
Частей ровно три, и путать их зоны ответственности не стоит.
| Часть | За что отвечает | Чего никогда не делает |
|---|---|---|
| Бот | Показывает каталог, собирает выбор, отправляет кнопку с оплатой, доставляет товар | Не хранит секреты и не решает, оплачен ли заказ |
| Backend | Считает цену, создаёт платёж, принимает колбэк, ведёт заказы | Не доверяет данным, пришедшим из сообщения пользователя |
| Платёжный сервис | Показывает форму оплаты, проводит деньги, присылает событие | Не знает вашей бизнес-логики и не выдаёт товар за вас |
Ошибка новичков — держать всю логику в обработчике callback_query. Пока товаров пять, это работает; на тридцати позициях и промокодах бот превращается в клубок, где цена вычисляется в трёх местах по-разному.
Путь покупателя: от команды до выдачи
- Пользователь жмёт «Купить». Бот отвечает карточкой товара и кнопкой подтверждения — на этом шаге ничего в базе ещё не меняется.
- Backend создаёт заказ. Строка в
orders: telegram user id, артикул, цена,status = pending, номер видаtg-4711. - Backend создаёт платёж. В ответе приходит
pay_url, бот отправляет его кнопкой вида «Оплатить 990 ₽». - Человек платит. Ссылка открывается в браузере телефона, дальше — приложение банка и возврат обратно в чат.
- Приходит колбэк. Backend меняет статус и просит бота отправить товар.
Между шагами 4 и 5 пользователь обязательно вернётся в чат раньше, чем придёт событие. Поставьте туда кнопку «Проверить оплату», которая читает статус из вашей базы: это снимает половину обращений в поддержку.
Код: создание платежа и обработка события
Платёж создаётся одним запросом. Заголовок X-API-Key — ключ кассы, X-Nonce — уникальный UUID на каждый запрос, он живёт 10 минут; при повторе того же значения вернётся 401 nonce already used.
POST /api/v1/payments
X-API-Key: <ключ кассы>
X-Nonce: 8b0d4f31-2c77-4b5f-a1de-6c9e30f47aa2
{
"amount": "990.00",
"payment_currency": "RUB",
"order_id": "tg-4711",
"description": "Набор пресетов Winter",
"customer_id": "tg:582931044",
"metadata": {"chat_id": 582931044, "sku": "preset-winter"}
}
Поле metadata вернётся в колбэке без изменений — кладите туда chat_id, чтобы не искать покупателя по сумме и времени. Колбэк приходит на ваш callback_url с заголовком X-Signature: это HMAC-SHA256 hex от строки X-Timestamp + "." + сырое тело запроса на ключе signing_secret. Считайте подпись до разбора JSON и сравнивайте constant-time. События бывают трёх типов: payment.paid, payment.canceled, payment.expired.
Выдача доступа: инвайт, ключ, файл
Самый частый товар в ботах — доступ в закрытый канал. Выдавайте его персональной одноразовой инвайт-ссылкой с ограничением на одно использование, а не общей ссылкой из настроек канала: общую перешлют друзьям в тот же вечер.
Файлы и ключи отправляйте из очереди, а не прямо в обработчике колбэка. Telegram иногда отвечает ошибкой сети или лимитом на отправку, и если из-за этого ваш endpoint вернёт 500, сервис будет повторять доставку события, а покупатель останется без товара. Правильный порядок: подтвердили приём, записали задачу, отправили.
Подписки требуют отдельного поля с датой окончания. Продление — это новый платёж с новым order_id, а не редактирование старого; иначе история оплат перестанет сходиться уже на третьем месяце. Механика разобрана в статье об оплате подписки в боте.
Что ломается на сотом платеже
- Двойная выдача. Колбэк доставлен дважды, бот отправил два ключа. Лечится проверкой текущего статуса заказа перед выдачей.
- Два платежа на один заказ. Пользователь нажал кнопку трижды. Идемпотентность создания платежа работает по
order_id— не генерируйте новый номер на каждый клик. - Просроченные ссылки. У платежа есть
expires_at; человек открыл кнопку через сутки и увидел ошибку. Дайте команду «Оплатить снова», которая создаёт свежий платёж. - Секреты в коде бота. Ключ кассы и
signing_secretживут в переменных окружения, а исходники ботов слишком часто уезжают в публичные репозитории. - Нет журнала событий. Без таблицы входящих колбэков спор «деньги списались, товара нет» разбирается вручную и долго.
Как проверить бота до первых клиентов
Проведите одну реальную покупку на минимальную сумму со своего телефона — целиком, от команды до получения товара. Половина проблем видна именно здесь: кнопка не открывается в мобильном браузере, сообщение с товаром приходит раньше подтверждения, сумма в чате не совпадает с суммой в форме.
Дальше проверьте неприятные ветки. Закройте страницу оплаты, не заплатив, и убедитесь, что заказ остался в pending, а бот не отправил ничего лишнего. Отправьте себе тот же колбэк дважды и посмотрите, придёт ли товар два раза. Наконец, дождитесь expires_at и проверьте, что старая кнопка не оживает.
Полезная привычка — писать в лог каждое входящее событие вместе с payment_id и результатом обработки. Когда через месяц придёт первое «я оплатил, ничего не пришло», разбор займёт минуту вместо вечера. Практические сценарии проверки собраны в статье о тестовом режиме платежей.
Сколько времени займёт запуск
Бот-магазин пресетов на 12 позиций собирается за полтора дня разработчика: полдня на каталог и заказы, полдня на платежи и колбэк, ещё полдня на тесты с реального телефона. Отдельно закладывайте модерацию: категорию проекта, доступные способы оплаты и условия подтверждают до запуска.
Подготовьте заранее описание того, что продаёте, ссылку на бота и правила возврата. Обязанности продавца платёжный сервис не забирает: чек, налог и общение с покупателем остаются на вас. Самозанятый формирует чек в приложении «Мой налог» и держит в уме годовой лимит 2,4 млн ₽, ИП работает со своей кассой. Если хочется сначала проверить спрос, стартуйте с ссылок на оплату и добавьте API, когда пойдут первые продажи.