Перейти до основного вмісту
Інструкції

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

Також доступно мовами:ENRUUK
Опубліковано April 24, 20267 хв читання51 переглядів
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-канал