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

Реферальные кредиты - это не деньги и не кэшбэк. Это внутренние баллы, которые уменьшают счет за подписку или покупки внутри сервиса. Их нельзя вывести на карту и «обналичить». Пользователь получает понятную выгоду, а продукт избегает спорных ситуаций с выплатами, налогами и чарджбэками.
Когда программа изначально построена вокруг кредитов (а не денег), правила проще: кредиты работают только внутри вашего биллинга и только по вашим условиям. Например, в TakProsto это может быть скидка на тариф Pro или Business в виде кредита, который автоматически учитывается при оплате.
Люди почти всегда задают одни и те же вопросы. Лучше закрыть их заранее прямо в интерфейсе: когда начислят кредиты (после регистрации или после первой оплаты), сколько начислят (фиксированно или процентом), как их потратить (автоматически при следующем списании или вручную), есть ли срок действия и применимы ли они ко всем тарифам.
Без четких правил реферальная программа быстро превращается в источник потерь и конфликтов. Самые частые риски предсказуемые: саморефералы (пригласил сам себя), мультиаккаунты (пачка новых аккаунтов ради бонусов) и возвраты (друг оплатил, бонус выдали, потом деньги вернули). Поэтому формулу «пригласил друга, получил кредиты» стоит всегда дополнять вторым предложением: «когда именно, при каких условиях и что будет, если платеж отменят».
Чтобы система реферальных кредитов не превратилась в набор «исключений по договоренности», договоритесь о словаре заранее. Тогда аналитика, поддержка и разработка будут одинаково понимать, что именно произошло и что должно начислиться.
Кредит - внутренняя единица (не деньги). Если вам нужен «курс к рублю», фиксируйте его как отдельное правило (например, 1 кредит = 1 рубль скидки) и не смешивайте с платежной логикой. Обязательно задайте срок жизни кредита и причину его появления.
Баланс кредитов удобно понимать как состояния: доступно (можно тратить), зарезервировано (обещано к списанию в ближайшем счете), списано (применено), сгорело (истек срок или отменено правило).
Подписка и платеж - разные вещи. Подписка живет периодами (текущий период, продление, отмена), а платежи отражают счета, оплаты и возвраты. Для TakProsto это важно, чтобы кредиты применялись предсказуемо при продлении и не ломались при возврате.
Состояния реферала обычно идут цепочкой: клик по приглашению -> регистрация -> активация -> возможная отмена (например, возврат или отмена подписки). Эти статусы лучше задавать явно, а не выводить «на глаз» из разрозненных логов.
Реферальный код или ссылка должны появляться там, где пользователь уже понимает пользу. Обычно это профиль или биллинг: «Пригласи друга - получи кредиты». В TakProsto это логично показывать рядом с тарифами, чтобы человек видел, что кредиты уменьшают стоимость подписки, а не превращаются в «кэшбэк».
Чтобы учет был надежным, достаточно фиксировать несколько базовых событий и хранить минимум контекста. Хорошее правило: записывайте только то, что влияет на начисление.
Чаще всего хватает такого набора:
Валидное приглашение проще всего определять так: один новый аккаунт привязывается только к одному пригласившему и только один раз. Привязку лучше «замораживать» после первой оплаты или после истечения короткого окна (например, 7 дней после регистрации), чтобы не было бесконечных переигрываний.
Если человек сначала пришел без ссылки, а потом вводит код, задайте жесткое правило: код можно ввести один раз и только до первой оплаты. Это снимает большую часть споров.
Какие данные не собирать: не тяните «все подряд». Обычно не нужны точная геолокация, списки установленных приложений, содержимое переписок, постоянные отпечатки устройства. Для базовой защиты достаточно технических меток уровня: время, источник (ссылка или ручной ввод), идентификаторы пригласившего и приглашенного и простой признак совпадения устройства/браузера без избыточной слежки.
Атрибуция отвечает на вопрос: кто именно пригласил пользователя, и как зафиксировать это так, чтобы потом не было споров. В системе реферальных кредитов лучше выбрать одно понятное правило и строго ему следовать.
Самый частый вариант - атрибуция по ссылке. Когда человек переходит по реферальной ссылке, вы сохраняете referrer_id в cookie или local storage и ставите срок жизни (например, 7-30 дней). Если за это время пользователь зарегистрировался, привязку можно закрепить в базе.
Второй вариант - атрибуция по коду. Код вводят в интерфейсе (при регистрации или в профиле), но только до первого платежа или до первого начисления. Код проверяется на существование, активность владельца и ограничения (например, нельзя вводить после привязки к другому приглашению).
Чтобы не спорить с пользователями и поддержкой, задайте приоритеты заранее:
Хороший аудит строится на прозрачной причине привязки. Храните источник (link или code), время первого касания, время регистрации, время фиксации привязки и идентификатор события (например, signup_event_id). Тогда в поддержке TakProsto можно быстро ответить: кто кому засчитан и почему, без ручных догадок.
Начисление работает лучше всего, когда у него мало правил, но они железные. Заранее решите, за какое действие вы даете кредиты и когда именно они становятся доступными.
Обычно достаточно 1-2 событий, которые сложно подделать и легко проверить. Самая понятная связка: небольшой бонус за регистрацию и основной бонус за первую оплату. Иногда добавляют бонус за удержание (например, 14-30 дней на платном плане), чтобы поощрять «качественные» приглашения.
Для TakProsto это можно привязать к первому переходу на Pro или Business.
Практичный вариант - сначала помечать кредиты как «в ожидании», а переводить в «доступные» только после окна возврата или короткой антифрод-проверки. Это особенно важно для начислений за оплату и удержание.
Если был возврат, отмена подписки в первый период, спор по платежу или чарджбэк, начисление нужно отменять. Если кредиты уже потрачены, фиксируйте «минусовую» корректировку (баланс может уйти в отрицательное значение) или блокируйте дальнейшее списание, пока долг не закрыт.
Лимиты нужны не для наказания, а чтобы один человек не «выжег» бюджет за сутки и чтобы абуз не выглядел как нормальный рост. Держите правила короткими: лимит начислений в день и в месяц на одного пригласившего, лимит на одного приглашенного (сколько раз он может приносить бонусы) и лимит на связку «пригласивший - приглашенный» (только один раз).
Добавьте срок жизни кредитов (например, 90 или 180 дней) и простые уведомления за 7 дней до сгорания. Тогда кредиты воспринимаются как полезный бонус, а не как «пропало без предупреждения».
Антифрод в рефералке нужен не ради наказаний, а чтобы честным пользователям было выгодно участвовать. Сквозное правило простое: нельзя пригласить самого себя. Это проверяется по совпадениям, которые вы и так знаете: аккаунт, email, телефон (если есть), а также явные связки вроде «один и тот же пользователь уже был рефералом ранее».
Дальше важен баланс. Часть кейсов можно блокировать автоматически, а часть отправлять на ручную проверку, чтобы не задевать родственников или коллег в одном офисе.
Сигналы абуза лучше оценивать по комбинации, а не по одному признаку: одно и то же платежное средство у пригласившего и приглашенного, повторяющееся устройство или одинаковая среда входа, подозрительные всплески регистраций по IP, одинаковые поведенческие шаблоны и серия «пригласил -> сразу оплатил минимально -> отменил».
Автоматика должна быть мягкой. Например, в TakProsto можно не блокировать пользователя целиком, а заморозить начисление кредитов до подтверждения оплаты и прохождения периода возврата. Еще вариант - снизить лимит начислений на подозрительной связке или запросить подтверждение (например, верификацию телефона) только перед выдачей бонуса.
Чтобы разбирать спорные случаи и нормально объяснять решение, продумайте логи. Полезно хранить: кто кого пригласил и по какому коду, какие правила сработали и какое решение принято (выдать, задержать, отклонить), технические признаки в безопасном виде (хеши, маски, без лишних персональных данных), историю оплат и отмен, а также текст причины для пользователя простыми словами (без «IP-скоринга»).
Так вы снизите абуз, но не превратите рефералку в минное поле.
Чтобы реферальные кредиты не превращались в спор с поддержкой, заранее решите: они уменьшают уже выставленный счет или только будущие списания. Для подписок проще и честнее правило «только к будущим списаниям»: человек видит, что следующий платеж будет меньше, и не ждет пересчета задним числом.
Дальше нужен один понятный порядок списания. В большинстве случаев лучше так: сначала кредиты, потом карта или счет. Тогда легко объяснить, почему человек заплатил меньше.
Зафиксируйте базовые правила и держите их одинаковыми во всех тарифах:
Пример: у пользователя в TakProsto 30000 коп. кредитов, платеж 49900 коп. Списываем 30000, с карты 19900.
При апгрейде или даунгрейде не пытайтесь «пересчитывать кредиты отдельно». Проще так: сначала считаете итоговую сумму корректировки (доплата или минус к следующему платежу), и уже к этой сумме применяете кредиты.
Возвраты: если вы отменяете подписку и делаете рефанд за неиспользованный период, кредиты восстанавливайте только в той части, которая реально была списана на этот платеж. Не восстанавливайте кредиты за прошлые периоды и не возвращайте их при чарджбеках до выяснения. Это делает систему предсказуемой и устойчивой к спорным кейсам.
Если вы строите систему реферальных кредитов, не храните кредиты как одно число в профиле. Иначе вы быстро потеряете причину, почему баланс стал таким, и не сможете безопасно отменять начисления или разбирать спорные случаи.
Правильная основа - два слоя: текущий баланс и журнал операций (ledger). Баланс нужен для быстрого ответа в интерфейсе, а ledger - как единственный источник правды: каждая выдача, сгорание и списание записаны отдельной строкой.
Чтобы не начислить дважды, делайте операции идемпотентными. У каждой операции должен быть ключ уникальности, например event_id или комбинация user_id + referral_id + trigger. Если событие пришло повторно, вы не создаете новую запись, а возвращаете уже существующую.
Полезно ввести статусы операций. На практике часто хватает четырех: создано (ожидает условий), подтверждено (влияет на баланс), отменено (условия не выполнились или был возврат), сгорело (истек срок). Статус позволяет аккуратно учитывать ситуацию, когда реферал сначала оплатил, а потом сделал возврат.
Перед списанием для подписки проверяйте два условия: хватает ли подтвержденного баланса и не истек ли срок у кредитов, которые вы собираетесь потратить. Если срок важен, списывайте по принципу «сначала сгорающие раньше».
Админ-инструменты лучше закладывать сразу. Ручная корректировка должна быть отдельной операцией в ledger и всегда требовать комментарий. Это дисциплинирует и помогает разбирать инциденты без догадок.
Начните с правил на бумаге и только потом переходите к коду. Если пропустить этот шаг, система реферальных кредитов быстро превратится в набор исключений, которые никто не может объяснить ни пользователю, ни поддержке.
Рабочая последовательность обычно такая:
Зафиксируйте триггер начисления. Самый понятный вариант - «приглашенный оплатил первую подписку». Так вы не платите за пустые регистрации.
Опишите атрибуцию и лимиты. Решите, сколько дней действует приглашение, что делать при смене устройства, и сколько кредитов можно получить за месяц. Сразу запишите спорные случаи: несколько реферальных ссылок, один email на разные аккаунты, отмена оплаты.
Спроектируйте учет как ledger, а не как «поле balance». Каждое начисление и списание - отдельная операция с суммой, валютой (кредиты), причиной, ссылкой на событие (оплата или возврат), статусом (pending, confirmed, canceled). Добавьте аудит: кто и почему сделал ручную корректировку.
Включите антифрод без перегибов. Минимум: запрет самореферала, детект явных дублей (email, телефон, платежный метод), ограничение по устройству. Часто помогает задержка начисления: например, кредиты становятся доступными через 7-14 дней, чтобы пережить возвраты.
Сделайте понятный интерфейс. Нужны баланс, история операций и короткие тексты правил: когда начислят, где можно потратить, что будет при возврате. В TakProsto это удобно привязать к оплате тарифов (free, pro, business, enterprise).
После этого прогоните тесты и попробуйте «сломать» систему заранее. Проверьте минимум: оплата прошла, потом возврат; повторная оплата в том же периоде; два приглашения на одного человека; списание кредитов больше стоимости счета; сбой, когда операция начисления записалась, а уведомление не ушло.
Главное правило: все начисления и списания должны быть объяснимы по журналу операций даже спустя полгода.
Реферальная механика чаще ломается не из-за кода, а из-за неясных правил. Пользователь ожидает простую логику: пригласил, получил кредиты, оплатил подписку. Если правила размыты, поддержка тонет в спорах, а злоупотребления быстро съедают бюджет.
Частая ловушка - награждать за сам факт регистрации без фильтров и задержек. В итоге появляются «фермы» аккаунтов, а настоящие приглашения теряются в шуме. Надежнее привязывать награду к понятному действию: первой оплате или прохождению периода без возврата.
Вторая боль - хранить только текущий баланс. Когда пользователь пишет «у меня пропали кредиты», без истории операций вы не сможете объяснить, что именно произошло. Нужна выписка: начисление, причина, срок действия, списание, отмена.
Третья проблема - игнорировать возвраты и отмены. Если реферал оплатил, кредиты начислили, а потом он сделал возврат, эти кредиты должны быть отозваны или хотя бы не подтверждены. Иначе появляется дыра в выручке, особенно на годовых планах.
Отдельная зона конфликтов - атрибуция. Если у вас есть промокоды, партнеры, акции и рефералы, заранее задайте приоритеты (например, «промокод важнее реферала» или наоборот) и покажите их пользователю простыми словами.
Подрывает доверие и непредсказуемое списание: сегодня кредиты применились, завтра нет. В TakProsto это особенно заметно на подписках: человек должен понимать, сколько спишется с карты и сколько закроют кредиты еще до нажатия «Оплатить».
Быстрый тест: сможете ли вы за 30 секунд объяснить, почему у пользователя 300 кредитов и куда делись еще 200? Если нет, программа уже трещит.
Перед публичным запуском проверьте не «красоту лендинга», а то, как программа ведет себя в спорных ситуациях. Хорошая система реферальных кредитов выигрывает предсказуемыми правилами.
Начните с атрибуции: один приглашенный пользователь должен быть привязан к одному пригласившему. Если вы разрешаете переопределение (например, по обращению в поддержку), оно должно быть редким, ручным и с понятной причиной. Иначе начнутся конфликты и абуз.
Минимальный контрольный список для тестовых аккаунтов:
Отдельно проверьте поддержку. Дайте оператору один кейс и попросите за 2 минуты объяснить решение: почему засчитали (или нет), когда начислили, сколько списали, что будет при возврате. Если это невозможно без разработчика, правила нужно упрощать.
Практический пример для TakProsto: пользователь оплатил Pro, пригласивший получил кредиты, а через неделю оплата вернулась. Нормальная система либо «замораживает» начисление до конца окна возврата, либо делает обратную операцию в истории и не ломает расчет следующего платежа.
Иван пользуется TakProsto и отправляет Анне реферальную ссылку. Анна регистрируется и на следующий день оформляет подписку Pro. Чтобы снизить абуз и возвраты, кредиты не падают мгновенно: они получают статус «ожидает» и подтверждаются, например, через 7 дней после успешной оплаты.
Дальше возможны три исхода.
Если Анна не отменяет подписку в период ожидания, Иван видит «начислено» и сумму кредитов. Анна может получать бонусы по правилам программы, но это отдельная логика.
Анна оформляет подписку и сразу отменяет (или оплата откатывается). Тогда запись меняется на «отклонено». Кредиты Ивану не начисляются, либо начисленные ранее автоматически сторнируются (если вы все же начисляете сразу).
Хорошо работает короткое пояснение: «Отменено из-за возврата платежа. Кредиты не начисляются».
Иван пытается создать второй аккаунт и оформить подписку сам через свой реферальный код. Здесь срабатывают понятные сигналы без паранойи: совпадение устройства и браузера, одинаковая платежная карта, один и тот же номер телефона, частые регистрации с одной сети. Такой кейс переводится в «на проверке», а после подтверждения - в «отклонено».
Чтобы уменьшить вопросы в поддержку, показывайте статусы и причины простыми словами:
Соберите 10-20 свежих обращений в поддержку, где пользователи спорят про скидки, промокоды, «меня не засчитали» или «это не мой аккаунт». По этим кейсам допишите правила так, чтобы любой спор решался по данным и одному абзацу в регламенте, а не «как договоримся».
Пилот лучше запускать с лимитами: по времени (например, 2-4 недели), по аудитории (часть новых регистраций), по сумме кредитов. На пилоте вы проверяете не щедрость, а предсказуемость: как часто возникают споры, где появляются обходы и хватает ли данных, чтобы принять решение.
Что измерять с первого дня:
Параллельно подготовьте понятные правила для пользователей и короткие подсказки в интерфейсе. Людям важны три вещи: когда начислят, за что могут отказать и как кредиты применяются к подписке (например, «сначала кредиты, потом карта»).
Дальше автоматизируйте отчеты: начислено, списано, отклонено, причина, кто принял решение (авто или вручную). Это снижает нагрузку на поддержку и помогает быстро править правила.
Если вы собираете продукт на TakProsto (takprosto.ai), удобно сразу зафиксировать правила в planning mode и быстро собрать базовые экраны без ручной рутины: баланс кредитов, историю операций, статусы рефералов и простую админку для разборов. Такой подход дает короткий цикл: правило -> пилот -> метрика -> правка.
Это внутренние баллы, которые уменьшают сумму к оплате внутри сервиса (например, за подписку). Их нельзя вывести на карту или обменять на деньги — они работают только в вашем биллинге и по вашим правилам.
Самый понятный вариант — начислять основной бонус после первой оплаты приглашенного (или после удержания 7–30 дней). Так вы не платите за пустые регистрации и снижаете риск абуза.
Практика: сначала статус «ожидает», затем «доступно» после окна возврата или короткой проверки (например, 7–14 дней). Это защищает от ситуации «оплатил → бонус выдали → сделал возврат».
Задайте одно правило и держите его везде одинаковым:
Если платеж отменен или сделан возврат, начисление за этого реферала нужно отменить.
Если кредиты уже успели потратить, делайте минусовую корректировку (баланс может стать отрицательным) или временно блокируйте дальнейшее списание, пока «долг» не закрыт.
Четкий минимум:
Обычно удобное правило такое:
Срок нужен, чтобы бонус не превращался в вечный «склад скидок».
Типичный вариант — 90–180 дней. Важно заранее сказать пользователю:
Минимум защиты без лишней «слежки»:
Если хранить только одно число «баланс», вы не сможете объяснить, почему он изменился.
Надежная схема: