Партнёрская программа: как получать % за приведённых
Что это. Приводите пользователей в qvib.pro по своей реферальной ссылке — за каждый их ОПЛАЧЕННЫЙ заказ вам начисляется процент. Это affiliate-модель (кэш за продажу), а не give-get купоны.
Зачем так. Движки — недёшевы и покупаются разово, поэтому процент с продажи — понятный и честный стимул для тех, кто рекомендует продукт (агентства, авторы, комьюнити-лиды).
Как это работает по шагам (в коде).
- Вступление:
POST /api/partner/enrollсоздаётpartner_accountsс уникальным реферальным кодом (алфавит без 0/O/1/I/l, чтобы не путать). Идемпотентно — повторный вызов вернёт тот же аккаунт. - Ссылка:
GET /api/partner/r/<код>(публичный) регистрирует клик, кладёт cookiees_refна 30 дней и делает 302 на корень. Неизвестный код молча игнорируется. - Атрибуция по ПЕРВОМУ касанию: при регистрации
bindReferralпишетpartner_referrals(user_id)cON CONFLICT (user_id) DO NOTHING— побеждает ПЕРВЫЙ партнёр, поздний код не перепишет привязку. Есть guard от самореферала (партнёр не может привести сам себя). - Фиксация на заказе: при создании заказа
ref_partner_idпроставляется из привязки — атрибуция «замораживается» в момент покупки. - Начисление: когда заказ становится
paid,accrueForOrderначисляет комиссию ОДНИМ SQL-стейтментом:INSERT ... ON CONFLICT (order_id) DO NOTHING+ черезFROM insбампитtotal_earnedтолько для реально вставленной строки. Повтор webhook'а = no-op: двойного начисления не будет по построению.
Сколько платят и когда
- Ставка: по умолчанию 25%. Кап по тиру движка: Simple ≤25%, Standard ≤30%, Pro ≤40% (
rate = min(ставка партнёра, кап тира)). Настраивается в админ-настройкеaffiliate. - Резерв 15% — страховка под возвраты.
- Холд: для карточных платежей 45 дней (
hold_until), затемreleaseHeldCommissionsпереводит комиссию изpendingвavailableи кредитует баланс (под блокировкой аккаунта, чтобы не было гонки). - Возврат/chargeback:
clawbackоткатывает комиссию по её стадии жизненного цикла (pending / available / locked / paid); если деньги уже были в выплате — баланс может уйти в минус ПО ДИЗАЙНУ и помечается флагом: долг реальный и должен быть виден, а не спрятан.
Worked-пример: продажа Pro-движка за ₽3900
Вход: партнёр с кодом K7MNPQ2A кинул ссылку /api/partner/r/K7MNPQ2A; человек перешёл, через неделю зарегистрировался, ещё через день купил Pro-движок за ₽3900 (390000 копеек). Ставка партнёра 40%, кап тира Pro = 40%.
Что делает движок:
- Клик записан, cookie
es_ref=K7MNPQ2Aживёт 30 дней. - При регистрации
bindReferralпривязал user к партнёру (первое касание). - Заказ создан с
ref_partner_id= этот партнёр. - Webhook
paid→accrueForOrder:rate = min(0.40, 0.40) = 0.40;commission = round(390000 * 0.40) = 156000копеек. - Комиссия создана в
pendingсhold_until = сейчас + 45 дней;total_earnedбампнут на 156000.
Результат: в кабинете партнёра (GET /api/partner/me) видно клики/регистрации/продажи, баланс, резерв, историю комиссий и выплат. Через 45 дней 1560 ₽ переедут в available.
Честно про выплаты (важное ограничение)
Выплата — РУЧНАЯ. Партнёр запрашивает вывод (POST /api/partner/payout), система создаёт pending-payout, резервирует деньги из баланса и блокирует нужные комиссии (старые первыми). Дальше АДМИН проводит транзакцию вручную и записывает transaction_id. Автовыплат нет: ЮKassa Выплаты — отдельный пред-фондируемый контракт, который пока не подключён. Плюс жёсткое условие: для вывода у партнёра ОБЯЗАН быть указан ИНН (самозанятый/ИП) — иначе 403 INN_REQUIRED.