Перейти к содержимому

Подарочные подписки

Покупатель выбирает подписку в разделе Бонусы → Мои подарки → Подарить. После оплаты он получает ссылку, по которой другой пользователь самостоятельно активирует подписку. Срок начинается при активации, а не при покупке. У неактивированного подарка нет срока годности.

Вкладка «Бонусы» появляется при первом открытии приложения, если включены подарки или реферальная программа. Доступность покупок приходит в /me как settings.gifts_enabled, независимо от загрузки списка подарков. При отключении покупок уже оплаченные подарки и сохранённые ссылки остаются доступны. Карточка «Мои подарки» использует общий компонент карточки и отступы раздела «Бонусы».

  • Доступны опубликованные тарифы на срок, их периоды и настроенные гибкие лимиты устройств, обычного и premium-трафика. Пакеты трафика без срока и продление отдельных устройств в подарок не продаются.
  • Покупатель может применить промокод. Скидка учитывается при оплате, а промодни и бонусный трафик передаются получателю. Использование промокода закрепляется за покупателем и платежом.
  • Поддерживаются доступные разовые способы оплаты, личный баланс и партнёрский баланс, включая доплату внешним способом в рамках обычного checkout. Tribute и способы с подпиской, управляемой провайдером, для подарков недоступны; автопродление подарка не включается.
  • Покупка подарка не меняет подписку покупателя. Повторный webhook одного платежа не создаёт второй подарок.
  • До подтверждения оплаты показывается ожидание с кнопкой возврата к оплате. Ссылка появляется после успешной выдачи подарка и сохраняется в «Моих подарках».

Переход в раздел можно добавить в рассылку кнопкой Раздел приложения → Бонусы или подстановкой {gifts_link} в тексте. Это ссылка на раздел покупки, а не на конкретный подарок. Плашка покупки на главной странице не показывается.

  1. Получатель открывает ссылку и входит в существующий аккаунт либо проходит регистрацию. Приложение сохраняет ожидающий подарок в браузере до завершения входа. Несколько открытых ссылок сохраняются в очереди.
  2. В окне подарка получатель проверяет тариф, срок, лимиты и аккаунт, для которого будет выполнена активация, затем подтверждает её. Один переход по ссылке ничего не активирует.
  3. После успешной активации подарок нельзя передать повторно. Повторный запрос того же получателя возвращает результат без повторного начисления срока.

Ссылка является секретом: подарок получает тот, кто первым подтвердит активацию. Email доставки не ограничивает аккаунт получателя. Покупатель не может активировать собственный неиспользованный подарок. При смене устройства, очистке данных браузера или недоступном локальном хранилище следует снова открыть исходную ссылку.

Для действующей подписки с совместимыми условиями подарок продлевает срок. При другом тарифе, изменившемся составе прав или включённом автопродлении активация блокируется: нужно дождаться окончания текущей подписки либо отключить автопродление. Подарок при этом сохраняется. Для trial используется правило TRIAL_DAYS_STRATEGY, сохранённое при оформлении подарка: add_remaining сохраняет остаток trial, start_from_payment начинает оплаченный срок с активации подарка.

Если Remnawave временно недоступен, подарок закрепляется за получателем в состоянии «Активируется». Другой аккаунт его уже не заберёт. Worker повторяет активацию; получатель также может повторить попытку. До завершения этой операции другие изменения оплаченной подписки не должны конкурировать с ней.

После успешной активации Web App заново загружает данные аккаунта, закрывает окно подарка и открывает главную страницу, чтобы активная подписка отображалась без ручного обновления.

При создании платежа сохраняются тариф, длительность, цены, выбранные лимиты и условия промокода. Изменение, скрытие или удаление тарифа из каталога не подменяет оплаченные условия. После активации подписка хранит снимок тарифа, который используют выдача прав и фоновые обновления лимитов и сквадов. Обычная последующая покупка или смена тарифа может заменить эти условия условиями нового заказа.

Снимок не создаёт заново удалённые объекты Remnawave: если администратор удалит используемые сквады или серверы из самой панели, необходимо восстановить доступность соответствующих ресурсов. Неактивированный подарок остаётся в базе, а не исчезает из-за отсутствия каталога.

При настроенных SMTP и SUBSCRIPTION_MINI_APP_URL покупатель может включить отправку подарка на указанный email. Письмо отправляет worker после подтверждения оплаты. При ошибке выполняется до пяти попыток с интервалом не менее пяти минут; статус виден покупателю и администратору. Сбой доставки не отменяет подарок: покупатель может скопировать ссылку и отправить её сам. При прерывании процесса после принятия письма SMTP-сервером возможна повторная доставка того же письма с той же ссылкой.

