Добавляем подписку с Telegram Stars в свой апп
Я очень радовался 14.08.2024 из‑за выхода очередного релиза Телеграм, в котором они анонсировали подписки за звезды, потому что это сильно облегчало мое взаимодействие с клиентами: они один раз подписываются и далее не имеют проблем с повторными платежами, вместо этого звезды тихонько списываются у них с счетов. В этом посте я расскажу, как прикрутил подписку в звездах к своей Telegram Mini App (TMA).
Вот как выглядит глазами клиентов списание звезд в пользу вашей аппы. Заметьте, никаких предупреждающих писем, как у Stripe, например.
Свои подписки можно посмотреть у себя в профиле. Это выглядит так:
https://storage.googleapis.com/memes-repo/tutorial/100000998111.png
Отменить подписку можно, если вы зайдете в ее детали.
https://storage.googleapis.com/memes-repo/tutorial/1000009980.png
Теперь, когда вы представляете все визуально, то опишу последовательность вызовов, которые вы должны выполнить.
Создать счет на подписку.
Подтвердить оплату.
Принять первое и последующие сообщения об оплате.
### Создание счета
Для создания счета вызываем метод createInvoiceLink.
def create_invoice(admin_chat_id: str,
channel_id: str,
title: str,
description: str,
tariff_id: int,
tariff_price: int,
) -> dict:
data = {
"chat_id": admin_chat_id,
"title": title,
"description": description,
"payload": json.dumps({"t": tariff_id}),
"provider_token": "", # Empty
"currency": "XTR", # required
"prices": [{'amount': tariff_price, 'label': title}],
"subscription_period": 2592000,
}
r = requests.post(f"{TG_API_URL}{TG_OP_SEND_INVOICE}", json=data)
Вещи, на которые обращаем внимание:
provider_token
пустая строкаcurrency
обязательно строка XTRsubscription_period
обязательно 2 592 000prices
содержит только один элемент
### Подтверждение оплаты
Для получения подтверждения оплаты счета вам нужно добавить в ваш webhook (allowed_updates) подписку на pre_checkout_query. После этого вы начнете получать update c данным полем и структурой.
Когда вы получаете такой апдейт, вам нужно отреагировать на него в течение 10 секунд: принимаете или отклоняете (например, если этот счет уже был оплачен и другие краевые условия).
Данная структура также позволяет вам понять, что было оплачено в рамках счета, путем чтения поля payload
(которое было записано при создании счета).
pre_checkout_data: PreCheckoutData = {
"id": packet["pre_checkout_query"]["id"],
"currency": packet["pre_checkout_query"]["currency"],
"total_amount": packet["pre_checkout_query"]["total_amount"],
"invoice_payload": json.loads(packet["pre_checkout_query"]["invoice_payload"])
}
Для подтверждения или отклонения оплаты счета используйте метод answerPreCheckoutQuery.
### Принять сообщения об оплате
На мое удивление сообщение об оплате встроено в существующий объект Message, так что не нужно дополнительно подписываться на новые источники данных. Вместо этого, мы просматриваем все message в поисках поля successful_payment
или refunded_payment
и записываем в статистику (для возможного возврата в том числе).
Обратите внимание! В структуре SuccessfulPayment есть параметр is_first_recurring
, и я думал, что он True для первого платежа подписки и False для последующих, но! в последующих его просто нет (это допустимо, так как это необязательный параметр).
На этом все, как только вы начали получать successful_payment
, вам не нужно больше делать ничего, чтобы клиент продлил подписку.
P.S. Вы всегда можете обновлять срок подписки при получении данного сообщения, читая поле subscription_expiration_date
. Если successful_payment
перестал приходить, то и подписка не обновится.
Ваш Дима из TG Defender, защита вашего Telegram канала от наплыва ботов на стиле.