Перейти к основному содержимому
Инструкции

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

Также доступно на языках:ENRUUK
Опубликовано April 24, 20267 мин. чтения63 просмотров
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)Аудитория
Supporter100~$1.30«спасибо за работу», тип-jar
Member500~$6.50регулярные потребители платных дропов
VIP2 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 нет.

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-бот»:

  1. Воспринимать subscription_period как настройку. Он зафиксирован — 2 592 000 секунд. 604 800 (одна неделя) вернёт общий 400; null молча выключает рекуррентное поведение, и вы отгрузите one-shot-бота.
  2. Выбрасывать telegram_payment_charge_id. Без него вы не сможете вызвать editUserStarSubscription, и единственный ответ на тикет «отмените мне» — «извините, отмените в настройках».
  3. Выдавать доступ на каждом successful_payment без проверки is_first_recurring. Если ваш «welcome» отправляет ссылку на скачивание, каждое продление отправит её снова. Welcome — на is_first_recurring, продление — на is_recurring and not is_first_recurring.
  4. Ожидать, что смена уровня — это один API-вызов. Такого вызова нет. Смена уровня = отмена + переоформление. Покажите это в /upgrade UX, чтобы пользователи не ждали смены в один тап.

По теме

Частые вопросы

Можно ли делать недельные или годовые 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. Подключите первый канал и получите 7 дней доступа к Solo с AI-бюджетом $1. Банковская карта не нужна.

Авторство фото

#telegram star subscriptions#createInvoiceLink#subscription_period#editUserStarSubscription#рекуррентный доход telegram#telegram бот настройка#telegram subscription bot

Подпишитесь на рассылку

Получайте последние советы по росту Telegram, стратегии автоматизации и обновления платформы прямо на почту.

Или подпишитесь на наш Telegram-канал