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 добавим четыре регистрации:

  1. send_invoice_handler — Регистрируем как обычное сообщение, указав фильтр команды donate.

  2. pre_checkout_handler — Регистрируем как событие pre_checkout_query.

  3. success_payment_handler — Регистрируем как обычное сообщение. В качестве фильтра используем так называемый "Магический фильтр F", представляющий собой объект Message. В фильтре обращаемся к полю successful_payment. Если оно не пустое (успешная оплата), будет вызван обработчик.

  4. 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.

Получим сообщение с информацией о платеже и кнопкой-счётом. Нажмём на кнопку.

Откроется окно с подтверждением оплаты (если у вас нет звёзд — откроется окно приобретения, как на первом скриншоте в начале поста). Нажимаем "Подтвердить и заплатить".

В чате выстрелит конфетти, и мы увидим сообщение об успешном платеже.

Заключение

Нововведение, конечно, всех удивило и немного застало врасплох. На переход дали мало времени, и наверняка не все даже узнали об этом. Интересно будет посмотреть, к чему всё это приведёт.

Читать пост на сайте.
Читать пост в Telegram.

Комментарии (9)


  1. grigoryvp
    13.06.2024 09:41

    Приобрести звёзды можно, открыв настройки Telegram и найдя пункт "Звёзды Telegram".

    Это уже сейчас доступно или будет когда-нибудь в будущем? Я открыл настройки и на десктопном клиенте, и на мобильном. Внимательно поискал, но такой пункт не нашел.


    1. proDream Автор
      13.06.2024 09:41

      Уже доступно, как вариант, пункт появится после покупки звёзд непосредственно в боте/вебапп


      1. grigoryvp
        13.06.2024 09:41

        Бот предлагает только подписаться на премиум и не предлагает купить звезды. Возможно оно доступно только в избранных регионах? У телеграма вообще есть концепция "региона"?


        1. proDream Автор
          13.06.2024 09:41

          Я имел в виду в боте, который продаёт что-то за звёзды. Сейчас все боты (видимо, кроме премиум бота) обязаны продавать только за звёзды, все остальные способы оплаты отключены.


          1. markoni
            13.06.2024 09:41

            Вот прямо сейчас расположил рядом 2 кнопки: оплата stars и оплата картой через stripe - обе работают, и старсы и деньги - приходят. Что я делаю не так?


            1. proDream Автор
              13.06.2024 09:41

              Видимо ещё не отключили, либо я не так понял то, что написано тут в разделе FAQ:
              https://core.telegram.org/bots/payments-stars


              1. markoni
                13.06.2024 09:41

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


  1. FedorOmron
    13.06.2024 09:41

    Кто разобрался в комиссиях итоговых? При оплате через Телеграмм Старс:
    1. Комиссия (эпл/гугл) = 35%
    2. Комиссия Телеграмм = 5%
    3. НДС = 20% (при проведении операции)
    4. Оплата налога ИП/ООО по факту выведения на р/с правильно посчитал?
    Итого 60%  комиссия с платежа + при поступлении на р/c ?


  1. glader
    13.06.2024 09:41

    А как выводить заработанные ботом звезды?