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 до свого каналу та отримувати зірки від підписників — без жодного рядка коду.

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

Повернення Telegram Stars: як насправді працює refundStarPayment
Коли повертати Telegram Stars, як викликати refundStarPayment, чому немає часткових повернень, обробка /paysupport і чиста звірка в обліку.
Підпишіться на нашу розсилку
Отримуйте найновіші поради з розвитку Telegram, стратегії автоматизації та оновлення платформи на вашу пошту.
Або підпишіться на наш Telegram-канал