Урок 4. Платежи в Telegram
Last updated
Was this helpful?
Last updated
Was this helpful?
Урок будет достаточно объемным, полный листинг программы как и всегда доступен
Итак, мы собрались принимать платежи в Telegram. Для этого необходимо перейти в , выбрать своего тестового бота и подключить к нему тестовые платежи. Я подключил платежи сервиса Яндекс.Касса. После этого переходим обратно к BotFather и получаем токен для Тестовых платежей, выглядит он примерно так: 012345678:TEST:1234
.
Важно! Токен привязывается к боту, поэтому для подключения даже тестовых платежей к другому боту, процедуру, описанную выше, придется повторить.
Создаем файлы и .
Для начала создадим самого простого бота, который принимает платежи, чтобы понять основу.
После делаем кое-что новое, а именно:
: loop = asyncio.get_event_loop()
. Предположим, что для полноценной работы нашего абстрактного интернет магазина в loop
нужно будет ещё запустить работу жизненно важных процессов.
для бота Parse Mode
: bot = Bot(BOT_TOKEN, parse_mode=types.ParseMode.MARKDOWN)
. На этом остановлюсь поподробнее: предположим, что наши стандартные сообщения размечены при помощи одного типа разметки. И поэтому при отправке сообщений нам придется каждый раз явно указывать тип этой самой разметки. Однако библиотека aiogram
позволяет нам установить стандартную разметку для всех отправляемых сообщений. Это можно сделать как при создании инстанса бота, так и в любой момент в коде обычным присваиванием: bot.parse_mode = 'HTML'
, а при необходимости удалить обычным del bot.parse_mode
. При этом мы всё ещё можем указывать тип разметки явно, и это будет иметь преимущество. Таким образом, при стандартной разметке 'MARKDOWN'
при вызове метода send_message
, передав в параметр parse_mode
значение 'HTML'
, сообщение будет отправлено с HTML разметкой.
Ну и : dp = Dispatcher(bot, loop=loop)
.
Теперь переходим к объявлению цены. Так как в минимальном примере она у нас будет одна, записываем следующее:
У объекта LabeledPrice
всего 2 параметра - это label
и amount
. И если первый говорит сам за себя, то второй требует больше внимания. В него нужно передавать целочисленное значение в минимально возможных единицах валюты. То есть если мы говорим о рублях, то передавать нужно копейки (123 ₽ как 12300). В подавляющем большинстве валют это 2 знака (как копейки у рубля и центы у доллара), однако, если вам пришлось работать со специфичной валютой, можно обратиться к файлу и найти параметр exp
. К примеру, те же йены или Исландские кроны не имеют "копеек".
Далее создаем обычный хэндлер команд:
И переходим к написанию самой логики платежей.
Распознаем команду, по которой будем присылать квитанцию:
И чтобы не запутать ни себя, ни пользователя, проверяем, работаем ли мы сейчас с тестовой оплатой. Узнать это очень просто - по слову TEST
в середине токена для платежей.
Что же там произошло? Объясняю (до параметра currency
всё и так понятно):
Параметры photo_height
и photo_width
нужно указать, если вы передаете ссылку на изображение в photo_url
, иначе изображение либо вообще не отобразится, либо отобразится некорректно. Следом можно добавить параметр photo_size
, у меня отображается и без него, но лишним точно не будет.
Параметр is_flexible
отвечает за то, что если финальная цена зависит от способа доставки (когда передаем True
), то:
будет добавлено поле выбора адреса доставки, даже если не передан параметр need_shipping_address
(как в этом примере)
Поле prices
принимает массив из цен, поэтому передаем туда [PRICE]
Параметр start_parameter
является обязательным, документация утверждает, что можно использовать уникальный диплинкинг параметр, чтобы создать эту квитанцию, однако как этим воспользоваться, мне узнать не удалось. Разве что проверить этот параметр, если пользователь ответит на сообщение с квитанцией, но это уж очень большие заморочки, как по мне
Ну и параметр payload
. Объем 1-128 байт. Рекомендуется использовать его для того, чтобы идентифицировать инвойсы - он не показывается пользователю, но мы можем его прочитать при получении успешной оплаты (об этом далее)
Ну что ж! С самым сложным разобрались! Запрашиваем квитанцию, заходим со смартфона (на десктопе платежи до сих пор не поддерживаются) и нажимаем на единственную кнопку под сообщением (она добавляется автоматически, если мы не передаем никакую клавиатуру к сообщению, в ином случае мы обязаны сделать первую кнопку "платежной", а остальные как обычно) и переходим к оплате:
Как мы видим, телеграм сам ставит разделитель копеек.
Нажимаем Payment Method и вводим данные карточки. Номер, как нам уже подсказал бот, это повторяющиеся 42, срок действия нужно указать валидный (больше текущей даты). Затем набираем трехзначный CVC и нажимаем "Заплатить" / "Pay".
Как ни странно, в этот момент оплата ещё совершена не будет, мы вернемся к предыдущему экрану, куда добавится информация о нашей платежной карточке.
Для того, чтобы обработать оплату в данном примере, нам понадобится ещё два хэндлера:
Для того, чтобы определить, что за платеж прошел, мы можем обратиться к полю provider_payment_charge_id
. Получив сообщение с информацией об успешной оплате, нам остается проинформировать пользователя о том, что оплата прошла успешно, для этого собираем нужные данные и отправляем ответ:
Начнем с изменения первой же цены. Запишем:
Теперь в оплату у нас помимо Машины Времени входит ещё и подарочная упаковка, которую нельзя убрать.
Об их применении чуть позже, сейчас добавим стандартные хэндлеры:
И отправляем счёт по команде /buy
:
Разберем добавившиеся параметры:
need_email
- будет запрошена электронная почта при заполнении информации для доставки
need_phone_number
- аналогично, но номер телефона
need_shipping_address
- этот параметр нам указывать не нужно, так как дальше мы задаем is_flexible=True
. Но если бы мы одновременно хотели получить адрес доставки и не менять цену в зависимости от адреса, можно было бы воспользоваться этим параметром.
send_phone_number_to_provider
- передать провайдеру платежей телефонный номер пользователя
send_email_to_provider
- аналогично, но адрес электронной почты
Ну что ж. Мы получили инвойс, открываем его и заполняем.
При сохранении адреса будет отправлен апдейт, ловим его и обрабатываем:
Ещё у shipping_query есть параметр id
, который мы задавали в начале. Для варианта Почта России это 'ru_post'
. Так что проверить можно ещё и по айди.
Ладно, выберем, например, Зимбабве, а ещё заполним поля, требующие номер телефона и почту:
Тут мы видим, что это не Россия, поэтому передаем только один вариант доставки - телепортом.
Выглянув в окно и убедившись, что мы всё таки не в Зимбабве, выставляем страну Россия, ну и укажем город Москва. Программа проверит это и добавит нужные опции в массив. Таким образом мы получим уже три варианта доставки:
Смотрите ещё что. В вариант отправки Почтой России мы добавили два обязательных параметра: это Деревянный ящик с амортизирующей подвеской внутри и Срочное отправление (5-10 дней), стоимость этих пунктов добавляется в квитанцию.
Нажимаем кнопку "Pay", но оплата у нас не пройдет: не забыли, что нам необходимо ещё подтвердить платеж? Создаем следующий хэндлер:
Допустим, мы всегда запрашиваем у пользователя почту, а затем проверяем её валидность. В данном примере мы запрещаем пользователю использовать почту vasya@pupkin.com
, поэтому при совпадении возвращаем ошибку.
Теперь для интереса (чтобы вариант "Самовывоз" пропал) сменим адрес на не Москву
Вот так.
Ну и, исправив почту, мы таки выполняем платеж:
И ещё: при каждом выборе адреса доставки мы печатали этот самый адрес. А при попытке оплатить печатали информацию по заказу. Взглянем же на распечатанное:
Эти данны мы можем использовать для дальнейшей обработки заказа, но это уже история совсем не про Telegram Bot API.
В качестве домашнего задания попробуйте добавить больше фильтров валидации к своему платежу
И затем в высылаем сам счет:
В currency
необходимо передать трехзначный код валюты в формате ISO 4217. Полный список валют можно найти .
после выбора пользователем адреса доставки будет отправлена , на которую ботапи будет ждать ответ (об этом в более подробном примере ниже в этом уроке)
Когда пользователь нажимает на кнопку "Оплатить" / "Pay", Телеграм отправляет апдейт типа , на который нам необходимо в течение десяти секунд. Подразумевается, что получив данный апдейт мы обработаем содержащуюся в нем информацию и отправим положительный, либо отрицательный ответ. Так как этот пример максимально простой, здесь мы всегда будем отвечать утвердительно (а ниже разберем пример с отказом), поэтому передаем ok=True
в answer_pre_checkout_query
. После получения сервером Телеграм положительного ответа происходит оплата (взаимодействие с провайдером оплаты, тот передает информацию об успешной оплате), и мы получаем апдейт (сообщение) с ContentType
SUCCESSFUL_PAYMENT
, который можем обработать (и будет правильно так сделать):
Для наглядности на строчках я сделал печать интересующих нас параметров в формате ключ = значение
:
Полный листинг этого примера доступен
Только что мы разобрали принцип получения платежей в Telegram. Теперь перейдем к более сложной части. Этот пример проведем в .
Затем на строках объявляем возможные способы доставки.
приведена ещё пара необзательных параметров, касающихся платежей:
Раз уж мы решили, что от адреса доставки изменяется конечная цена, обработаем этот самый адрес. Для начала укажем страну Австралию. Предположим, что туда мы не можем доставить наш товар, для этого проверяем country_code
(код страны) у объекта ShippingAddress
. Это код в формате ISO 3166-1 alpha-2. Коды всех стран доступны . , что выбрана страна Австралия, отвечаем пользователю, что такой вариант нам не подходит: