---
title: "SubscriptionConductor"
description: "Мульти-провайдерная система членских подписок — Stripe, WayForPay, RING-кредиты, ончейн-токен, NFT-гейт и PayPal. Один реестр, конфигурируемые шлюзы, cron-пайплайны и админ-панель."
locale: "ru"
---
# SubscriptionConductor

> **Info**
> Фильтруйте эту страницу как **Founder** / **Developer** в боковой панели. Основатели узнают *что* стоит каждый провайдер и как настроить комиссии; разработчики — архитектуру, контракты модулей провайдеров и детали cron-пайплайнов.

SubscriptionConductor (v1, Фаза S4) — мульти-провайдерная система биллинга членских подписок Ring Platform. Один SSOT-реестр (`subscription_ledger`) отслеживает все состояния подписчиков независимо от способа оплаты. Шесть модулей провайдеров реализуют общий контракт `SubscriptionProviderModule`, а пять cron-пайплайнов поддерживают подписки актуальными.

Реализация: `lib/payments/subscription/`.

### For founders

## Что получают основатели от SubscriptionConductor

Ваша платформа зарабатывает регулярный доход через членские подписки — с нулевой комиссией платформы на внутренние методы (кредитный баланс, RING-токен, NFT-гейт). Выберите, какие шлюзы включить, настройте переложение комиссий и отслеживайте чистый доход в админ-панели.

### Статус функций

| Провайдер | Детали | Шлюз | Статус |
|----------|---------|---------|--------|
| WayForPay | рекуррентный биллинг через recToken | WayForPay (UAH) | ✅ Доступно |
| Кредитный баланс | автосписание с внутренних RING-кредитов | Кредитные баллы | ✅ Доступно |
| RING-токен | ончейн-платёж в Solana | RING (Токены) | ✅ Доступно |
| Stripe | Stripe Subscriptions API | Stripe (USD) | 🔮 TBD |
| NFT-гейт | 12-месячный доступ через soulbound NFT | NFT Сертификат | 🔮 TBD |
| PayPal | PayPal рекуррентный биллинг | PayPal (USD) | 🔮 TBD |

### Тарифы комиссий и чистый доход

Каждый шлюз удерживает свою комиссию. Внутренние методы (кредитный баланс, RING-токен, NFT-гейт) взимают **0%** — каждый доллар идёт вашей платформе.

| Провайдер | Комиссия % | Фиксированная комиссия | Валюта |
|----------|-------|-----------|----------|
| WayForPay | 2.5% | — | UAH |
| Stripe | 2.9% | $0.30 | USD |
| Кредитный баланс | 0% | — | USD |
| RING-токен | 0% | — | RING (Токены) |
| NFT-гейт | 0% | — | RING |
| PayPal | 2.9% | $0.30 | USD |

**Формула чистого дохода:** `net = gross - (gross × feePercent / 100) - feeFixed`. Функция `calculateNetRevenue()` в `subscription-config.ts` вычисляет это на сервере; админ-панель показывает gross, fee и net для каждой подписки.

### Конфигурация (ring-config.json)

Все настройки провайдеров хранятся в `ring-config.json` в секции `payment.gateways`:

```json
{
  "payment": {
    "cardPaymentProcessor": "wayforpay",
    "supportedMethods": ["wayforpay", "credit_balance", "ring_token"],
    "futureMethods": ["stripe", "paypal", "nft_gate"],
    "gateways": {
      "wayforpay": { "enabled": true, "feePercent": 2.5, "currency": "UAH" },
      "stripe": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "USD" },
      "credit_balance": { "enabled": true, "feePercent": 0, "currency": "USD" },
      "ring_token": { "enabled": true, "feePercent": 0, "currency": "RING", "label": "Tokens" },
      "paypal": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "USD" },
      "nft_gate": { "enabled": false, "feePercent": 0, "currency": "RING", "label": "NFT Certificate" }
    }
  }
}
```

- `cardPaymentProcessor` — карточный шлюз по умолчанию (`wayforpay` или `stripe`). Переопределение через `PAYMENT_MEMBERSHIP_PROCESSOR=stripe`.
- `supportedMethods` — провайдеры, доступные пользователям при оформлении.
- `futureMethods` — провайдеры с пометкой "Скоро" в UI.
- `gateways..feePercent` — процентная комиссия, удерживаемая перед вашим чистым доходом.

