LAB Обсудить задачу
00

Журнал

Как принимать оплату в Telegram-боте

· 11 мин чтения

01

Бот сам деньги не принимает. Деньги принимает платёжный сервис, а бот выставляет счёт, ждёт подтверждения от сервиса и после него выдаёт то, за что заплатили. Разбираем весь путь: от кнопки «купить» до возврата и до вопроса, кому и когда оплата в боте вообще не нужна.

Что на самом деле происходит, когда «бот принимает оплату»

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

Из этого следуют два практических правила, которые определяют всю остальную конструкцию.

  • Реквизиты карты человек вводит на стороне платёжного сервиса - на его странице или в его форме. Не в чате, не в сообщении боту, не в мини-приложении, которое само собирает номер карты. Просить номер карты в переписке нельзя ни при каких условиях.
  • Факт оплаты бот узнаёт от сервиса, а не от покупателя. Всё, что покупатель говорит о своей оплате, - это его версия событий. Она бывает верной, но проверять её должна машина.

Соответственно, задача разработки сводится не к «научить бота брать деньги», а к тому, чтобы связать три вещи: заказ на нашей стороне, платёж на стороне сервиса и выдачу товара или доступа.

Способы принять деньги: четыре рабочих варианта

Перевод по реквизитам вручную

Самый частый старт. Человек пишет в бот или в директ, ему присылают номер карты или счёт, он переводит и присылает скриншот. Дальше кто-то живой сверяет поступление и выдаёт доступ.

Это работает, пока продаж мало и владелец физически успевает. Ломается предсказуемо: ночью никто не отвечает, скриншоты копятся, суммы путаются, человек уже заплатил и ждёт, а очередь до него дойдёт утром. Ровно с такой точки начинался наш кейс с онлайн-курсом: продажи шли через Instagram, и каждую покупку вели руками - ответить в директе, дождаться перевода, проверить, добавить в закрытый канал.

Ссылка на оплату от платёжного сервиса

Бот обращается к API платёжного сервиса, создаёт платёж и получает ссылку. Человек нажимает кнопку, открывается страница оплаты, там он платит картой или другим доступным способом. Сервис присылает уведомление о результате на наш адрес.

Универсальный вариант: одна и та же интеграция обслуживает и сайт, и бота, способы оплаты определяются сервисом, а не мессенджером. Именно по такой схеме работает бот из кейса Карины - платежи принимает платёжный сервис, а бот ведёт человека по сценарию.

Нативный счёт Telegram

Telegram умеет показывать счёт прямо в чате: карточка товара, сумма, кнопка оплаты. Оплата проходит внутри мессенджера, карта может быть сохранена в Telegram, но деньги всё равно идут через подключённого платёжного провайдера - без него счёт выставить не получится.

Механика для разработчика состоит из трёх шагов: бот отправляет счёт, затем получает предпроверочный запрос перед списанием и должен на него ответить, а после успешного списания получает событие об оплате. У ответа на предпроверку жёсткий таймаут в считанные секунды - не ответили, платёж отменяется. Это то место, где нельзя ходить в медленную внешнюю систему: проверку наличия товара и корректности заказа надо успевать делать по своей базе.

Внутренняя валюта Telegram

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

Путь платежа по шагам

Схема одинаковая почти для любого сервиса. Меняются названия полей, не логика.

