Обзор
Подарочные подписки позволяют пользователям Cabinet покупать VPN-подписки и дарить их другим людям. Начиная с v3.29.0 (бот) и v1.30.0 (Cabinet) основной сценарий — покупка по коду: покупатель получает уникальный подарочный код, который можно передать любым способом. Получатель активирует код в боте или в Cabinet. Прежний способ — указание получателя при покупке (email / Telegram username) — по-прежнему поддерживается.Возможности
- Код-подарок — покупка без указания получателя, передача кода любым удобным способом
- Активация кода через deep link бота (
t.me/bot?start=GIFT_XXXXXXXXXXXX) или в Cabinet (вкладка «Активировать») - Отправка подписки по email или Telegram username (классический способ)
- Оплата с баланса (мгновенно) или через платёжную систему
- Выбор тарифа и периода подписки
- Персональное сообщение для получателя (до 1000 символов)
- 3 вкладки в разделе подарков: Купить, Активировать, Мои подарки
- Защита от активации собственного кода
- Rate limiting: 5 подарков в минуту
Включение функции
Через Admin Cabinet
- Откройте Cabinet → Админ-панель → Настройки
- Найдите переключатель Подарочные подписки (Gift Subscriptions)
- Включите его
Переключатель сохраняется в базе данных как системная настройка
CABINET_GIFT_ENABLED. Перезапуск бота не требуется.Через API
RBAC права
Для управления настройкой требуется разрешениеsettings:edit. Для чтения — settings:read.
Для пользователей
Интерфейс Cabinet
Раздел подарков в Cabinet содержит 3 вкладки:| Вкладка | Назначение |
|---|---|
| Купить | Выбор тарифа, периода и оплата. Указание получателя не обязательно — по умолчанию создаётся код-подарок |
| Активировать | Ввод подарочного кода для активации полученной подписки |
| Мои подарки | Три секции: Активные (ожидают активации), Активированные (использованные), Полученные |
Покупка подарка (код-подарок)
Основной сценарий — покупка без указания получателя:Оплатите
- С баланса — списание мгновенное, код генерируется сразу
- Через платёжную систему — код генерируется после подтверждения оплаты
Код можно передать двумя способами:
- Deep link бота:
t.me/bot?start=GIFT_XXXXXXXXXXXX— получатель нажимает ссылку и активирует подписку в Telegram - Ссылка на Cabinet:
cabinet.url/gift?tab=activate&code=TOKEN— получатель активирует код в веб-интерфейсе
Покупка подарка с указанием получателя (классический способ)
По-прежнему можно указать получателя при покупке:Активация подарочного кода
В Cabinet
- Откройте раздел Подарить подписку → вкладка Активировать
- Введите подарочный код (минимум 8 символов)
- Подписка активируется мгновенно
Через deep link бота
- Новый пользователь: отправьте ссылку
t.me/bot?start=GIFT_XXXXXXXXXXXX— после регистрации подписка активируется автоматически - Существующий пользователь: при переходе по ссылке подписка активируется сразу
Статус подарка
После покупки через платёжную систему отображается страница ожидания с автоматическим опросом статуса оплаты. Когда платёж подтверждён:- Код-подарок — отображается подарочный код для передачи получателю
- С указанием получателя — подарок доставляется получателю автоматически
Процесс покупки
Код-подарок: оплата с баланса
Код-подарок: оплата через платёжную систему
Активация подарочного кода
Классический способ (с указанием получателя)
При указанииrecipient_type и recipient_value поведение не изменилось — подписка доставляется получателю после оплаты, как и раньше.
Резолвинг Telegram-получателя
При указании Telegram username бот пытается найти пользователя:- База данных — поиск по username среди существующих пользователей
- Bot API — запрос через
getChatдля полученияuser_id - Если не удалось найти — покупка создаётся с предупреждением
recipient_warning
Если получатель не найден в момент покупки, подарок будет ожидать активации. Когда получатель запустит бота через
/start, подписка активируется автоматически.API эндпоинты
GET /cabinet/gift/config
Конфигурация подарков. Возвращает доступные тарифы, периоды, платёжные системы и баланс. Ответ:POST /cabinet/gift/purchase
Создание подарочной покупки. Поляrecipient_type и recipient_value опциональны — если не указаны, создаётся код-подарок.
Запрос (код-подарок, без получателя):
Поле
purchase_token в ответе содержит усечённый код (12 символов). Полный 64-символьный токен никогда не покидает сервер.GET /cabinet/gift/purchase/
Статус подарочной покупки. Поддерживает поиск по префиксу токена (минимум 8 символов). Доступно только покупателю. Ответ:POST /cabinet/gift/activate
Активация подарочного кода. Поиск по префиксу (минимум 8 символов). Запрос:| Код | Описание |
|---|---|
| 400 | Попытка активировать собственный подарок |
| 404 | Код не найден (единообразный ответ для предотвращения перебора) |
| 410 | Код уже активирован |
| 429 | Превышен лимит запросов |
GET /cabinet/gift/pending
Список ожидающих подарков для текущего пользователя (как получателя).Безопасность
Защита токенов
- Полный 64-символьный токен никогда не покидает сервер — в API-ответах возвращается усечённый 12-символьный код
- Для активации требуется минимум 8 символов кода (поиск по префиксу)
- Единообразные 404-ответы — предотвращают перебор токенов (token enumeration)
Защита от race conditions
- Активация использует
SELECT FOR UPDATE— блокировка строки предотвращает двойную активацию при параллельных запросах
Rate limiting
- Эндпоинт активации имеет отдельный rate limit
- Покупка: 5 подарков в минуту
Защита от самоактивации
Покупатель не может активировать собственный код:- API возвращает 400 Bad Request
- В боте deep link с собственным кодом игнорируется
Gateway webhook и код-подарки
Код-подарки (
is_code_only=true, is_gift=True без получателя) обрабатываются иначе при получении webhook от платёжной системы:- С получателем: webhook →
fulfill_purchase()→ создание подписки → уведомление получателя - Код-подарок: webhook → генерация кода → подписка НЕ создаётся (создаётся при активации кода)
Deep link активация в боте
Формат deep link
GIFT_ обязателен. После него — подарочный код (12 символов).
Сценарии
| Ситуация | Поведение |
|---|---|
| Новый пользователь | /start GIFT_XXXXXXXXXXXX → регистрация → автоматическая активация подарка |
| Существующий пользователь | /start GIFT_XXXXXXXXXXXX → немедленная активация |
| Код принадлежит этому пользователю | Код игнорируется (без ошибки) |
| Код уже использован | Сообщение об ошибке |
| Неверный код | Сообщение об ошибке |
Транзакции
Подарочные платежи записываются с типомGIFT_PAYMENT:
- Сумма отрицательная (списание с баланса покупателя)
payment_method—Noneдля оплаты с баланса, идентификатор провайдера для gateway-оплаты- Описание: формат с указанием тарифа (и получателя, если указан)
Подарочные платежи с баланса (
payment_method=None) не учитываются в статистике доходов, так как REAL_PAYMENT_METHODS не включает NULL.Устранение проблем
Раздел подарков не отображается
- Функция включена? Проверьте
GET /cabinet/branding/gift-enabled CABINET_ENABLED=true?- Хотя бы один тариф создан и активен?
Код подарка не активируется
- Код введён верно? Минимум 8 символов
- Это не ваш собственный код? Покупатель не может активировать свой подарок
- Код уже был использован? Проверьте вкладку «Мои подарки» → «Активированные»
- Проверьте логи:
Получатель не получает подарок (классический способ)
- Telegram username указан корректно (с
@)? - Получатель запустил бота? Если нет — подарок ожидает активации через
/start - Проверьте логи:
Ошибка «Нельзя активировать собственный подарок»
Система запрещает активацию собственного подарочного кода. Передайте код другому пользователю.Ошибка rate limit
Максимум 5 подарочных покупок за 60 секунд. Подождите и попробуйте снова.Deep link не работает
- Формат ссылки верный?
t.me/bot?start=GIFT_XXXXXXXXXXXX - Префикс
GIFT_присутствует? - Бот обновлён до v3.29.0+?