### Админ-панель

Суперадмины имеют доступ к `/admin/subscriptions`:

- **Список подписок** — фильтр по провайдеру, статусу, пользователю; каждая строка показывает gross, fee и net доход.
- **Агрегированная статистика** — `/api/admin/subscriptions/stats` возвращает `total_active`, `due_for_payment`, разбивки `by_provider` и `by_method`.
- **Отслеживание дохода** — `calculateNetRevenue()` вызывается для каждой строки, чтобы основатели видели реальный доход после комиссий шлюзов.

### For developers

## Архитектура

```
Membership upgrade / checkout
        ↓
lib/payments/subscription/subscription-conductor.ts
        ↓
Модули провайдеров: stripe | wayforpay | credit_balance | ring_token | nft_gate | paypal
        ↓
subscription_ledger (PostgreSQL — провайдер-агностический SSOT)
        ↓
Cron-пайплайны: expiry + payment + credit-balance + solana-batch + nft-gate
```

### Реестр провайдеров

Шесть модулей провайдеров реализуют контракт `SubscriptionProviderModule` (`lib/payments/subscription/subscription-types.ts`). Conductor определяет их по ID провайдера:

| ID провайдера | Модуль | Источник |
|-------------|--------|--------|
| `credit_balance` | `ringCreditSubscriptionProvider` | `providers/ring-credit-subscription.ts` |
| `ring_token` | `ringTokenSubscriptionProvider` | `providers/ring-token-subscription.ts` |
| `stripe` | `stripeSubscriptionProvider` | `providers/stripe-subscription.ts` |
| `wayforpay` | `wayforpaySubscriptionProvider` | `providers/subscription-provider-stubs.ts` |
| `nft_gate` | `nftGateSubscriptionProvider` | `providers/subscription-provider-stubs.ts` |
| `paypal` | `paypalSubscriptionProvider` | `providers/subscription-provider-stubs.ts` |

Заглушки для WayForPay, NFT Gate и PayPal являются заполнителями; Stripe, Credit Balance и RING Token имеют полные реализации.

### Схема subscription_ledger

SSOT-коллекция: `subscription_ledger`. Схема определена в `lib/payments/subscription/subscription-ledger-schema.ts` (Zod).

Ключевые поля:

| Поле | Тип | Описание |
|-------|------|-------------|
| `id` | `string` | ID строки реестра (`sub__`) |
| `user_id` | `string` | ID пользователя-владельца |
| `provider` | `enum` | `stripe`, `wayforpay`, `credit_balance`, `ring_token`, `nft_gate`, `paypal` |
| `gateway` | `string` | Человеко-читаемая метка (напр. "Stripe", "WayForPay") |
| `method` | `enum` | `card`, `credit_balance`, `crypto`, `nft` |
| `status` | `enum` | `active`, `expired`, `cancelled`, `suspended`, `grace_period` |
| `amount` | `number` | Цена подписки (в минорных единицах) |
| `currency` | `string` | Валюта биллинга |
| `gateway_fee_percent` | `number` | Процентная комиссия (напр. `2.9`) |
| `gateway_fee_fixed` | `number` | Фиксированная комиссия в минорных единицах (напр. `30` для Stripe) |
| `stripe_subscription_id` | `string?` | Stripe-ссылка (если провайдер Stripe) |
| `wayforpay_rec_token` | `string?` | Рекуррентный токен WayForPay |
| `solana_tx_signature` | `string?` | Ончейн-подпись транзакции |
| `nft_mint_address` | `string?` | Адрес минта NFT-сертификата |
| `start_time` | `number` | Начало подписки (мс эпохи) |
| `next_payment_due` | `number` | Время следующего платежа |
| `failed_attempts` | `number` | Последовательные неудачи платежа (макс 3 → авто expiring) |
| `auto_renew` | `boolean` | Флаг автопродления |
| `total_paid` | `string` | Всего оплачено за всё время |
| `payments_count` | `number` | Количество успешных платежей |

### API Conductor

`SubscriptionConductor` (`lib/payments/subscription/subscription-conductor.ts`) предоставляет:

