Возврат Telegram Stars: как на самом деле работает refundStarPayment

Возврат Telegram Stars: как на самом деле работает refundStarPayment
Что получите. Рабочий обработчик
/paysupport, который позволяет клиенту-плательщику Stars запросить возврат прямо в чате, аудируемый вызовrefundStarPaymentпо оригинальномуtelegram_payment_charge_id, учётную запись на стороне оператора, переживающую риск клоубэка от App Store/Google Play, и чёткое правило для возвратов по подписке (которое никогда не отменяет саму подписку — это отдельный вызовeditUserStarSubscription). Два аргумента API, одно дерево решений и самый чистый support-флоу в экосистеме Stars.
Если платная Stars-поверхность уже работает, а обработки возвратов нет — вы накапливаете технический долг. Планировщик Autogram передаёт refund-вебхук вашему боту так же, как передаёт платные дропы.
Что понадобится
Каждый шаг ниже опирается на следующие условия:
- Бот, уже принявший хотя бы один Stars-платёж. Без транзакции нет
telegram_payment_charge_id, который можно вернуть. - Постоянная запись каждого
successful_paymentпо ключуtelegram_payment_charge_id→(user_id, tier_id, amount, paid_at). SQLite подойдёт; in-memory — нет. - Обработчик команды
/paysupport. Stars ToS прямо говорит пользователям отправлять/paysupportботу, когда они хотят возврат. Боты, игнорирующие команду, автоматически теряют путь эскалации. - Библиотека на Bot API 7.4+ —
refundStarPaymentзапустился вместе с валютой Stars (июнь 2024), так что всё, что поддерживаетXTR, поддерживает и возвраты.
Шаг 1 — Решите, уместен ли возврат вообще
Photo by Yan Krukau on Pexels
Возврат уместен, когда выполнено одно из условий ниже. Всё остальное — кандидат на кредит, извинение или запись в feature-request, но не возврат:
| Триггер | Возврат? | Почему |
|---|---|---|
| Обещанный контент не доставлен (404, битые ссылки, отсутствует видео) | Да, полный | Раздел 3.1 Stars ToS прямо покрывает этот случай |
| Пользователь случайно купил дважды за короткое окно | Да, только дубль | Жест доброй воли; дубль не имеет бизнес-ценности |
| Подписка продлилась, а пользователь не понял, что это авторекуррент | Да, только последний период | Возврат самого свежего списания; не трогайте старые периоды |
| Контент доставлен, пользователь передумал | Нет | По ToS: «все продажи Stars окончательны» после поставки цифрового товара |
| Пользователь хочет частичный возврат с мульти-айтемного поста | Нет (невозможно) | refundStarPayment не принимает сумму — возврат только полный |
| Списание старше ~6 месяцев (без официального лимита, но практически) | Возможно | API не блокирует, но Telegram мог уже обработать клоубэк |
Полезное правило: возврат делает клиента целым; кредит делает следующую покупку приятнее. Когда сомневаетесь — по умолчанию кредит: он сохраняет аудит-лог и LTV. Возврат — только для «мы не доставили».
Шаг 2 — Подключите /paysupport, чтобы пользователь мог попросить чисто
Когда пользователь открывает Настройки → Telegram Stars → Транзакции и тапает по транзакции бота, UI Telegram показывает кнопку «Связаться с ботом для возврата», которая вызывает /paysupport. Если бот не обрабатывает эту команду, пользователь оказывается в мёртвом чате — и Telegram в своём флоу эскалации отметит, что «разработчик отказался обрабатывать законный возврат». Такая эскалация может закончиться тем, что Telegram сам спишет Stars с вашего баланса позже. Обрабатывайте команду:
@router.message(Command("paysupport"))
async def on_paysupport(message: Message, db):
user_id = message.from_user.id
recent = await db.last_charges(user_id, limit=5)
if not recent:
return await message.answer(
"У нас нет недавних Stars-списаний от вас. "
"Откройте Настройки → Telegram Stars → Транзакции, чтобы увидеть ID транзакции бота."
)
buttons = [
[InlineKeyboardButton(
text=f"Вернуть {c.amount}⭐ от {c.paid_at:%Y-%m-%d}",
callback_data=f"refund:{c.charge_id}",
)] for c in recent
]
await message.answer(
"Выберите списание, которое хотите вернуть. "
"Возврат восстанавливает полную оригинальную сумму; частичные не поддерживаются.",
reply_markup=InlineKeyboardMarkup(inline_keyboard=buttons),
)
Два нюанса, которые надо усвоить:
- Всегда показывайте сумму и дату перед действием. Stars-покупки сливаются между собой, и возврат «не того» списания порождает второй тикет.
- Никогда не возвращайте автоматически без inline-подтверждения. Операторы, ставящие «каждый
/paysupport= мгновенный возврат», за неделю обнаруживают баланс бота на нуле — пользователи тестируют флоу.
Шаг 3 — Вызывайте refundStarPayment
Photo by Towfiqu barbhuiya on Pexels
Два аргумента, один вызов Bot API, один булев ответ. Минимальный обработчик для inline-кнопки из шага 2:
@router.callback_query(F.data.startswith("refund:"))
async def on_refund_confirm(query: CallbackQuery, bot: Bot, db):
charge_id = query.data.removeprefix("refund:")
charge = await db.get_charge(charge_id)
if not charge or charge.user_id != query.from_user.id:
return await query.answer("Списание не найдено.", show_alert=True)
if charge.refunded_at:
return await query.answer("Уже возвращено.", show_alert=True)
try:
await bot.refund_star_payment(
user_id=charge.user_id,
telegram_payment_charge_id=charge_id,
)
except TelegramBadRequest as e:
# CHARGE_ALREADY_REFUNDED, USER_ID_INVALID, CHARGE_ID_EMPTY, USER_BOT_REQUIRED
await db.log_refund_failure(charge_id, str(e))
return await query.answer(f"Ошибка возврата: {e.message}", show_alert=True)
await db.mark_refunded(charge_id, refunded_by=query.from_user.id)
await query.message.edit_text(
f"Возвращено {charge.amount}⭐ за {charge_id[:12]}…. "
f"Stars уже у вас в кошельке."
)
Поведение, которое надо учесть:
- Мгновенно и синхронно. Кошелёк пользователя пополняется, баланс бота списывается атомарно. Никакого «pending» состояния нет.
- Четыре документированные ошибки:
CHARGE_ALREADY_REFUNDED,CHARGE_ID_EMPTY,USER_BOT_REQUIRED,USER_ID_INVALID. Всё остальное — транспорт или rate-limit; повторяйте с backoff. - Частичных возвратов нет. Продали бандл на 1 000 Stars и пользователь оспаривает 200? Возврат полный + новый счёт за оставшееся. Планируйте размер SKU соответственно.
- Возврат подписочного списания не отменяет подписку. Следующее 30-дневное продление всё равно сработает, если вы также не вызовете
editUserStarSubscription(is_canceled=True)по тому жеtelegram_payment_charge_id. Сначала возврат, потом отмена.
Шаг 4 — Сверьте возврат в учёте
Photo by Mikhail Nilov on Pexels
Сторона бота — один вызов; бухгалтерии — три вещи, которые надо держать в соответствии:
- Внутренний леджер. Пометьте строку
refunded_at = now(), refunded_by = <admin user_id>. Не удаляйте оригинальное списание — возврат это дебет против существующего кредита. - Баланс в Stars-дашборде. Возвраты появляются мгновенно в Stars-out. Если вы выводите в TON по расписанию, возврат может опустить доступный баланс ниже 500-Star порога.
- Риск клоубэка. Если пользователь позже оспорит покупку через App Store или Google Play, Telegram оставляет за собой право списать дополнительные Stars с вашего баланса, чтобы покрыть тот возврат. Держите запас на высокостоимостных списаниях.
Для любого финансового handoff'а строка, нужная бухгалтеру: refund_id, original_charge_id, user_id, amount, original_paid_at, refunded_at, reason_code. Bot API не возвращает refund_id — синтезируйте из (charge_id + refunded_at).
Частые ошибки
Четыре ошибки, превращающие чистый возврат в спираль тикетов:
- Вызвать refund без сохранения результата. Если вы вызвали
refundStarPayment, но не записалиrefunded_at, следующий/paysupportснова покажет это списание как «доступное к возврату». Второй вызов вернётCHARGE_ALREADY_REFUNDED, и пользователь увидит ошибку. - Вернуть подписочное списание и забыть про
editUserStarSubscription. Пользователь ожидал «прекратите меня списывать»; вы выдали «верните деньги за прошлый месяц», но подписка осталась активной. Следующее продление через 30 дней — второй, злой тикет. - Авто-возврат с
/paysupportбез inline-подтверждения. Часть пользователей будут тапать, чтобы проверить, что будет. Inline-кнопка — это ваш контракт. - Воспринимать «нет окна допустимости» как «возврат когда угодно — безопасно». API не блокирует старые списания, но Telegram мог уже свести оригинальный платёж с Apple/Google. Возврат такого списания может оставить баланс бота отрицательным.
По теме
- Telegram Star Subscriptions: настройка для рекуррентного дохода — родительский материал. Любой возврат подписочного списания начинается там: вам нужен сохранённый
telegram_payment_charge_idизsuccessful_payment. - Монетизация Telegram Stars: набор инструментов для канала 2026 — более широкая Stars-поверхность. Обработка возвратов — операционный фундамент, что даёт всему остальному toolkit'у работать без потери доверия.
- Telegram-бот для авторского канала: пять часов в неделю и стабильный выход — соло-автор-фрейминг возвратов: когда тикет в неделю — норма, а когда это сигнал качества контента.
- Лимиты Telegram Bot API на масштабе — потолок throttle, действующий и на refund-флоу во время viral-баг'а.
Частые вопросы
Можно ли вернуть только часть Stars-платежа?
Нет. refundStarPayment принимает только user_id и telegram_payment_charge_id — без поля суммы, частичные возвраты не поддерживаются. Обходные пути: вернуть полностью и повторно выставить счёт за оставшееся; или выдать кредит в Stars-эквиваленте внутри бота.
Есть ли временной лимит на возврат Telegram Stars?
Telegram не документирует жёсткое окно допустимости. Единственный API-блокер — CHARGE_ALREADY_REFUNDED. Практически, возвраты старше ~3–6 месяцев рискованны, потому что Telegram мог уже свести оригинальную покупку с Apple/Google, и вы рискуете получить клоубэк-дебет позже.
Отменяет ли возврат подписочного списания саму подписку?
Нет. refundStarPayment возвращает Stars только за одно списание. Цикл продления продолжается. Чтобы остановить будущие продления, дополнительно вызовите editUserStarSubscription(user_id, telegram_payment_charge_id, is_canceled=True) по тому же charge ID. Сначала возврат, потом отмена.
Что происходит со Stars пользователя после возврата?
Мгновенно зачисляются обратно на Stars-баланс пользователя. Он может потратить их на любую другую Stars-поверхность, вывести через Fragment там, где это поддерживается, или — в случае клоубэка через Apple/Google — увидеть, как они исчезнут, когда платформа обработает собственный возврат.
Должен ли я обрабатывать /paysupport?
Да, на практике. UI Telegram направляет пользователей к /paysupport из Настроек → Stars. Бот, который её не обрабатывает, оставляет пользователя без in-chat пути решения; тот эскалирует до Telegram, который может списать Stars с вашего баланса для покрытия возврата. Обрабатывайте даже с простой «ответим в течение 24 часов».
Может ли пользователь оспорить Stars-покупку через Apple или Google?
Да — Stars покупаются через in-app purchase, поэтому возвраты на уровне платформы возможны. Если пользователь делает это после того, как вы уже поставили цифровой товар, Telegram может списать эквивалент Stars с баланса бота для компенсации. Держите Stars-запас против высокостоимостных списаний.
Итог
Возврат — это вызов API с двумя аргументами, обёрнутый в четырёхшаговую операционную дисциплину: решить, что возврат уместен, дать пользователю чистый /paysupport флоу, вызвать refundStarPayment с подтверждением, сверить учёт. Техническая поверхность крошечная; бизнес-поверхность — всё, что вокруг. Запустите обработчик /paysupport до следующего платного дропа — дивиденды доверия накапливаются, риск клоубэка уменьшается.
Подключите Autogram к боту — и пусть планировщик держит платные дропы на том же календаре, где живут refund-вебхуки.
Авторство фото
- Hero-изображение — фото Yan Krukau на Pexels
- Inline-изображение №1 — фото Towfiqu barbhuiya на Pexels
- Inline-изображение №2 — фото Mikhail Nilov на Pexels
Похожие посты

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

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

Telegram Star Subscriptions: настройка для рекуррентного дохода
Пошаговая настройка Telegram Star Subscriptions — invoice-ссылки, обработка повторных платежей, сохранение charge_id и чистая отмена через editUserStarSubscription.
Подпишитесь на рассылку
Получайте последние советы по росту Telegram, стратегии автоматизации и обновления платформы прямо на почту.
Или подпишитесь на наш Telegram-канал