2025, Nov 05 06:01

Как исправить PAYMENT_REQUIRED в Telethon при передаче подарков Telegram Stars

Столкнулись с RPCError 400: PAYMENT_REQUIRED в Telethon при TransferStarGiftRequest? Покажем, как переводить подарки Telegram Stars через инвойс и форму оплаты.

Отправка подарка Telegram Stars через Telethon может неожиданно завершиться ошибкой RPCError 400: PAYMENT_REQUIRED, даже если на счету достаточно звёзд и предмет не находится под торговым баном. Если ранее работавшая функция внезапно начала возвращать эту ошибку, в первую очередь стоит пересмотреть используемую последовательность вызовов.

Как воспроизвести проблему

Ниже функция пытается передать сохранённый подарок Stars напрямую через TransferStarGiftRequest. Получатель определяется с помощью get_input_entity, а в полезной нагрузке подарка передаётся его msg_id.

async def push_gift_async(tg, recipient_input, present_data):
    try:
        result = await tg(TransferStarGiftRequest(
            stargift=InputSavedStarGiftUser(msg_id=present_data['msg_id']),
            to_id=recipient_input
        ))
        return True
    except Exception as exc:
        err_text = str(exc)
        print(f"Gift sending failed: {err_text}")
        return False, err_text
# в другом месте
# recipient_input = await tg.get_input_entity(user_id)
# пример present_data: {"msg_id": 904312, "title": "Desk Calendar", "slug": "DeskCalendar-29932"}

В таком варианте вызов может завершаться следующей ошибкой:

RPCError 400: PAYMENT_REQUIRED (caused by TransferStarGiftRequest)

Что происходит на самом деле

Передача должна идти через платежный поток на основе инвойса. Вместо прямого вызова TransferStarGiftRequest сервер ожидает, что вы создадите инвойс для перевода, получите платежную форму и затем подтвердите её. Без этой последовательности может возникать PAYMENT_REQUIRED.

Решение: используйте поток с инвойсом и платежной формой

Рабочий подход — создать InputInvoiceStarGiftTransfer, получить форму через GetPaymentFormRequest и подтвердить её с помощью SendStarsFormRequest. msg_id по‑прежнему идентифицирует сохранённый подарок, а получатель передаётся как InputUser с id и access_hash.

from telethon.tl.functions.payments import GetPaymentFormRequest, SendStarsFormRequest
from telethon.tl.types import InputUser, InputInvoiceStarGiftTransfer, InputSavedStarGiftUser
async def transfer_gift_via_invoice(tg, recipient_input, present_data):
    bill_payload = InputInvoiceStarGiftTransfer(
        stargift=InputSavedStarGiftUser(msg_id=present_data['msg_id']),
        to_id=InputUser(
            user_id=recipient_input.user_id,
            access_hash=recipient_input.access_hash
        )
    )
    pay_form = await tg(GetPaymentFormRequest(invoice=bill_payload))
    await tg(SendStarsFormRequest(
        form_id=pay_form.form_id,
        invoice=bill_payload
    ))
    return True

Эта последовательность соответствует ожидаемому платежному потоку для передачи сохранённого подарка Stars.

Почему это важно

Работая с Telegram Stars, необходимо придерживаться платежного процесса, который навязывает API. Низкоуровневый вызов передачи без инвойса может приводить к PAYMENT_REQUIRED, даже если баланс в норме. Использование инвойса и формы гарантирует, что перевод проходит проверку на стороне сервера в шаге оплаты.

Выводы

Если столкнулись с RPCError 400: PAYMENT_REQUIRED при TransferStarGiftRequest, переходите на схему с инвойсом. Соберите InputInvoiceStarGiftTransfer для выбранного msg_id сохранённого подарка и точного получателя, получите форму через GetPaymentFormRequest и завершите перевод через SendStarsFormRequest. Это минимальное изменение делает отправку подарков стабильной и согласованной с текущим потоком API.

Статья основана на вопросе на StackOverflow от morz1k3 и ответе aayco.