| Операция | Сигнатура | Описание |
|-----------|-----------|-------------|
| `createSubscription` | `(input: CreateSubscriptionInput) → CreateSubscriptionResult` | Маршрутизация к модулю провайдера, вставка строки реестра |
| `cancelSubscription` | `(userId, provider, gatewayRef?) → CancelSubscriptionResult` | Отмена у провайдера + пометка строк реестра |
| `renewSubscription` | `(userId, provider, gatewayRef?) → RenewSubscriptionResult` | Продление у провайдера + обновление реестра |
| `getSubscription` | `(userId) → SubscriptionLedgerRow \| null` | Последняя активная подписка пользователя |
| `getSubscriptions` | `(filter) → SubscriptionLedgerRow[]` | Запрос по пользователю, провайдеру, статусу, методу, окну оплаты |
| `getStats` | `() → SubscriptionStats` | Агрегированные подсчёты по статусу, провайдеру, методу |
| `calculateNetRevenue` | `(row) → { gross, fee, net, currency }` | Чистый доход на строку |

### API-маршруты

| Метод | Путь | Назначение | Авторизация |
|--------|------|---------|------|
| `POST` | `/api/membership/subscription/create` | Создание подписки через conductor | Сессия |
| `GET` | `/api/membership/subscription/status` | Статус подписки + баланс | Сессия |
| `POST` | `/api/membership/subscription/cancel` | Отмена подписки | Сессия |
| `POST` | `/api/membership/payment/token` | Обработка токен-платежа | Сессия |
| `GET` | `/api/admin/subscriptions` | Список всех подписок | Суперадмин |
| `GET` | `/api/admin/subscriptions/stats` | Агрегированная статистика | Суперадмин |

### Cron-пайплайны

Пять cron-пайплайнов зарегистрированы в `lib/processes/registry.ts` в категории `membership`:

| ID пайплайна | Cron-путь | Обработчик | Расписание |
|-------------|-----------|---------|----------|
| `subscription-expiry-check` | `/api/cron/subscription-expiry` | `runSubscriptionExpiryCheck` | Ежедневно в полночь |
| `credit-balance-monthly` | `/api/cron/credit-balance-monthly` | `runCreditBalanceMonthly` | Ежечасно |
| `subscription-payment` | `/api/cron/subscription-payment` | `runSubscriptionPaymentCheck` | Ежедневно в 2:00 |
| `solana-batch-payment` | `/api/cron/solana-batch-payment` | `runSolanaBatchPayment` | Ежедневно в 3:00 |
| `nft-gate-expiry` | `/api/cron/nft-gate-expiry` | `runNftGateExpiry` | Ежедневно в 4:00 |

Пайплайны запускаются через HTTP cron-задания по `cronPath`. Обработчики импортируются из `lib/processes/subscription/`:

- `expiry-check.ts` — помечает просроченные подписки как `expired` и понижает роли пользователей
- `credit-balance-monthly.ts` — списывает ежемесячную плату с кредитного баланса
- `subscription-payment.ts` — обрабатывает рекуррентные платежи Stripe/WayForPay
- `solana-nft-stubs.ts` — пакетные переводы RING-токенов и истечение срока NFT-гейта

### Добавление нового провайдера

1. Реализуйте контракт `SubscriptionProviderModule` в `providers/-subscription.ts`
2. Зарегистрируйте в `subscription-conductor.ts` в `providerRegistry` Map
3. Добавьте конфигурацию шлюза в `ring-config.json` `payment.gateways.`
4. Добавьте в массив `SUBSCRIPTION_PROVIDERS` в `subscription-ledger-schema.ts`
5. Обновите `getMembershipPaymentOptions()` в `subscription-config.ts`
6. При необходимости добавьте обработчик cron-пайплайна в `lib/processes/subscription/`

### Переменные окружения

```bash
PAYMENT_MEMBERSHIP_PROCESSOR=wayforpay    # Переопределение карточного шлюза для членства
WAYFORPAY_MERCHANT_ACCOUNT=your_merchant
WAYFORPAY_SECRET_KEY=your_secret
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
```

## Связанное

- [PaymentConductor](/docs/features/payment-conductor.md) — оркестрация одноразовых платежей
- [WayForPay интеграция](/docs/features/wayforpay-integration.md)
- [Кошелёк и кредиты](/docs/features/wallet.md)
- [Магазин](/docs/features/store.md) — поток оформления членства
- [Админ-панель](/docs/features/admin.md)
