Telegram Star Subscriptions: настройка для рекуррентного дохода

Telegram Star Subscriptions: настройка для рекуррентного дохода
Что получите. Рабочую Telegram Star Subscription, которая списывает 100, 500 или 2 000 Stars каждые 30 дней по уровням доступа — созданную через
createInvoiceLink({subscription_period: 2592000}), обрабатываемую в вебхукеsuccessful_payment(с флагамиis_recurring/is_first_recurring), сохраняемую черезtelegram_payment_charge_idи чисто отменяемую или возобновляемую методомeditUserStarSubscription. Итог — прогнозируемый MRR в Stars и аккуратный off-boarding для тех, кто уходит.
Не хотите писать бота с нуля? Планировщик Autogram работает с вашим subscription-ботом так же, как с бесплатным каналом — тот же календарь, та же панель.
Что понадобится
Каждый шаг ниже опирается на следующие условия:
- Бот, созданный в @BotFather — для Stars (
XTR) дополнительное одобрение не нужно. createInvoiceLinkуже работает для разовых Stars-платежей. Если вы ещё не запускали ни одного нерекуррентного списания — сделайте это сначала; рекуррентный payload отличается только полемsubscription_period.- Постоянное хранилище для
telegram_payment_charge_idна каждого пользователя и уровень. SQLite подойдёт для тестов; in-memory — нет. - Вебхук-обработчик
successful_payment. Каждое продление прилетает именно туда. Обработчики, слушающие толькоpre_checkout_query, пропускают все повторные списания. - Библиотека на Bot API 8.0+ — aiogram ≥ 3.13, python-telegram-bot ≥ 21.7, telegraf ≥ 4.16, gramio ≥ 1.0. Более старые молча выкидывают новые поля
SuccessfulPayment.
Шаг 1 — Задайте уровни подписки в каталоге бота
Photo by Matheus Bertelli on Pexels
Уровень — это кортеж (название, количество Stars, payload-префикс) в вашем коде. На стороне Telegram понятия «уровня» нет: каждый уровень — это отдельный вызов createInvoiceLink с другой ценой. Три уровня — нормальная стартовая конфигурация:
| Уровень | Stars / 30 дней | Эквивалент в $ (≈$0.013/Star) | Аудитория |
|---|---|---|---|
| Supporter | 100 | ~$1.30 | «спасибо за работу», тип-jar |
| Member | 500 | ~$6.50 | регулярные потребители платных дропов |
| VIP | 2 000 | ~$26 | высоко вовлечённые, ожидают 1:1 |
Жёсткие ограничения из спецификации Bot API 8.0 (и гида Star Subscriptions):
subscription_periodОБЯЗАТЕЛЬНО2592000(ровно 30 дней). Никаких других периодов сейчас не поддерживается. Недельных и годовых циклов нет — планируйте под месячный.- Максимальная цена подписки — 10 000 Stars на уровень. 2 000 Stars для VIP оставляют значительный запас.
- Валюта ОБЯЗАТЕЛЬНО
XTR(Telegram Stars), когда заданsubscription_period. Фиатные валюты для рекуррентного не работают. - Пользователь может иметь несколько активных подписок к одному боту. Если «апгрейдится» — вы запускаете новую и отменяете старую; смены уровня in-place нет.
Шаг 2 — Соберите рекуррентный инвойс через createInvoiceLink
Photo by Lukas Blazek on Pexels
Для каждого уровня сгенерируйте одну invoice-ссылку и используйте её для всех подписчиков. Ссылка постоянная, пока вы её не пересоздаёте. Минимальный payload (Python + python-telegram-bot 21.7+):
SUB_PERIOD = 2592000 # 30 дней — единственное допустимое значение в Bot API 8.0
async def make_subscription_link(bot, tier_id: str, label: str, stars: int) -> str:
return await bot.create_invoice_link(
title=f"{label} — месячный доступ",
description="Продлевается автоматически каждые 30 дней. Отмена — в настройках Telegram.",
payload=f"sub:{tier_id}", # вернётся в successful_payment.invoice_payload
provider_token="", # ОБЯЗАТЕЛЬНО пустая строка для Stars
currency="XTR", # Telegram Stars
prices=[LabeledPrice(label=label, amount=stars)],
subscription_period=SUB_PERIOD,
)
Три вещи, которые сломают вас, если их пропустить:
provider_tokenдолжен быть пустой строкой для Stars — не пропущенным, не вашим фиатным токеном. Передача фиатного токена вместе сcurrency="XTR"вернёт400 Bad Request: provider_token is invalid.payload— ваш единственный out-of-band идентификатор уровня. Закодируйтеtier_id— вы прочитаете его на шаге 3, и это единственное, что отличает Supporter от VIP.- Отправляйте ссылку через кнопку или
sendInvoice, не «голым» текстом. Старые клиенты не рендерятt.me/$invoice/...как платный контент.
Шаг 3 — Сохраните telegram_payment_charge_id из successful_payment
Этот шаг определяет, сможете ли вы потом управлять подпиской. Когда пользователь платит, ваш обработчик successful_payment получает объект SuccessfulPayment с новыми полями Bot API 8.0. Считайте все четыре:
@router.message(F.successful_payment)
async def on_payment(message: Message, db):
sp = message.successful_payment
tier_id = sp.invoice_payload.removeprefix("sub:")
await db.upsert_subscription(
user_id=message.from_user.id,
tier_id=tier_id,
charge_id=sp.telegram_payment_charge_id, # НУЖЕН для editUserStarSubscription
expires_at=sp.subscription_expiration_date, # Unix-секунды
is_first=sp.is_first_recurring or False, # true только на первом списании
)
if sp.is_first_recurring:
await message.answer("Добро пожаловать — подписка активна. Продление через 30 дней.")
elif sp.is_recurring:
await message.answer("Продлено ещё на 30 дней. Спасибо.")
Три поведения, которые надо усвоить:
telegram_payment_charge_idтот же между продлениями для одной подписки. Держите одну строку на(user_id, tier_id, charge_id); на продлении обновляйтеexpires_atи сбрасывайтеis_first.is_first_recurring=trueсрабатывает ровно один раз на подписку — на стартовом списании.is_recurring=trueсрабатывает на каждом следующем. У разового Stars-платежа оба флага отсутствуют или false; удобно для ветвления в общем обработчике.- Telegram не присылает апдейт «подписка отменена». Если пользователь отменил в Настройках → Подписки, следующее продление просто не приходит. Считайте отсутствие продления после
expires_at + grace_periodсигналом отмены.
Шаг 4 — Отмена и возобновление через editUserStarSubscription
Photo by weCare Media on Pexels
editUserStarSubscription делает только две вещи: отменяет будущие продления или возобновляет ранее отменённую подписку. Он не меняет цену, не меняет уровень и не возвращает текущий период — это отдельные сценарии.
async def cancel_subscription(bot, user_id: int, charge_id: str):
await bot.edit_user_star_subscription(
user_id=user_id,
telegram_payment_charge_id=charge_id,
is_canceled=True,
)
async def resume_subscription(bot, user_id: int, charge_id: str):
await bot.edit_user_star_subscription(
user_id=user_id,
telegram_payment_charge_id=charge_id,
is_canceled=False,
)
Три поведения, которые цепляют новичков:
is_canceled=Trueне отзывает доступ мгновенно — пользователь сохраняет полный доступ до конца текущего 30-дневного периода. Если нужно немедленное отключение — делайте это в собственном слое проверки прав.- Возобновление работает, только пока подписка не истекла. Как только 30-дневное окно закрылось без продления,
editUserStarSubscriptionвозвращает400 Bad Request: subscription not active, и пользователь должен оформлять подписку с нуля. - Смена уровня = отмена + новая подписка. Отмените старый
charge_id, потом отправьте свежую invoice-ссылку нового уровня. Для полного возврата текущего периода вызовитеrefundStarPaymentДО отмены — аудит-лог будет читаться чище.
Частые ошибки
Четыре ошибки, на которых строится большинство тикетов «у меня не работает subscription-бот»:
- Воспринимать
subscription_periodкак настройку. Он зафиксирован — 2 592 000 секунд. 604 800 (одна неделя) вернёт общий 400; null молча выключает рекуррентное поведение, и вы отгрузите one-shot-бота. - Выбрасывать
telegram_payment_charge_id. Без него вы не сможете вызватьeditUserStarSubscription, и единственный ответ на тикет «отмените мне» — «извините, отмените в настройках». - Выдавать доступ на каждом
successful_paymentбез проверкиis_first_recurring. Если ваш «welcome» отправляет ссылку на скачивание, каждое продление отправит её снова. Welcome — наis_first_recurring, продление — наis_recurring and not is_first_recurring. - Ожидать, что смена уровня — это один API-вызов. Такого вызова нет. Смена уровня = отмена + переоформление. Покажите это в
/upgradeUX, чтобы пользователи не ждали смены в один тап.
По теме
- Монетизация Telegram Stars: набор инструментов для канала 2026 — родительский toolkit. Этот материал — глубокое погружение в рекуррентную поверхность, которую он лишь упомянул в FAQ.
- Telegram-бот для авторского канала: пять часов в неделю и стабильный выход — как соло-автор встраивает Stars-подписки в недельный цикл.
- ROI автоматизации Telegram: экономия против ручного постинга (2026) — обратная сторона уравнения: часы, которые освобождает автоматизация, финансируют ваш subscription-эксперимент.
- AI-бот для Telegram-канала: настройка с нуля в 2026 — как только подписки взлетели, AI-генерируемые дропы — то, что держит VIP-уровень оправданным по цене.
Частые вопросы
Можно ли делать недельные или годовые Star Subscriptions?
Нет. На момент Bot API 8.0 единственный поддерживаемый subscription_period — 2592000 (30 дней). Планируйте цены вокруг месячного цикла и возвращайтесь к вопросу, когда Telegram расширит спецификацию.
Какой максимум за одну подписку?
10 000 Telegram Stars за 30-дневный период — около $130 по курсу выплат автору (~$0.013 за Star). Потолок тот же, независимо от того, что закрывает подписка — Mini App, приватный канал или доступ к контенту через бота.
Как обрабатывать upgrade и downgrade?
Смены уровня in-place нет. Отмените действующую подписку через editUserStarSubscription(is_canceled=True), потом отправьте свежую invoice-ссылку нового уровня. Старый уровень работает до конца текущего периода; новый начинает списывать сразу.
Уведомляет ли Telegram пользователя, когда бот отменяет его подписку?
Нет. editUserStarSubscription(is_canceled=True) молчаливый — пользователь узнает только тогда, когда следующее продление не придёт. Отправьте собственное подтверждение и покажите строку «подписка завершится YYYY-MM-DD» в пост-cancel UI.
Как отличить первое списание от продления в successful_payment?
Bot API 8.0 добавил is_first_recurring (true ровно один раз на подписку) и is_recurring (true на каждом следующем списании). У разового Stars-платежа оба флага отсутствуют или false. Ветвите обработчики по этим флагам, не только по invoice_payload.
Может ли пользователь отменить подписку без участия моего бота?
Да. Подписчики управляют всеми Star Subscriptions в Настройках → Telegram Stars → Подписки. Бот об этом не уведомляется — единственный сигнал в том, что продление не приходит. Считайте любую подписку после expires_at + 24h отменённой в собственном слое проверки прав.
Итог
Telegram Star Subscriptions — это тонкий слой поверх createInvoiceLink: три новых поля в SuccessfulPayment, один новый метод управления жизненным циклом, один зафиксированный 30-дневный период. Сложность — операционная, а не на уровне API: сохраните charge_id, ветвите welcome по is_first_recurring, обрабатывайте смену уровня как «отменить + переоформить». Запустите Supporter, посмотрите, что конвертит за первые 30 дней, потом наслоите Member и VIP.
Подключите Autogram к вашему subscription-боту — и пусть планировщик постит дропы для платных уровней в том же календаре, где живёт бесплатный контент.
Авторство фото
- Hero-изображение — фото Matheus Bertelli на Pexels
- Inline-изображение №1 — фото Lukas Blazek на Pexels
- Inline-изображение №2 — фото weCare Media на Pexels
Похожие посты

Как добавить Telegram Mini App в канал: монетизация без кода в 2026
Пошаговое руководство: как подключить Telegram Mini App к каналу и принимать Stars-оплату от подписчиков — без единой строки кода.

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

Возврат Telegram Stars: как на самом деле работает refundStarPayment
Когда возвращать Telegram Stars, как вызывать refundStarPayment, почему нет частичных возвратов, обработка /paysupport и чистая сверка в учёте.
Подпишитесь на рассылку
Получайте последние советы по росту Telegram, стратегии автоматизации и обновления платформы прямо на почту.
Или подпишитесь на наш Telegram-канал