Путь платежа: бот выставляет счёт, человек платит на стороне сервиса, обратно приходит статус. Товар выдаётся по статусу от платёжной системы, а не по скриншоту из переписки - в этом и разница между «бот принимает оплату» и «бот принимает скриншоты».
  1. Выбор. Человек выбирает позицию: тариф, товар, подписку. Бот показывает, что именно покупается и за сколько.
  2. Заказ у себя. До обращения к платёжному сервису мы создаём запись заказа в своей базе: что куплено, кому, на какую сумму, статус «ожидает оплаты», собственный идентификатор. Это опорная точка. Наша база - источник правды, а не переписка и не панель сервиса.
  3. Счёт. Обращаемся к сервису: сумма, валюта, описание, наш идентификатор заказа, адрес возврата пользователя и адрес для уведомлений. Идентификатор заказа обязателен - по нему потом сходится всё остальное.
  4. Оплата. Происходит на стороне сервиса. Мы в этот момент не знаем ничего и не должны догадываться.
  5. Подтверждение. Сервис присылает уведомление о результате на заранее заданный адрес. Это единственное событие, по которому можно что-то выдавать.
  6. Проверка. Сверяем подпись уведомления, находим заказ по идентификатору, сверяем сумму и валюту, проверяем статус и то, что этот заказ ещё не был обработан.
  7. Выдача. Меняем статус заказа, выдаём доступ или оформляем то, что куплено, пишем время выдачи.
  8. Двустороннее уведомление. Покупателю - сообщение в боте с тем, что он получил и что делать дальше. Владельцу - короткое уведомление о продаже. Молчаливая система пугает обе стороны.

Отдельно продумывается возвращение человека в бот после оплаты. Он ушёл на страницу сервиса и там завис или закрыл вкладку - бот должен сам догнать его сообщением по факту уведомления, а не ждать, что покупатель вернётся и нажмёт «я оплатил».

Почему скриншот - это не подтверждение

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

Что должно быть в обработчике уведомления, помимо самой выдачи:

  • Проверка подписи. Уведомление приходит на публичный адрес, туда может постучаться кто угодно. Без проверки подлинности запроса эндпоинт выдачи доступа становится бесплатной раздачей.
  • Сверка суммы и валюты с заказом. Не «пришло уведомление - значит оплачено», а «пришло уведомление на ту сумму, что мы выставляли».
  • Идемпотентность. Одно и то же уведомление может прийти несколько раз - это нормальное поведение сервисов при досылке. Обработка должна быть повторяемой: второй и третий раз ничего не выдают заново и не начисляют дважды.
  • Быстрый ответ. Сервис ждёт короткий успешный ответ. Тяжёлую работу - рассылку, генерацию, обращения к сторонним API - выносят за пределы обработчика, иначе сервис посчитает доставку неудачной и начнёт слать повторы.
  • Собственная сверка. Уведомление может не дойти совсем: сеть, деплой, упавший процесс. Поэтому заказы, застрявшие в статусе «ожидает оплаты», периодически проверяются встречным запросом к сервису - «что с этим платежом». Фоновые задачи по расписанию мы держим на сервере как отдельный механизм; в собственном продукте krug.by по расписанию работают четыре регулярных процесса, и это ровно то место, куда такая сверка встраивается.

Проверка того, кто именно пришёл, не менее важна, чем проверка того, сколько заплачено. В krug.by вход из Telegram в мини-приложение проверяется подписью HMAC-SHA256, а данные старше суток отбраковываются. Логика та же: доверять можно подписанному, а не пересказанному.

Что ломается на практике

  • Оплатил, доступ не пришёл. Самый болезненный случай. Причина почти всегда в недоставленном или упавшем уведомлении. Лечится фоновой сверкой и ручной выдачей как запасным путём.
  • Оплатил дважды. Человек нажал кнопку два раза или заплатил по старой ссылке. Нужна защита от повторного создания счёта на тот же заказ и понятный сценарий возврата лишнего.
  • Заплатил один, а доступ нужен другому. Оплата с аккаунта мужа, жены, коллеги. Стоит заранее решить, привязываем доступ к тому, кто нажал кнопку в боте, или к тому, кто оплатил.
  • Счёт протух. У ссылки на оплату есть срок жизни. Заказ, по которому ссылка истекла, надо уметь закрывать и предлагать создать новый, а не оставлять висеть навсегда.
  • Платёж в статусе ожидания. Некоторые способы оплаты подтверждаются не мгновенно. Бот должен уметь говорить «платёж принят, ждём подтверждения», а не молчать и не выдавать доступ авансом.
  • Смена цены во время оплаты. Если тариф поменяли, пока человек был на странице оплаты, сверка суммы обязана это поймать. Решение принимается заранее: принять по старой цене или вернуть деньги.

