6 июня Павел Дуров сообщил, что в Telegram вводится новая валюта — Stars. Stars позволят производить покупку цифровых товаров и услуг, проще говоря, оплачивать покупки внутри Telegram, например, в ботах или в MiniApps. Однако не всё так радужно. Введение нового способа оплаты влечёт за собой отключение всех остальных платёжных средств. Если ваш бот принимал оплату через ЮКассу, то теперь только "Звёзды". Причины таких изменений оставим за скобками и сосредоточимся на более важных вещах, а именно на том, как внедрить в Telegram-бота новый способ оплаты — Telegram Stars.
Приобрести звёзды можно, открыв настройки Telegram и найдя пункт "Звёзды Telegram".
Стоит отметить. На момент написания не было актуальной информаций по тому, как и где использовать полученные от пользователей звёзды. Статья будет дополняться по мере обновления информации от Telegram. Если вам что-то известно, сообщите нам!
Внимание! Пост является продолжением серии "Telegram-бот на AIOgram3".
Обновление зависимостей
Для полноценной поддержки нового способа оплаты требуется версия AIOgram 3.7.0. Для обновления библиотеки достаточно выполнить команду:
pip install -U aiogram
После этого обновите версию в файле requirements.txt
.
aiogram==3.7.0
Кнопка оплаты
Перед тем, как мы начнём писать обработчик команды, выставляющей счёт на оплату, необходимо создать кнопку для оплаты, нажатие на которую откроет окно для оплаты.
В пакете botlogic
создадим новый пакет keyboards
, а в нём файл payment_keyboard.py
.
Пропишем функцию payment_keyboard
, которая ничего не принимает.
В теле функции создадим переменную builder
, в которой определим экземпляр класса InlineKeyboardBuilder
.
В него можно передать список списков с объектами класса кнопки, но это не совсем удобно, проще пользоваться методами класса. На следующей строке вызываем у объекта класса метод .button
, добавляющий кнопку в сборщик клавиатуры. Передаём два аргумента:
text
— Определяет текст на кнопке. Если в тексте будетXTR
или эмодзи звезды ⭐️, оно автоматически заменится на иконку Telegram Stars.pay
— Определяет тип кнопки как кнопку для оплаты.
Далее делаем возврат переменной builder
, применив к ней метод .as_markup
, чтобы получить объект готовой к размещению в сообщении клавиатуры.
Код файла:
from aiogram.utils.keyboard import InlineKeyboardBuilder
def payment_keyboard():
builder = InlineKeyboardBuilder()
builder.button(text=f"Оплатить 20 ⭐️", pay=True)
return builder.as_markup()
Создание клавиатуры не обязательно, отправлять счёт можно и без неё. Однако, она позволяет настроить текст кнопки, а также добавить дополнительные функциональные кнопки, такие, как отмена платежа, выбор другого товара и т.д.
Обработчик выставления счёта
Приступим к написанию обработчика команды.
В пакете handlers
создадим файл payment.py
.
В этом файле пропишем асинхронную функцию send_invoice_handler
, принимающую message
— объект класса Message
.
Создадим переменную prices
, в которую поместим список с объектами класса LabeledPrice
, вернее, с одним объектом, так как для оплаты через Telegram Stars этот список должен состоять из одного элемента. В объект класса передаём следующие аргументы:
label
— Определение валюты. В нашем случае этоXTR
.amount
— Стоимость в звёздах.
Далее у переменной message
вызываем метод .answer_invoice
, чтобы бот ответил на сообщение пользователя кнопкой со счётом на оплату. В метод передаём следующие аргументы:
title
— Название платежа, товара или услуги.description
— Описание платежа, товара или услуги.prices
— Список объектовLabeledPrice
, определённый ранее в одноимённой переменной.provider_token
— Токен платёжной системы, для Telegram Stars просто отправляем пустую строку.payload
— Маркировка платежа. Она не отображается пользователю, а может использоваться для разделения платежей по их типам и так далее. Максимум 128 байт данных (в Python один символ занимает один байт, но стоит учитывать, что специальные символы или эмодзи могут занимать больше места).currency
— Валюта платежа, для Telegram Stars этоXTR
.reply_markup
— Объект клавиатуры.
Код обработчика:
from aiogram.types import LabeledPrice, Message
from botlogic.keyboards.payment_keyboard import payment_keyboard
async def send_invoice_handler(message: Message):
prices = [LabeledPrice(label="XTR", amount=20)]
await message.answer_invoice(
title="Поддержка канала",
description="Поддержать канал на 20 звёзд!",
prices=prices,
provider_token="",
payload="channel_support",
currency="XTR",
reply_markup=payment_keyboard(),
)
Предпродажная проверка
Счёт выставлен, пользователь нажимает "Оплатить". Если у него не хватает звёзд, система предложит их приобрести. Если звёзд у него хватает, он произведёт оплату, и в этот момент Telegram пришлёт в бота запрос "точно ли всё хорошо?". На ответ у нас будет ровно 10 секунд. Если мы по каким-то причинам не хотим принимать оплаты у данного пользователя или логика бота настроена на отмену платежа, в таком случае необходимо дать ответ, сигнализирующий об отмене платежа, сопроводив его причиной отмены. В противном же случае, подтверждаем, что всё "Ок".
В этом же файле создадим асинхронную функцию pre_checkout_handler
, принимающую аргумент pre_checkout_query
— объект класса PreCheckoutQuery
.
В теле функции у переменной pre_checkout_query
вызываем метод .answer
, передавая в него аргумент ok
со значением True
.
Код функции:
from aiogram.types import PreCheckoutQuery
async def pre_checkout_handler(pre_checkout_query: PreCheckoutQuery):
await pre_checkout_query.answer(ok=True)
Информирование о покупке
Бюрократия позади, осталось только поздравить пользователя с покупкой!
В этом же файле создадим асинхронную функцию success_payment_handler
, принимающую аргумент message
— объект класса Message
.
В объекте класса Message
хранится различная информация о текущем сообщении, а в поле successful_payment
находится информация о платеже, такая, как идентификатор платежа, сумма, валюта, информация, полученная от пользователя. По-хорошему, это всё необходимо сохранить во избежание возможных вопросов по платежам в будущем.
В теле функции делаем обычный ответ, сообщая, что покупка прошла успешно.
Код функции:
async def success_payment_handler(message: Message):
await message.answer(text="?Спасибо за вашу поддержку!?")
Команда paysupport и немного про возврат средств
Telegram также предъявляет условия к возврату средств пользователям. Не за все товары и услуги подразумевается возврат средств, однако у пользователя всё равно должна быть возможность запросить возврат средств, либо быть проинформированным касательно этого.
Для информирования пользователя обязательно должна быть команда /paysupport
. В ней можно указать условия возврата, контактные данные и др. Давайте сделаем эту команду.
Создадим асинхронную функцию pay_support_handler
, принимающую message
— объект класса Message
. В теле функции пропишем ответ на сообщение с текстом, описывающим условия для возврата средств.
Код функции:
async def pay_support_handler(message: Message):
await message.answer(
text="Добровольные пожертвования не подразумевают возврат средств, "
"однако, если вы очень хотите вернуть средства - свяжитесь с нами." )
Непосредственно возврат средств можно сделать доступным пользователю. Для этого необходимо создать обработчик команды возврата, в котором, обращаясь к методу .refund_star_payment
у объекта Bot
, передать в него user_id
и telegram_payment_charge_id
.
user_id
— Telegram-ID пользователя, запрашивающего возврат средств.telegram_payment_charge_id
— Идентификатор платежа, совершённого пользователем.
Регистрация обработчиков
Всё готово, осталось зарегистрировать обработчики в main.py
.
Откроем файл main.py
и в функции start
добавим четыре регистрации:
send_invoice_handler
— Регистрируем как обычное сообщение, указав фильтр командыdonate
.pre_checkout_handler
— Регистрируем как событиеpre_checkout_query
.success_payment_handler
— Регистрируем как обычное сообщение. В качестве фильтра используем так называемый "Магический фильтрF
", представляющий собой объектMessage
. В фильтре обращаемся к полюsuccessful_payment
. Если оно не пустое (успешная оплата), будет вызван обработчик.pay_support_handler
— Регистрируем как обычное сообщение с фильтром на командуpaysupport
.
from aiogram import F
dp.message.register(payment.send_invoice_handler, Command(commands="donate"))
dp.pre_checkout_query.register(payment.pre_checkout_handler)
dp.message.register(payment.success_payment_handler, F.successful_payment)
dp.message.register(payment.pay_support_handler, Command(commands="paysupport"))
Тестирование
Запустим бота и выполним команду /donate
.
Получим сообщение с информацией о платеже и кнопкой-счётом. Нажмём на кнопку.
Откроется окно с подтверждением оплаты (если у вас нет звёзд — откроется окно приобретения, как на первом скриншоте в начале поста). Нажимаем "Подтвердить и заплатить".
В чате выстрелит конфетти, и мы увидим сообщение об успешном платеже.
Заключение
Нововведение, конечно, всех удивило и немного застало врасплох. На переход дали мало времени, и наверняка не все даже узнали об этом. Интересно будет посмотреть, к чему всё это приведёт.
Комментарии (9)
FedorOmron
13.06.2024 09:41Кто разобрался в комиссиях итоговых? При оплате через Телеграмм Старс:
1. Комиссия (эпл/гугл) = 35%
2. Комиссия Телеграмм = 5%
3. НДС = 20% (при проведении операции)
4. Оплата налога ИП/ООО по факту выведения на р/с правильно посчитал?
Итого 60% комиссия с платежа + при поступлении на р/c ?
grigoryvp
Это уже сейчас доступно или будет когда-нибудь в будущем? Я открыл настройки и на десктопном клиенте, и на мобильном. Внимательно поискал, но такой пункт не нашел.
proDream Автор
Уже доступно, как вариант, пункт появится после покупки звёзд непосредственно в боте/вебапп
grigoryvp
Бот предлагает только подписаться на премиум и не предлагает купить звезды. Возможно оно доступно только в избранных регионах? У телеграма вообще есть концепция "региона"?
proDream Автор
Я имел в виду в боте, который продаёт что-то за звёзды. Сейчас все боты (видимо, кроме премиум бота) обязаны продавать только за звёзды, все остальные способы оплаты отключены.
markoni
Вот прямо сейчас расположил рядом 2 кнопки: оплата stars и оплата картой через stripe - обе работают, и старсы и деньги - приходят. Что я делаю не так?
proDream Автор
Видимо ещё не отключили, либо я не так понял то, что написано тут в разделе FAQ:
https://core.telegram.org/bots/payments-stars
markoni
На данный момент, по описанию - владелец сам определяет "цифровые товары и услуги". Ну, и в случае несоответствия - может что-то прилететь от телеги. Плюс - там не оговорены пожертвования - это не товар, и не услуга. Но отключать прием карт для ботов, исходя опять же из написанного - не будут.