Покупка, триал, смена тарифа
Кнопка «Купить VPN» ведёт в один из двух режимов продаж — переключается настройкой SALES_MODE:
| Значение | Флоу |
|---|---|
plans (дефолт) | Каталог готовых тарифов: тариф → срок → оплата |
constructor | Юзер собирает подписку сам: срок → пакет трафика → оплата |
Тарифы, сроки, цены, периоды и пакеты трафика настраиваются в кабинете — Тарифы.
Каталог тарифов
Юзер видит список тарифов с трафиком и ценой «от …» прямо в кнопках, выбирает срок — и уже в списке сроков цена показана финальная, со всеми его скидками: цена на витрине всегда равна сумме списания. Скидки складываются: промо-группа + персональная + одноразовая с промокода + активная акция, кап — 100 % (при 100 % покупка проходит бесплатно, без счёта).
Конструктор
Два шага: срок (из настроенных периодов, у каждого своя цена) и трафик (пакет гигабайт или ∞ — пакет с 0 ГБ значит безлимит). Итог = цена периода + цена пакета, скидки применяются так же. Лимит устройств берётся из настройки DEFAULT_DEVICE_LIMIT (дефолт 3).
NEW / RENEW / CHANGE
Тип покупки бот определяет сам, юзеру думать не нужно:
- активная подписка на этот же тариф → RENEW — продление той же подписки, тот же panel-user, ссылка подключения не меняется;
- активная подписка на другой тариф → CHANGE — смена тарифа с зачётом остатка;
- подписки нет → NEW.
Логика общая для бота и мини-аппы — оба фронта ведут себя одинаково.
Смена тарифа с зачётом остатка
При CHANGE неиспользованные дни текущего тарифа превращаются в денежный кредит: оставшиеся дни × (фактически оплачено / оплаченных дней) — считается от суммы, которую юзер реально платил, а не от прайса. Кредит вычитается из финальной цены (не больше её самой), на экране оплаты юзер видит строку «Зачтён остаток текущего тарифа: −X ₽». Подписка остаётся той же — ключи и ссылка у юзера не меняются. Триальные подписки кредита не дают.
Оплата
На экране оплаты кнопки собираются динамически:
- С баланса — если включён кошелёк (
BALANCE_ENABLED, дефолт вкл); кнопка сразу показывает баланс и ✅/❌ хватает ли; - Telegram Stars — всегда; цена пересчитывается в ★ по курсу
STARS_RATE_RUB(дефолт 130 коп/★, округление вверх), инвойс приходит прямо в чат; - каждый включённый онлайн-шлюз — карта/СБП/крипта; кнопка появляется сама, как только провайдер активирован в кабинете (Платежи).
Если скидки ещё нет, на экране есть кнопка «🎟 У меня промокод» — применить код можно не выходя из оплаты.
Оплата с баланса проходит в одной транзакции: списание, выдача на панели и запись подписки либо происходят целиком, либо целиком откатываются — при сбое панели деньги не списываются. Онлайн-оплата: бот создаёт счёт, юзер платит по кнопке «Оплатить», подписка выдаётся автоматически по вебхуку; потерянные вебхуки каждые 5 минут добивает фоновый реконсилятор (как это работает).
Замороженный снапшот
Цена и состав тарифа замораживаются в момент выставления счёта. Даже если владелец поменяет каталог между счётом и оплатой — юзер получит ровно то, что заказывал, по той цене.
Умная корзина
Если на балансе не хватило, бот не бросает юзера: покупка откладывается в корзину, юзеру предлагается пополнить баланс — и сразу после зачисления (Stars или любой шлюз) отложенная покупка завершается сама, с уведомлением и ссылкой подключения.
| Ключ | Дефолт | Что делает |
|---|---|---|
AUTO_PURCHASE_AFTER_TOPUP | вкл | Автопокупка после пополнения; выкл — просто алерт «Недостаточно средств» |
CART_TTL_SECONDS | 86400 | Сколько отложенная покупка ждёт пополнения |
MIN_DEPOSIT_AMOUNT | 5000 коп | Минимальное пополнение; пресеты пополнения — 100/250/500/1000 ₽ |
Триал
Кнопка пробного периода появляется в меню только пока триал доступен юзеру — одна попытка на аккаунт, повторное нажатие защищено на уровне БД. Перед выдачей срабатывает гейт канала со скоупом trial. Все лимиты — из настроек:
| Ключ | Дефолт | Что делает |
|---|---|---|
TRIAL_ENABLED | вкл | Пробный период вообще |
TRIAL_DURATION_DAYS | 3 | Длительность |
TRIAL_TRAFFIC_GB | 10 | Трафик (0 — безлимит) |
TRIAL_DEVICE_LIMIT | 1 | Устройств на триале |
TRIAL_PRICE | 0 | Платный триал: цена в копейках, списывается с баланса (0 — бесплатно) |
TRIAL_CARRYOVER_DAYS | вкл | Неиспользованные дни триала добавляются к первой платной подписке |
Каждая выдача триала пишет строку конверсии trial→paid — воронка считается автоматически.
Докупка трафика
К активной подписке с лимитом трафика можно докупить гигабайты пакетами — те же пакеты, что в конструкторе (настраиваются в кабинете). Гигабайты добавляются к лимиту сразу после оплаты, срок подписки не меняется. Персональные скидки юзера применяются и здесь — цена в кнопке равна списанию. На безлимитной подписке докупка недоступна. Оплата — теми же способами: баланс, Stars, онлайн-шлюз.