Возвраты

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

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

Какие данные о платеже хранить, а какие нельзя

Хранить полезно:

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

Хранить нельзя:

  • номер карты, срок действия, код проверки - их не должно быть ни в базе, ни в логах, ни в скриншотах переписки. Их вообще не должно быть в нашем контуре;
  • секреты интеграции в коде и в репозитории - только в переменных окружения;
  • полные тела запросов от платёжного сервиса в открытых логах: там встречаются поля, которых лучше не сохранять.

Плюс организационное: доступ к панели с платежами и к админке нужен не всем, а вопрос «на каком основании и как долго мы храним персональные данные покупателя» решается до запуска, а не по факту первого запроса от человека.

Чек и закон

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

Что от разработки зависит напрямую:

  • в боте доступны условия продажи - кто продавец, что продаётся, как получить купленное, как вернуть деньги и как связаться с человеком, а не с автоответчиком;
  • перед оплатой видна конечная сумма, а не «уточним позже»;
  • ссылка на оферту и политику обработки данных есть и в боте, и на сайте, и они одинаковые;
  • подтверждение покупки приходит покупателю в письменном виде в чат.

Что проверить перед запуском

Список, по которому мы прогоняем платёжный сценарий перед тем, как включить его людям:

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

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

Когда оплата в боте не нужна

Бывает часто, и честнее сказать об этом сразу.

  • Продаж мало и они штучные. Если сделок несколько в месяц и каждая всё равно сопровождается разговором, автоматизация оплаты не решает проблему - проблемы нет.
  • Сделка требует переговоров. Услуги, где сумма считается под задачу, договор и счёт живут вне бота. Бот в таком случае полезен как заявка и напоминание, а не как касса.
  • Хватает одной ссылки. Иногда достаточно ссылки на оплату от сервиса, отправленной руками. Это дешевле и быстрее, и такой ответ мы даём регулярно.
  • Товар со сложным подбором и доставкой. Размеры, варианты, расчёт стоимости доставки - это про сайт с корзиной, а не про переписку с кнопками.
  • Нет договора с платёжным сервисом. Сначала юридическая часть, потом интеграция. Обратный порядок стабильно приводит к готовому боту, который нечем включить.
  • Ассортимент меняется каждый день. Каталог в боте придётся кормить руками, и он быстро станет источником неверных цен.

С чего начинать, если нужна

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

Как это выглядит на готовых проектах, видно в разделе кейсы; общая логика связок «бот - оплата - выдача - CRM» разобрана в материалах про боты и автоматизацию. Если непонятно, какой из четырёх способов подходит вашей продаже, - обсудить задачу можно бесплатно, разбор ничего не стоит, и вариант «вам это не нужно» тоже входит в число возможных ответов.

Частые вопросы

Может ли Telegram-бот сам принимать деньги?

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

Можно ли выдавать доступ по скриншоту перевода?

Так делают на старте, но скриншот не говорит ни о статусе платежа, ни о его окончательности, ни о том, не отменён ли он. Выдачу стоит привязывать к уведомлению от платёжного сервиса с проверкой подписи и суммы.

Что делать, если человек оплатил, а доступ не пришёл?

Нужны два механизма: фоновая сверка зависших заказов встречным запросом к сервису и ручная выдача для нестандартных случаев. В нашем кейсе с онлайн-курсом ручная выдача сознательно оставлена после автоматизации.

Кто выдаёт чек при оплате в боте?

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

Всегда ли стоит встраивать оплату в бота?

Нет. При штучных продажах, сделках с переговорами или сложном подборе товара оплата в боте не решает задачу - иногда достаточно ссылки на оплату вручную или корзины на сайте.

Разбор задачи бесплатный: смотрим, что происходит сейчас, и говорим, решается это автоматизацией или нет.

Обсудить задачу

Все разборы · Кейсы