Режимы продаж
Бот поддерживает два режима продажи подписок. Переключение — через переменную SALES_MODE в .env или в админ-панели: Настройки → Подписки.
| Режим | SALES_MODE | Описание |
|---|
| Конструктор | classic | Пользователь сам выбирает период, трафик, серверы, устройства |
| Тарифы | tariffs | Готовые тарифные планы с фиксированными параметрами |
Конструктор (classic)
Режим по умолчанию. Пользователь самостоятельно собирает подписку из компонентов:
- Период — выбор из
AVAILABLE_SUBSCRIPTION_PERIODS
- Трафик — пакет из
TRAFFIC_PACKAGES_CONFIG или фиксированный лимит
- Серверы — один или несколько (автопропуск при одном сервере)
- Устройства — от
DEFAULT_DEVICE_LIMIT до MAX_DEVICES_LIMIT
Настройка периодов и цен
# Доступные периоды (дни, через запятую)
AVAILABLE_SUBSCRIPTION_PERIODS=30,90,180
# Доступные периоды для продления (могут отличаться)
AVAILABLE_RENEWAL_PERIODS=30,90,180
# Цены за каждый период (в копейках)
PRICE_14_DAYS=7000
PRICE_30_DAYS=10000
PRICE_60_DAYS=25900
PRICE_90_DAYS=36900
PRICE_180_DAYS=69900
PRICE_360_DAYS=109900
# Базовая надбавка к цене (в копейках, по умолчанию 0)
BASE_SUBSCRIPTION_PRICE=0
Формула расчёта цены
Итого = Цена периода + Стоимость трафика × месяцев + Доп. устройства × месяцев + Доп. серверы × месяцев
Количество месяцев рассчитывается как round(период_дней / 30), минимум 1.
Пример для 180 дней (6 месяцев):
| Компонент | Расчёт | Итого |
|---|
| Базовый период | PRICE_180_DAYS | 699 руб |
| Трафик безлимит | 200 руб/мес × 6 мес | 1 200 руб |
| 4 устройства (3 бесплатно + 1 доп.) | 100 руб/мес × 6 мес | 600 руб |
| 2 доп. сервера | 100 руб/мес × 6 мес | 1 200 руб |
| Итого | | 3 699 руб |
Тарифы (tariffs)
Готовые тарифные планы — пользователь выбирает тариф из списка и период оплаты.
Тарифы создаются и управляются в админ-панели: Админ → Тарифы.
Что входит в тариф
Каждый тариф включает фиксированные параметры:
| Параметр | Описание |
|---|
| Название | Отображаемое имя (например, «Premium», «Basic») |
| Описание | Текстовое описание тарифа |
| Трафик | Фиксированный лимит в ГБ (0 = безлимит) |
| Устройства | Базовое количество устройств |
| Серверы | Список доступных серверов (сквадов) |
| Цены за периоды | JSON: {"30": 50000, "90": 120000, "180": 200000} |
| Порядок отображения | Сортировка в списке (display_order) |
| Уровень (tier) | Для визуального оформления (1 = базовый) |
Расширенные возможности тарифов
Тарифы поддерживают дополнительные настройки, которых нет в классическом режиме:
| Возможность | Описание |
|---|
| Докупка устройств | device_price_kopeks — цена за доп. устройство, max_device_limit — максимум |
| Докупка трафика | traffic_topup_enabled — разрешение, traffic_topup_packages — пакеты {"5": 5000, "10": 9000} |
| Суточный тариф | is_daily + daily_price_kopeks — ежедневное списание с баланса |
| Произвольные дни | custom_days_enabled + price_per_day_kopeks — покупка на любое количество дней |
| Произвольный трафик | custom_traffic_enabled + traffic_price_per_gb_kopeks — покупка произвольного объёма |
| Режим сброса трафика | traffic_reset_mode — DAY / WEEK / MONTH / NO_RESET (или глобальная настройка) |
| Доступ по промогруппам | Ограничение тарифа для определённых промогрупп |
| Триал на тарифе | is_trial_available — можно ли взять триал на этом тарифе |
Триал в режиме тарифов
# ID тарифа для триала (0 = стандартные настройки триала)
TRIAL_TARIFF_ID=0
Если указан ID тарифа, параметры триала (трафик, устройства, серверы) берутся из тарифа. Длительность триала всё равно определяется TRIAL_DURATION_DAYS.
Сравнение режимов
| Возможность | Конструктор | Тарифы |
|---|
| Выбор периода | Из AVAILABLE_SUBSCRIPTION_PERIODS | Из period_prices тарифа |
| Выбор трафика | Пакеты или фиксированный | Фиксирован в тарифе |
| Выбор серверов | Из доступных | Фиксированы в тарифе |
| Выбор устройств | От DEFAULT_DEVICE_LIMIT до MAX_DEVICES_LIMIT | Фиксированы + докупка (опционально) |
| Суточное списание | Нет | Да (is_daily) |
| Произвольные дни | Нет | Да (custom_days_enabled) |
| Произвольный трафик | Нет | Да (custom_traffic_enabled) |
| Скидки промогрупп | На период, серверы, трафик, устройства | На период (% от цены тарифа) |
| Простая покупка | Да | Нет (и так упрощённый UX) |
Режимы продажи трафика
Применяются только в режиме конструктора (classic).
Выбираемые пакеты (selectable)
Пользователь выбирает пакет трафика из списка.
TRAFFIC_SELECTION_MODE=selectable
TRAFFIC_PACKAGES_CONFIG="5:2000:false,10:3500:false,50:11000:true,100:15000:true,0:20000:true"
Формат каждого пакета: ГБ:цена_копейки:показать_безлимит. Значение 0 ГБ означает безлимит.
Цена безлимитного трафика также задаётся отдельно:
PRICE_TRAFFIC_UNLIMITED=20000
Фиксированный лимит (fixed)
Все подписки создаются с одинаковым объёмом трафика.
TRAFFIC_SELECTION_MODE=fixed
FIXED_TRAFFIC_LIMIT_GB=100
0 означает безлимит.
Докупка трафика
Позволяет пользователю докупить трафик к существующей подписке. Трафик докупается пакетами на 1 месяц — при следующем сбросе трафика докупленный объём обнуляется вместе с основным.
# Включить докупку трафика
TRAFFIC_TOPUP_ENABLED=true
# Показывать кнопку в меню
BUY_TRAFFIC_BUTTON_VISIBLE=true
# Пакеты для докупки (формат: "гб:цена_копейки:enabled")
# Пустая строка = использовать TRAFFIC_PACKAGES_CONFIG
TRAFFIC_TOPUP_PACKAGES_CONFIG=10:5000:true,25:10000:true,50:15000:true,100:25000:true
Докупленный трафик действует до следующего сброса (по стратегии traffic_reset_mode). Это не разовая прибавка навсегда, а месячный пакет.
В режиме тарифов докупка трафика настраивается индивидуально для каждого тарифа: traffic_topup_enabled, traffic_topup_packages, max_topup_traffic_gb.
Сброс трафика
Пользователь может сбросить счётчик использованного трафика за плату.
# Режим расчёта цены сброса
TRAFFIC_RESET_PRICE_MODE=traffic_with_purchased
| Режим | Описание |
|---|
period | Фиксированная цена = стоимость 30-дневного периода (PRICE_30_DAYS) |
traffic | Цена = стоимость текущего пакета трафика подписки |
traffic_with_purchased | Цена = стоимость базового + докупленного трафика (рекомендуется) |
# Базовая цена сброса в копейках (0 = использовать PRICE_30_DAYS)
TRAFFIC_RESET_BASE_PRICE=0
# Глобальная стратегия сброса трафика
DEFAULT_TRAFFIC_RESET_STRATEGY=MONTH
# Сбрасывать трафик при каждой оплате подписки
RESET_TRAFFIC_ON_PAYMENT=false
Режим period может быть использован для абьюза — пользователь с дорогим трафиком будет сбрасывать его по цене 30-дневного периода. Рекомендуется traffic_with_purchased.
Управление устройствами
В режиме конструктора
# Базовое количество устройств (бесплатно)
DEFAULT_DEVICE_LIMIT=3
# Максимум устройств для покупки (0 = без лимита)
MAX_DEVICES_LIMIT=15
# Цена за каждое дополнительное устройство (копейки/месяц)
PRICE_PER_DEVICE=10000
# Включить выбор количества устройств
DEVICES_SELECTION_ENABLED=true
# Количество устройств, если выбор отключён (0 = не назначать)
DEVICES_SELECTION_DISABLED_AMOUNT=0
Если DEVICES_SELECTION_ENABLED=false, пользователь не видит шаг выбора устройств. Всем подпискам назначается DEVICES_SELECTION_DISABLED_AMOUNT устройств (или DEFAULT_DEVICE_LIMIT, если 0).
В режиме тарифов
Базовое количество устройств задаётся в тарифе (device_limit). Если device_price_kopeks указан — пользователь может докупить устройства до max_device_limit.
Простая покупка подписки
Упрощённый режим — кнопка «Купить подписку» без пошагового конструктора. Все параметры фиксированы.
SIMPLE_SUBSCRIPTION_ENABLED=true
# Фиксированный период (должен быть в AVAILABLE_SUBSCRIPTION_PERIODS)
SIMPLE_SUBSCRIPTION_PERIOD_DAYS=30
# Фиксированное количество устройств
SIMPLE_SUBSCRIPTION_DEVICE_LIMIT=1
# Фиксированный трафик в ГБ (0 = безлимит)
SIMPLE_SUBSCRIPTION_TRAFFIC_GB=0
# UUID сквада (пустой = серверы по умолчанию)
# SIMPLE_SUBSCRIPTION_SQUAD_UUID=
Простая покупка доступна только в режиме конструктора (classic). В режиме тарифов UX и так упрощён — пользователь просто выбирает тариф и период.
Тестовая подписка (триал)
TRIAL_DURATION_DAYS=3
TRIAL_TRAFFIC_LIMIT_GB=10
TRIAL_DEVICE_LIMIT=1
# Платный триал (0 = бесплатно)
TRIAL_PAYMENT_ENABLED=false
TRIAL_ACTIVATION_PRICE=0
# Плюсовать оставшиеся дни триала при покупке платной подписки
TRIAL_ADD_REMAINING_DAYS_TO_PAID=false
Триал включает:
- Настраиваемый период, трафик, устройства
- Уведомления об истечении
- Автоконверсию в платную подписку
- Контроль обязательной подписки на канал
- Платный триал с выбором способа оплаты (если
TRIAL_ACTIVATION_PRICE > 0)
Промогруппы и скидки
Промогруппы — основной инструмент скидочной системы. У каждого пользователя может быть несколько промогрупп. Для расчёта скидки используется группа с наивысшим приоритетом.
Параметры промогруппы
| Параметр | Описание |
|---|
name | Название группы |
priority | Приоритет (чем выше — тем важнее) |
server_discount_percent | Скидка на серверы (%) |
traffic_discount_percent | Скидка на трафик (%) |
device_discount_percent | Скидка на устройства (%) |
period_discounts | Скидки за длительные периоды: {"60": 10, "90": 20, "180": 40} |
auto_assign_total_spent_kopeks | Авто-назначение при достижении суммы трат (лояльность) |
apply_discounts_to_addons | Применять скидки к доп. услугам |
Как скидки работают в режиме конструктора
В конструкторе каждый компонент стоимости дисконтируется отдельно:
- Цена периода — скидка
period_discounts[период_дней]%
- Трафик — скидка
traffic_discount_percent%
- Устройства — скидка
device_discount_percent%
- Серверы — скидка
server_discount_percent%
Итого = (Период - скидка) + (Трафик - скидка) + (Устройства - скидка) + (Серверы - скидка)
Пример: промогруппа «VIP» со скидкой 20% на серверы, 15% на трафик, 10% на устройства:
| Компонент | Без скидки | Скидка | Итого |
|---|
| Период 90 дней | 369 руб | 0% | 369 руб |
| Трафик 100 ГБ | 150 руб/мес × 3 мес = 450 руб | 15% = 67 руб | 383 руб |
| 2 доп. устройства | 100 руб/мес × 3 мес = 300 руб | 10% = 30 руб | 270 руб |
| 1 сервер | 100 руб/мес × 3 мес = 300 руб | 20% = 60 руб | 240 руб |
| Итого | 1 419 руб | 157 руб | 1 262 руб |
Как скидки работают в режиме тарифов
В тарифном режиме промогруппа применяет скидку за период (period_discounts) к итоговой цене тарифа:
Итого = Цена тарифа за период - period_discounts[период]%
Скидки на серверы, трафик и устройства в режиме тарифов не применяются — эти параметры фиксированы и уже включены в цену тарифа.
Пример: тариф «Premium» стоит 5 000 руб/90 дней. Промогруппа с period_discounts: {"90": 20}:
5 000 руб - 20% = 4 000 руб
Скидки за период для базовых пользователей
Для пользователей без промогруппы (или в группе is_default=true) можно включить скидки за длительные периоды через .env:
# Включить скидки за период для базовых пользователей
BASE_PROMO_GROUP_PERIOD_DISCOUNTS_ENABLED=false
# Формат: период_дней:процент_скидки
BASE_PROMO_GROUP_PERIOD_DISCOUNTS=60:10,90:20,180:40,360:70
Эти скидки не работают для пользователей в именных промогруппах — у тех свои period_discounts.
BASE_PROMO_GROUP_PERIOD_DISCOUNTS применяются как скидка ко всем компонентам (серверы, трафик, устройства), если у базовой группы server_discount_percent, traffic_discount_percent и device_discount_percent равны 0. Это сделано для упрощения — базовые пользователи получают единую скидку за длительный период.
Система лояльности
Промогруппы автоматически назначаются по сумме трат:
Промогруппа «Silver» → auto_assign_total_spent_kopeks = 500000 (5 000 руб)
Промогруппа «Gold» → auto_assign_total_spent_kopeks = 1500000 (15 000 руб)
Промогруппа «VIP» → auto_assign_total_spent_kopeks = 5000000 (50 000 руб)
При достижении порога пользователь автоматически повышается на следующий уровень.
Приоритет промогрупп
Пользователь может состоять в нескольких промогруппах (например, назначенная вручную + за лояльность). Для расчёта скидки используется группа с наивысшим priority. При одинаковом приоритете — группа с большим id.
Ограничение тарифов по промогруппам
В режиме тарифов можно ограничить доступ к тарифу по промогруппам. Если у тарифа задан список allowed_promo_groups — его увидят только пользователи из этих групп. Если список пуст — тариф доступен всем.
Модем-подписки
Дополнительный функционал для устройств-модемов.
# Включить модем-функционал
MODEM_ENABLED=false
# Цена модема за месяц (копейки)
MODEM_PRICE_PER_MONTH=10000
# Скидки за длительный срок: "месяцев:процент"
MODEM_PERIOD_DISCOUNTS=3:15,6:20,12:25
Сквозная корзина
Система сохраняет выбранные параметры при недостатке баланса:
- Пользователь выбирает подписку
- Баланса не хватает — корзина сохраняется в Redis (TTL 1 час)
- Пользователь пополняет баланс
- Кнопка «Вернуться к оформлению» восстанавливает корзину
- Подписка оформляется автоматически
Для работы корзины требуется Redis: REDIS_URL=redis://redis:6379/0
Автопродление
Бот автоматически продлевает подписки при наличии средств на балансе:
- Фоновый сервис мониторинга проверяет подписки по расписанию
- За N дней до истечения — уведомление пользователю
- При наличии средств — автоматическое продление
- При недостатке — уведомление о необходимости пополнения
- Поддержка настройки дня списания
Промо-коды
| Тип | Описание |
|---|
| Деньги | Начисляет сумму на баланс |
| Дни подписки | Продлевает подписку на N дней |
| Триал | Выдаёт пробную подписку |
| Промогруппа | Назначает промогруппу со скидками |