Покупателю с доступным Telegram отправляется сообщение со ссылкой. В настроенный админский Telegram лог-чат поступает уведомление о покупке с пометкой подарка и номером платежа. Отдельные записи журнала: gift_purchased, gift_activated, gift_email_delivery. Они содержат идентификаторы и результат операции; секретную ссылку в админский журнал покупки или доставки не записывают.

  • Подарки → Создать подарок выдает бесплатный подарок от администратора. Можно выбрать опубликованный тариф, срок и доступные гибкие лимиты, а при настроенной почте — email получателя. Оплата, промокод и списания с балансов не нужны. Лимиты, тариф и срок сохраняются так же, как для оплаченного подарка; изменение или скрытие тарифа не меняет выданный подарок.

  • Создателем и владельцем такого подарка становится администратор. Ссылка доступна сразу после создания и повторно в карточке подарка для авторизованных администраторов. Ссылки покупательских подарков в админке не раскрываются. В общем списке секретных ссылок нет.

  • Бесплатная выдача сохраняется как успешная операция с суммой 0, провайдером admin_gift и источником admin_grant. Она не входит в денежную выручку, число внешних платежей и средний чек. В финансовой статистике есть отдельные счетчики выданных и активированных бесплатных подарков за все время; отмененные выдачи исключаются. Партнерские комиссии и реферальные бонусы за бесплатную выдачу не начисляются.

  • Создание фиксируется в журнале как gift_created_by_admin с автором и ID операции и отправляется в административный Telegram-лог через обычное событие успешной операции. Повтор запроса с тем же request_id возвращает тот же подарок, даже если тариф уже скрыт; повторной выдачи и повторного события не происходит. Email отправляется через существующую очередь доставки. Недоступность почты не лишает администратора ссылки.

  • Административная выдача доступна независимо от GIFTS_ENABLED: этот переключатель управляет пользовательскими покупками. Получение уже созданного подарка остается доступным.

  • Настройки → Общие → Подарочные подписки, параметр GIFTS_ENABLED (по умолчанию True), управляет новыми покупками. Выключение не мешает оплате уже созданного платежа, просмотру истории, доставке и активации уже оплаченных подарков. Настройка независима от REFERRAL_PROGRAM_ENABLED.

  • Раздел Подарки показывает покупателя, получателя, тариф, сумму, провайдера, дату и статус. Есть поиск, фильтры статуса и источника, сортировка и страницы по 25 записей; на мобильном — карточки. Кнопки с иконками открывают карточку подарка и карточки пользователей.

  • В карточке доступны сохранённый состав, промобонусы, скидка, списания с личного и партнёрского балансов, платёж и результат доставки email. В пользовательской истории показываются последние 100 покупок; полная история доступна администратору.

  • Администратор может отозвать только оплаченный подарок в состоянии ready. Операция блокирует платёж и подарок, поэтому не конкурирует с начавшейся активацией; activating и activated подарки не отзываются. По умолчанию она возвращает покупателю полную фактически оплаченную стоимость (checkout_total_amount, с fallback на amount) на личный баланс одним идемпотентным ledger entry gift_refund. Возврат сохраняет администратора и обязательную причину, включает всю смешанную оплату и выполняется даже при выключенном балансе: кредит остаётся у пользователя до последующего включения баланса.

  • Для доставки и восстановления незавершённых активаций должен работать worker. При обновлении сначала применяются миграции 0077_subscription_gifts и 0078_gift_entitlements штатным сервисом migrate.

API покупки использует существующий checkout с gift: true и необязательным gift_recipient_email. Авторизованные маршруты: GET /api/gifts/options, GET /api/gifts, POST /api/gifts/preview, POST /api/gifts/claim; административный список — GET /api/admin/gifts. Точный контракт находится в OpenAPI.

Административная выдача: GET /api/admin/gifts/options, POST /api/admin/gifts (request_id, plan_id, необязательные checkout_addons и recipient_email). Просмотр отдельной карточки: GET /api/admin/gifts/{gift_id}. POST /api/admin/gifts/{gift_id}/revoke принимает обязательную reason, а также restore_promo_usage и refund_to_balance. Доступ ко всем этим маршрутам проверяется по административной авторизации; клиент не может задать сумму или источник средств.