> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bedolagam.ru/llms.txt
> Use this file to discover all available pages before exploring further.

# Автопокупка и корзина

> Сквозная корзина и автоматическая покупка подписки после пополнения баланса

## Обзор

Система "сквозной корзины" решает проблему: пользователь хочет купить подписку, но баланса не хватает. Вместо того чтобы заставлять пользователя начинать покупку заново после пополнения, бот сохраняет параметры покупки и может автоматически оформить подписку после зачисления средств.

## Как работает

```
1. Пользователь выбирает подписку → не хватает баланса
2. Параметры покупки сохраняются в Redis (корзина)
3. Пользователь пополняет баланс любым способом
4. После зачисления бот проверяет наличие корзины
5a. AUTO_PURCHASE=true и баланса хватает → покупка автоматически
5b. Иначе → кнопка "Вернуться к корзине"
```

## Сохранение корзины

При недостатке средств бот сообщает:

* Сколько не хватает для покупки
* Что корзина сохранена
* Предлагает кнопку **Пополнить баланс**

### Что сохраняется

Корзина хранится в Redis с ключом `user_cart:{user_id}` и содержит все параметры покупки:

| Режим корзины           | Что сохраняется                                        |
| ----------------------- | ------------------------------------------------------ |
| `extend`                | ID подписки, тариф, период, цена, скидки, серверы      |
| `tariff_purchase`       | ID тарифа, период, трафик, устройства, серверы, скидки |
| `daily_tariff_purchase` | ID тарифа, суточная цена, трафик, устройства, серверы  |
| `add_devices`           | Количество устройств, цена                             |
| `add_traffic`           | ID подписки, объем трафика, цена, скидка               |

### TTL корзины

По умолчанию корзина живет **1 час** (3600 секунд). Настраивается через `CART_TTL_SECONDS`.

После истечения TTL корзина автоматически удаляется из Redis.

## Автоматическая покупка

При `AUTO_PURCHASE_AFTER_TOPUP_ENABLED=true` покупка происходит **полностью автоматически** — без подтверждения от пользователя.

### Когда срабатывает

После **каждого успешного платежа** через любую платежную систему:

* YooKassa, CryptoBot, Telegram Stars, CloudPayments
* Freekassa, Platega, PayPalych, Heleket
* MulenPay, Tribute, WATA, Kassa AI

### Логика после пополнения

1. Проверяется `AUTO_PURCHASE_AFTER_TOPUP_ENABLED`
2. Загружается корзина из Redis
3. Проверяется защита от дублирования (не было ли покупки за последние 60 секунд)
4. Проверяется достаточность баланса
5. Выполняется покупка, баланс списывается
6. Подписка создается/продлевается, синхронизируется с RemnaWave
7. Корзина удаляется
8. Пользователю отправляется уведомление об автопокупке

### Если баланса все еще не хватает

* Автопокупка **не выполняется**
* Корзина **не удаляется** (остается до истечения TTL)
* Пользователю отправляется сообщение с кнопкой **Вернуться к корзине**

### Пересчет цены

Для тарифных корзин цена **пересчитывается** из БД в момент покупки, а не берется из сохраненных данных. Это защищает от ситуации, когда тариф подорожал между сохранением корзины и покупкой.

## Уведомления пользователю

### При сохранении корзины

```
Недостаточно средств для оформления подписки.
Не хватает: 150₽

Корзина сохранена! После пополнения баланса
подписка будет оформлена автоматически.

[Пополнить баланс] [Назад]
```

### При автоматической покупке

В зависимости от типа:

* **Продление**: "Подписка автоматически продлена на 30 дней"
* **Новый тариф**: "Подписка на 90 дней автоматически оформлена после пополнения баланса"
* **Суточный**: "Суточный тариф 'Базовый' активирован!"
* **Устройства**: "Устройства добавлены автоматически! +2 устройства"
* **Трафик**: "Трафик добавлен автоматически! +10 ГБ"

Все уведомления содержат кнопки: **Моя подписка** и **Главное меню**.

### При недостатке средств (корзина осталась)

```
[Вернуться к сохраненной корзине]
```

## Ручное управление корзиной

Пользователь может:

* **Вернуться к корзине** — кнопка в сообщении после пополнения (если автопокупка не сработала)
* **Очистить корзину** — кнопка `clear_saved_cart` удаляет корзину из Redis

## Источники корзины

Корзина сохраняется из трех интерфейсов:

| Интерфейс      | Описание                                                            |
| -------------- | ------------------------------------------------------------------- |
| Telegram бот   | Все хендлеры покупки/продления/докупки                              |
| Cabinet WebApp | API возвращает HTTP 402 с `cart_saved: true`                        |
| MiniApp        | После успешной покупки сохраняет корзину для будущего автопродления |

## Настройка

| Переменная                          | По умолчанию | Описание                              |
| ----------------------------------- | ------------ | ------------------------------------- |
| `AUTO_PURCHASE_AFTER_TOPUP_ENABLED` | `false`      | Включить автоматическую покупку       |
| `CART_TTL_SECONDS`                  | `3600`       | Время жизни корзины в Redis (секунды) |

Настройку `AUTO_PURCHASE_AFTER_TOPUP_ENABLED` можно менять **без перезапуска бота** через админ-панель (категория настроек: Payment).

<Note>
  Для работы корзины необходим Redis. Без Redis параметры покупки не сохраняются.
</Note>

## Защита от дублирования

* Перед автопокупкой проверяется, не было ли транзакции типа `SUBSCRIPTION_PAYMENT` за последние 60 секунд
* Если была — корзина очищается без покупки (предотвращает двойное списание при быстрых платежах)
