Покупка и установка: разовая цена → ссылка на установку
Что это. Модель монетизации простая и без подписок: один разовый платёж за один движок. Никаких кредитов, кошельков и абонплаты. Смотреть каталог, собирать/выбирать движок и листать превью — бесплатно; платите только за ДОСТАВКУ устанавливаемого пакета.
Зачем так. Конфиги — это commodity, их не стыдно показать. Ценность — в собранной дисциплине движка вайб-кодинга (команда ролей + вето-ревью + процесс + установщик); модули расширяют движок и покупаются так же — разовым платежом. Купленная версия — ваша навсегда; новая версия ядра выходит отдельным продуктом, а не «обновлением по подписке». Поэтому paywall стоит на границе доставки, а не на роутах: без оплаты вы видите redacted-превью, но не полную спеку и не пакет.
Когда что происходит (гейт в коде). Запрос полной спеки без права доступа возвращает 402 Payment required + redacted-превью (или 404, если движок не опубликован). Экспорт (POST /export, GET /export.zip) тоже требует entitlement: владелец org ИЛИ оплаченный заказ. Цена берётся из карточки листинга, иначе — из админ-настройки по тиру. Дефолтные тиры (редактируются в админке): Simple ₽900 / Standard ₽4900 / Pro ₽3900. Деньги хранятся в КОПЕЙКАХ (BIGINT) — конвертация в рубли только на границе API ЮKassa, никаких float-округлений.
Worked-пример: от кнопки «Купить» до рабочего движка
Вход: вы собрали свой движок вайб-кодинга на базе Quest и жмёте «Купить».
Что делает движок (бэкенд):
createOrderв одной транзакции: проверяет, что org покупателя владеет движком (multi-tenant guard), фиксирует приведшего партнёра (если есть), создаёт заказstatus: pending, создаёт платёж в ЮKassa (идемпотентность по id заказа, redirect-подтверждение) и записываетpayment_url.- Вы оплачиваете банковской картой на защищённой странице ЮKassa.
- ЮKassa шлёт webhook. Телу уведомления не доверяем: статус перепроверяется авторитетным запросом к API ЮKassa (fail-closed — поддельный webhook бесполезен). Обработка идемпотентна: повтор уведомления просто подтверждается без повторной обработки; флип
pending → paid— это CAS по id заказа и статусу, поэтому гонка двух webhook'ов не выпустит два токена. - При флипе в
paidчеканятся два РАЗНЫХ секрета:install_token(одноразовая установка) иwatermark_base(вотермарк на пакете). Разные байты — отзыв одного не палит другой. - Если заказ был приведён партнёром — атомарно и идемпотентно начисляется комиссия (см. статью про партнёрку).
Результат: ссылка на установку /install/<token> — посадочная страница с пакетом под ваш инструмент (Claude Code / Cursor / AGENTS.md), README, INSTALL.md и готовым промтом-установщиком.
Установка считается по местам (seat-counted лицензия)
Доставка — не «скачал раз и всё», а честная посчитанная лицензия. Токен в ссылке — это bearer, а отпечаток машины (machineFp) идентифицирует место:
POST /:token/materialize {machineFp}— РЕЗЕРВИРУЕТ место (не считается в лимит; резерв авто-освобождается через 15 минут, чтобы брошенная установка не сжигала слот) и выдаёт подписанный download-handle.GET /:token/download?h=...— стримит zip и СЧИТАЕТ доставку только ПОСЛЕ полной отправки (проверенная доставка = ENFORCED счётчик; оборванная — не считается).POST /confirm— HMAC-маячок «поставил/активировал». Он ADVISORY: подтверждает факт, но НИКОГДА не увеличивает лимит и не освобождает место.
Превышение лимита мест → 403 INSTALL_LIMIT. Страница установки всегда проверяет order.status = 'paid' — до оплаты не отдаётся ничего.
Честно про защиту и возвраты
Полный DRM невозможен: платящий читает свой plaintext-пакет. Что реально защищаем: pre-pay-внутренности (полная спека и пакет за гейтом 402), лицензию и вотермарк, и посчитанные места установки. При возврате/chargeback комиссия партнёра откатывается через clawback, а install-токен/место можно инвалидировать — страница установки, проверяя status, перестанет отдавать пакет.