Типичный кешбэк, как правило, приходит в конце расчётного периода. Иногда увидеть вознаграждение можно через несколько недель. Но если сам платёж проходит быстро, почему бы не сделать таким же быстрым и вознаграждение?

На связи Константин Гузаров, эксперт направления в команде платформы лояльности Мир Plat.Form, технологической команды Национальной системы платёжных карт (НСПК), и сегодня я расскажу, как мы запускали моментальный кешбэк за покупки по Системе быстрых платежей (СБП) и что пришлось изменить в платформе, чтобы вознаграждение приходило практически одновременно с платежом. 

Сейчас кешбэк за покупку по СБП начисляется мгновенно по заведённым акциям. Для пользователя это выглядит просто: оплатил покупку — получил кешбэк. Но между этими двумя событиями происходит цепочка операций: процессинговый центр лояльности (ПЦЛ) получает информацию о транзакции, проверяет условия акции, учитывает историю покупок клиента, определяет размер вознаграждения и инициирует процесс выплаты. 

Процент за лояльность

Для бизнеса кешбэк — это один из маркетинговых инструментов. С помощью акции можно, например, стимулировать покупку определённого товара, увеличить частоту визитов или предложить клиенту попробовать новый способ оплаты. Но чем интереснее механика акции, тем меньше она похожа на простую формулу «вернуть 5% от покупки».

Например:

  • 7% начисляются на каждую третью покупку;

  • 100 рублей возвращаются за каждые 5000 рублей, потраченные в торговой сети за месяц;

  • для одного клиента действует ограничение по максимальной сумме вознаграждения.

Для человека это несколько условий в описании акции. Для информационной системы — состояние, которое нужно отслеживать после каждой транзакции. Допустим, клиент участвует в акции «кешбэк за каждую вторую покупку». Он совершил десять покупок, а затем вернул третью. После возврата нельзя просто вычесть одну покупку из общего количества. Нужно заново определить, какие операции теперь считаются второй, четвёртой, шестой и так далее и какие кешбэки должны были быть начислены.

Таких пограничных случаев у программ лояльности может быть множество. Поэтому кешбэк — это не только процент от суммы покупки, но и набор правил, которые нужно корректно применять к последовательности транзакций. Базовые отличия кешбэков при оплате картой и по СБП мы разбирали в материале «Кешбэк 2.0». 

Здесь сосредоточимся на другом вопросе: как построить высоконагруженную систему, которая будет выполнять эти правила со скоростью СБП.

Как Система быстрых платежей поменяла правила игры

У карточных платежей есть особенность, важная для расчёта кешбэка: между авторизацией и окончательным расчётом проходит клиринговый процесс — ранее в блоге мы уже рассказывали, какое у него значение и чем отличаются платежи по картам «Мир» от платежей по СБП.

Поэтому карточный кешбэк начисляется с задержкой. Во многих программах пользователь получает его раз в месяц, за этот период могут произойти возвраты, но банк учтёт их в расчётном периоде.

У СБП другая модель. Платежи по Системе быстрых платежей окончательны в момент проведения операции, поэтому системе не нужно ждать клиринга, чтобы начать расчёт вознаграждения. Да, по СБП тоже могут быть возвраты, но ПЦЛ СБП может в моменте обрабатывать и такие ситуации. О механике перерасчёта кешбэка после возврата мы ещё поговорим, а пока рассмотрим общую идею.

В СБП для большинства категорий торгово‑сервисных предприятий (ТСП) комиссия за приём платежа составляет не более 0,7%, для социально значимых — 0,4%, для ЖКУ — 0,2%. Поэтому для ТСП использование СБП может быть выгоднее, чем приём карточных платежей. И часть этой экономии на эквайринге ТСП может направить на финансирование своей программы лояльности, а за счёт отсутствия клиринга кешбэк будет почти мгновенным. 

Кешбэк без долгого ожидания

Почему вообще важно начислять вознаграждение моментально, если пользователи привыкли к ежемесячному кешбэку? 

Когда вознаграждение приходит через несколько недель, связь между покупкой и кешбэком размывается. Клиент может не помнить, за что именно ему начислили деньги, в каком магазине, за какую акцию и какие условия он успел выполнить. А если механика акции сложная, ещё нужно понять, почему за одну покупку магазин вернул кешбэк, а за другую — нет. И часть акций для пользователя выглядит как случайное совпадение с нужными параметрами. 

Когда связь «купил — получил» сразу закрепляется выплатой, то и понимание, за какую именно акцию начислено вознаграждение, выше. Поэтому при проектировании системы начисления кешбэка для СБП мы исходили из той же идеи, что и сама Система быстрых платежей: если операция может пройти быстро, нет смысла искусственно добавлять ожидание.

К этой мысли пришли не только мы.

Часть банков сейчас стала отправлять сумму кешбэка в уведомлении на списание денег, чтобы пользователь сразу видел, какую сумму ему начислили за покупку, которую он совершил буквально минуту назад.

Где живёт кешбэк: от «Привет, Мир!» до «Привет!»

Платформа лояльности НСПК, которая сейчас обрабатывает эти операции, изначально создавалась для ПС «Мир». Начиналось всё с программы лояльности «Привет, Мир!». Торгово‑сервисное предприятие настраивало акцию, платформа получала информацию об операциях и рассчитывала вознаграждение.

Со временем активно стала развиваться Система быстрых платежей. Особенно её C2B‑сегмент. Отсюда возник естественный запрос от бизнеса по развитию инструментов лояльности и для СБП.

Летом 2023 года мы собрали MVP кешбэка для СБП. Первая версия была пакетной. Операции собирались по ночам, затем обрабатывались, а выплаты отправлялись реестром через банк раз в день. Раз в день — уже существенно лучше, чем раз в месяц, для MVP этого было достаточно.

Первый кешбэк за покупку по СБП был начислен 4 июля 2023 года в 18:34, десять рублей. Причём сами деньги тоже были отправлены клиенту через СБП — скриншот этого исторического момента есть в статье про кешбэк в нашем блоге. Дальше систему постепенно перестраивали. 

Весной 2024 года сайт переехал с privetmir.ru на vamprivet.ru — остался просто «Привет!», потому что задачи платформы стали шире. Платформа лояльности стала поддерживать не только акции ПС «Мир», но и Системы быстрых платежей. На схеме ниже показан общий контур платформы.

Как устроена платформа лояльности НСПК
Как устроена платформа лояльности НСПК

Сегодня «Привет!» — платформа, на которой торгово‑сервисные предприятия могут запускать акции собственных программ лояльности. Сейчас на vamprivet.ru для СБП и карт платёжной системы «Мир» заведено более 500 акций. 

Как устроен процессинговый центр лояльности СБП

Для формирования положительного пользовательского опыта в диалоге с бизнесом (и учитывая опыт, полученный на MVP), мы пришли к мысли, что кешбэк должен приходить, пока клиент ещё держит смартфон в руках после покупки. 

Общее время транзакции: от получения информации о транзакции до формирования и отправки поручения на выплату кешбэка в СБП должно укладываться в 1 минуту. 

При этом основная масса операций проходит значительно быстрее. По результатам нагрузочного тестирования 98% транзакций — обычных покупок — система успевает обработать менее чем за две секунды. Оставшиеся 2% — в основном возвраты — идут по более сложному сценарию и тоже укладываются в установленные лимиты. 

Такое разделение связано с самой природой этих операций. Когда клиент совершает обычную покупку, для расчёта достаточно текущей транзакции и уже накопленного состояния по акции. Это «горячий путь». А вот возврат может изменить то, что система уже посчитала раньше. Тогда приходится смотреть историю операций клиента и пересчитывать результат. Это «холодный путь», и он заметно тяжелее. 

Но прежде чем разбираться с этими двумя сценариями, посмотрим, какие задачи вообще решает платформа.

Остальные требования выглядели так:

  • Поддерживать полную и частичную отмену операций. 

  • Выдерживать 1200 транзакций в секунду в пике, а в прогнозах — больше 4000.

  • Хранить оперативные данные год. Это требование закона. 

  • Плюс отчёты и интеграции, которых у платёжной инфраструктуры всегда много.

Что такое 1200 транзакций в секунду? Небольшой магазин пробивает столько чеков за день. Здесь они прилетают каждую секунду, и по каждому надо успеть решить, должен ли быть начислен кешбэк. Нам нужно было разделить сам процесс так, чтобы тяжёлые операции, связанные с отчётностью или личным кабинетом, не мешали расчёту кешбэка. Именно поэтому за основу взяли процессинговый центр лояльности от карт, немного доработали и разделили на два контура.

Онлайн, офлайн и Kafka

Для начала — что вообще видит участник программы. 

Клиент регистрируется на сайте платформы лояльности НСПК vamprivet.ru или в приложении «Привет!» по номеру мобильного телефона, с которого он будет оплачивать покупки через СБП, или же пользователь может быть добавлен в программу лояльности со стороны банка. 

После покупки клиент может проверить начисления в личном кабинете сайта или приложении. 

Отображение начисления кешбэка в приложении «Привет!»
Отображение начисления кешбэка в приложении «Привет!»

Для торгово‑сервисного предприятия сценарий тоже относительно простой: достаточно иметь эквайринговый договор с банком, подключиться к программе лояльности НСПК и настроить механику акции. В ней можно учитывать, например, дату и время покупки, конкретный магазин или сеть, порядковый номер и сумму транзакции, общую сумму покупок в рамках акции, количество и сумму уже выплаченных кешбэков.

Теперь посмотрим, что происходит после того, как клиент нажал кнопку оплаты.

Все компоненты процессингового центра лояльности разделены на онлайн‑ и офлайн‑части. Расчёту кешбэка не нужны ни личный кабинет, ни отчёт для банка, ни регистрация нового клиента. Если они будут конкурировать за те же ресурсы, любая тяжёлая операция может повлиять на время начисления. 

Онлайн‑контур с помощью трёх компонентов отвечает за то, чтобы провести транзакцию по самому короткому пути: 

  1. Подготовка — получает сообщение о транзакции из СБП и проверяет её на возможность начисления кешбэка.

  2. Расчёт — рассчитывает кешбэк с учётом условий акций и данных о предыдущих операциях клиента.

  3. Отправка — отправляет в СБП поручение на выплату кешбэка.

Этот контур асинхронный и нереляционный, и только к нему относятся требования по скорости. В онлайн‑части используется Cassandra.

Офлайн‑контур — синхронный и реляционный, на PostgreSQL. Он занимается операциями, которым не нужно укладываться в полминуты:

  1. API — отвечает за регистрацию клиентов и настройку акций.

  2. Остальная лояльность (бэкенд) — обеспечивает работу личных кабинетов.

  3. Отчёты — формирует отчёты для банков и ТСП.

  4. Транспорт событий — передаёт данные из онлайн‑контура в офлайн.

Ничего из этого не должно задерживать расчёт. Поэтому оно живёт в другом физическом и логическом контуре. Между этими частями — шина данных на Kafka. По ней вверх едут транзакции и кешбэк, вниз — новые клиенты и новые акции из PostgreSQL. 

Схематическое устройство ПЦЛ СБП
Схематическое устройство ПЦЛ СБП

Как проходит одна транзакция

Условно путь выглядит так:

  1. Получаем сообщение из СБП. Компонент подготовки проверяет формат, тип операции и необходимые атрибуты. Здесь же по номеру телефона определяется клиент платформы и отсекаются дубликаты. После этого сообщение отправляется в Kafka.

  2. Считаем кешбэк. Компонент расчёта забирает сообщение из Kafka и проверяет его по активным акциям. Если клиент подходит под условия, система рассчитывает вознаграждение и публикует событие о начислении обратно в Kafka.

  3. Отправляем кешбэк и сохраняем результат. Одно событие дальше читают два компонента. Первый занимается многошаговым обменом с СБП и отправляет поручение на выплату. Второй сохраняет данные в PostgreSQL — они понадобятся для отчётов и личного кабинета.

Получается, что расчёт не зависит от того, что в этот момент происходит в интерфейсе или отчётности. Ключом сообщения в Kafka выбран идентификатор клиента. Тут всё сложилось исторически, ибо все события логичным образом собирались вокруг этого идентификатора.

Почему именно Kafka? Из‑за pull‑модели: обработчик сам забирает сообщения с той скоростью, с которой способен их обработать. Если транзакций вдруг стало в два раза больше, они не начинают одновременно бить в базу и ломать обработчик. Часть остаётся в очереди и ждёт своей обработки. Это означает, что при пике мы можем получить задержку, но не должны потерять данные. 

Ещё один плюс — устойчивость к падению отдельных компонентов. Если обработчик временно недоступен, сообщения остаются в Kafka. После восстановления он продолжает работу с накопившейся очереди. Все сообщения дойдут до обработчика. 

Не пересчитывать посчитанное

Вернёмся к механикам акций и их подводным камням. Простое промо вроде «3% от чека» считается по каждой транзакции. Такая схема понятна и проста. При этом может выставляться лимит кешбэка по акции.

Но продавцы любят механики похитрее. 7% на каждую третью покупку. 100 рублей за каждые 5000, потраченные в сети за месяц. Лимит выплат на одного клиента. Для такого нужно помнить историю.

А поднимать всю историю покупок по каждому пользователю после каждого нового платежа, укладываясь в считанные секунды, — это максимально плохая идея. Выход есть: не считать снова то, что уже посчитано. Для каждой пары «клиент — акция» платформа держит агрегат. 

Агрегат — это набор счётчиков, в которых накапливаются результаты транзакций пользователя в рамках акции, а именно: сколько транзакций клиент сделал по акции, на какую сумму и сколько кешбэка уже получил. К этим трём числам сводится состояние любой механики, которую можно завести в нашем конструкторе. Обратное тоже верно: механику, которая в три числа не помещается, завести нельзя. Агрегат связан с конкретным пользователем и конкретной акцией. 

Простая механика: фиксированный процент от суммы чека 
Простая механика: фиксированный процент от суммы чека 

Пример. Акция: 10 рублей за каждую покупку больше 100 рублей, лимит по акции — 15 рублей. Первая покупка на 56 рублей: агрегат «1, 56, 0», выплаты нет. Вторая на 120: агрегат «2, 176, 10», выплата 10 рублей. Третья на 99: «3, 275, 10», выплаты нет.

Четвёртая на 200 проходит по условиям, положено ещё 10. Но выплачено уже 10, а лимит 15. Выплата 5 рублей, агрегат «4, 475, 15», акция для этого клиента исчерпана.

Без агрегата на четвёртом шаге пришлось бы поднимать историю выплат. 

Сложная механика: N рублей за каждую третью покупку
Сложная механика: N рублей за каждую третью покупку

Хранится всё это в Cassandra. Из базы намеренно убрали всю семантику: ключ раздела — клиент, ключ группировки — тип записи и время, дальше JSON. На каждого клиента как будто своя папка в картотеке, и всё нужное для расчёта лежит в ней по порядку. Ни соединений таблиц, ни агрегирующих запросов.

Под такой профиль Cassandra и создана. Из специального — только TTL (Time to Live): один год у нас и срок давности возврата, и глубина хранения, так что записи старше года удаляются автоматически.

Когда всё же нужно пересчитать

По статистике у нас ~98% транзакций — покупки, ~2% — возвраты. Система заточена и оптимизирована именно под первое, но второе тоже приходится учитывать. 

Возврат меняет предыдущий расчёт. Клиент купил семь раз по акции «за каждую третью покупку» и получил кешбэк за третью и шестую. Потом вернул третью. Теперь четвёртая покупка стала третьей, а седьмая — шестой. Два старых кешбэка оказались невалидны, два новых валидны, но уже за другие покупки с другой суммой. 

Возврат для сложной механики
Возврат для сложной механики

Агрегат тут не помощник. Он знает итог, но не знает, из чего итог сложился.

Для возвратов есть отдельный, «холодный» путь. Платформа поднимает все транзакции клиента по акции за год, вычёркивает отменённую (полностью или частично) и заново, по порядку, пересчитывает все кешбэки и агрегаты. Потом берет список кешбэков, которые клиенту уже выплатили, и сравнивает с новым. Лишнее списывает, недостающее доначисляет.

Процесс обработки возвратов
Процесс обработки возвратов

Зачем такая дотошность? Потому что после отмены клиент может получить и меньше, и больше, чем без неё. Недодать своё нельзя, отдать лишнее — тоже. Плюс это защита от простого трюка: купить три раза, забрать кешбэк за третью и вернуть всё. 

Вместо заключения

Быстрый кешбэк — это не просто приятный бонус, а рабочий инструмент для повышения лояльности. Когда вознаграждение приходит практически в момент покупки, клиент сразу видит связь между оплатой и выгодой: понятно, где он совершил покупку и за какую акцию получил деньги. Такая связь запоминается лучше, чем строчка в выписке в конце месяца.

При этом запустить акцию может любое торгово‑сервисное предприятие, а не только крупные сети с собственными программами лояльности. Достаточно иметь эквайринговый договор с банком, присоединиться к программе лояльности НСПК и настроить механику на платформе «Привет!». Всё остальное, от расчёта до выплаты, берёт на себя наша инфраструктура.

Надеемся, что наш опыт и инструменты помогут бизнесу выстраивать отношения с покупателями и сделают СБП ещё более привлекательным способом оплаты — и для магазинов, и для их клиентов.

Типичный кешбэк, как правило, приходит в конце расчётного периода. Иногда увидеть вознаграждение можно через несколько недель. Но если сам платёж проходит быстро, почему бы не сделать таким же быстрым и вознаграждение?

На связи Константин Гузаров, эксперт направления в команде платформы лояльности Мир Plat.Form, технологической команды Национальной системы платёжных карт (НСПК), и сегодня я расскажу, как мы запускали моментальный кешбэк за покупки по Системе быстрых платежей (СБП) и что пришлось изменить в платформе, чтобы вознаграждение приходило практически одновременно с платежом. 

Сейчас кешбэк за покупку по СБП начисляется мгновенно по заведённым акциям. Для пользователя это выглядит просто: оплатил покупку — получил кешбэк. Но между этими двумя событиями происходит цепочка операций: процессинговый центр лояльности (ПЦЛ) получает информацию о транзакции, проверяет условия акции, учитывает историю покупок клиента, определяет размер вознаграждения и инициирует процесс выплаты. 

Процент за лояльность

Для бизнеса кешбэк — это один из маркетинговых инструментов. С помощью акции можно, например, стимулировать покупку определённого товара, увеличить частоту визитов или предложить клиенту попробовать новый способ оплаты. Но чем интереснее механика акции, тем меньше она похожа на простую формулу «вернуть 5% от покупки».

Например:

  • 7% начисляются на каждую третью покупку;

  • 100 рублей возвращаются за каждые 5000 рублей, потраченные в торговой сети за месяц;

  • для одного клиента действует ограничение по максимальной сумме вознаграждения.

Для человека это несколько условий в описании акции. Для информационной системы — состояние, которое нужно отслеживать после каждой транзакции. Допустим, клиент участвует в акции «кешбэк за каждую вторую покупку». Он совершил десять покупок, а затем вернул третью. После возврата нельзя просто вычесть одну покупку из общего количества. Нужно заново определить, какие операции теперь считаются второй, четвёртой, шестой и так далее и какие кешбэки должны были быть начислены.

Таких пограничных случаев у программ лояльности может быть множество. Поэтому кешбэк — это не только процент от суммы покупки, но и набор правил, которые нужно корректно применять к последовательности транзакций. Базовые отличия кешбэков при оплате картой и по СБП мы разбирали в материале «Кешбэк 2.0». 

Здесь сосредоточимся на другом вопросе: как построить высоконагруженную систему, которая будет выполнять эти правила со скоростью СБП.

Как Система быстрых платежей поменяла правила игры

У карточных платежей есть особенность, важная для расчёта кешбэка: между авторизацией и окончательным расчётом проходит клиринговый процесс — ранее в блоге мы уже рассказывали, какое у него значение и чем отличаются платежи по картам «Мир» от платежей по СБП.

Поэтому карточный кешбэк начисляется с задержкой. Во многих программах пользователь получает его раз в месяц, за этот период могут произойти возвраты, но банк учтёт их в расчётном периоде.

У СБП другая модель. Платежи по Системе быстрых платежей окончательны в момент проведения операции, поэтому системе не нужно ждать клиринга, чтобы начать расчёт вознаграждения. Да, по СБП тоже могут быть возвраты, но ПЦЛ СБП может в моменте обрабатывать и такие ситуации. О механике перерасчёта кешбэка после возврата мы ещё поговорим, а пока рассмотрим общую идею.

В СБП для большинства категорий торгово‑сервисных предприятий (ТСП) комиссия за приём платежа составляет не более 0,7%, для социально значимых — 0,4%, для ЖКУ — 0,2%. Поэтому для ТСП использование СБП может быть выгоднее, чем приём карточных платежей. И часть этой экономии на эквайринге ТСП может направить на финансирование своей программы лояльности, а за счёт отсутствия клиринга кешбэк будет почти мгновенным. 

Кешбэк без долгого ожидания

Почему вообще важно начислять вознаграждение моментально, если пользователи привыкли к ежемесячному кешбэку? 

Когда вознаграждение приходит через несколько недель, связь между покупкой и кешбэком размывается. Клиент может не помнить, за что именно ему начислили деньги, в каком магазине, за какую акцию и какие условия он успел выполнить. А если механика акции сложная, ещё нужно понять, почему за одну покупку магазин вернул кешбэк, а за другую — нет. И часть акций для пользователя выглядит как случайное совпадение с нужными параметрами. 

Когда связь «купил — получил» сразу закрепляется выплатой, то и понимание, за какую именно акцию начислено вознаграждение, выше. Поэтому при проектировании системы начисления кешбэка для СБП мы исходили из той же идеи, что и сама Система быстрых платежей: если операция может пройти быстро, нет смысла искусственно добавлять ожидание.

К этой мысли пришли не только мы.

Часть банков сейчас стала отправлять сумму кешбэка в уведомлении на списание денег, чтобы пользователь сразу видел, какую сумму ему начислили за покупку, которую он совершил буквально минуту назад.

Где живёт кешбэк: от «Привет, Мир!» до «Привет!»

Платформа лояльности НСПК, которая сейчас обрабатывает эти операции, изначально создавалась для ПС «Мир». Начиналось всё с программы лояльности «Привет, Мир!». Торгово‑сервисное предприятие настраивало акцию, платформа получала информацию об операциях и рассчитывала вознаграждение.

Со временем активно стала развиваться Система быстрых платежей. Особенно её C2B‑сегмент. Отсюда возник естественный запрос от бизнеса по развитию инструментов лояльности и для СБП.

Летом 2023 года мы собрали MVP кешбэка для СБП. Первая версия была пакетной. Операции собирались по ночам, затем обрабатывались, а выплаты отправлялись реестром через банк раз в день. Раз в день — уже существенно лучше, чем раз в месяц, для MVP этого было достаточно.

Первый кешбэк за покупку по СБП был начислен 4 июля 2023 года в 18:34, десять рублей. Причём сами деньги тоже были отправлены клиенту через СБП — скриншот этого исторического момента есть в статье про кешбэк в нашем блоге. Дальше систему постепенно перестраивали. 

Весной 2024 года сайт переехал с privetmir.ru на vamprivet.ru — остался просто «Привет!», потому что задачи платформы стали шире. Платформа лояльности стала поддерживать не только акции ПС «Мир», но и Системы быстрых платежей. На схеме ниже показан общий контур платформы.

Как устроена платформа лояльности НСПК
Как устроена платформа лояльности НСПК

Сегодня «Привет!» — платформа, на которой торгово‑сервисные предприятия могут запускать акции собственных программ лояльности. Сейчас на vamprivet.ru для СБП и карт платёжной системы «Мир» заведено более 500 акций. 

Как устроен процессинговый центр лояльности СБП

Для формирования положительного пользовательского опыта в диалоге с бизнесом (и учитывая опыт, полученный на MVP), мы пришли к мысли, что кешбэк должен приходить, пока клиент ещё держит смартфон в руках после покупки. 

Общее время транзакции: от получения информации о транзакции до формирования и отправки поручения на выплату кешбэка в СБП должно укладываться в 1 минуту. 

При этом основная масса операций проходит значительно быстрее. По результатам нагрузочного тестирования 98% транзакций — обычных покупок — система успевает обработать менее чем за две секунды. Оставшиеся 2% — в основном возвраты — идут по более сложному сценарию и тоже укладываются в установленные лимиты. 

Такое разделение связано с самой природой этих операций. Когда клиент совершает обычную покупку, для расчёта достаточно текущей транзакции и уже накопленного состояния по акции. Это «горячий путь». А вот возврат может изменить то, что система уже посчитала раньше. Тогда приходится смотреть историю операций клиента и пересчитывать результат. Это «холодный путь», и он заметно тяжелее. 

Но прежде чем разбираться с этими двумя сценариями, посмотрим, какие задачи вообще решает платформа.

Остальные требования выглядели так:

  • Поддерживать полную и частичную отмену операций. 

  • Выдерживать 1200 транзакций в секунду в пике, а в прогнозах — больше 4000.

  • Хранить оперативные данные год. Это требование закона. 

  • Плюс отчёты и интеграции, которых у платёжной инфраструктуры всегда много.

Что такое 1200 транзакций в секунду? Небольшой магазин пробивает столько чеков за день. Здесь они прилетают каждую секунду, и по каждому надо успеть решить, должен ли быть начислен кешбэк. Нам нужно было разделить сам процесс так, чтобы тяжёлые операции, связанные с отчётностью или личным кабинетом, не мешали расчёту кешбэка. Именно поэтому за основу взяли процессинговый центр лояльности от карт, немного доработали и разделили на два контура.

Онлайн, офлайн и Kafka

Для начала — что вообще видит участник программы. 

Клиент регистрируется на сайте платформы лояльности НСПК vamprivet.ru или в приложении «Привет!» по номеру мобильного телефона, с которого он будет оплачивать покупки через СБП, или же пользователь может быть добавлен в программу лояльности со стороны банка. 

После покупки клиент может проверить начисления в личном кабинете сайта или приложении. 

Отображение начисления кешбэка в приложении «Привет!»
Отображение начисления кешбэка в приложении «Привет!»

Для торгово‑сервисного предприятия сценарий тоже относительно простой: достаточно иметь эквайринговый договор с банком, подключиться к программе лояльности НСПК и настроить механику акции. В ней можно учитывать, например, дату и время покупки, конкретный магазин или сеть, порядковый номер и сумму транзакции, общую сумму покупок в рамках акции, количество и сумму уже выплаченных кешбэков.

Теперь посмотрим, что происходит после того, как клиент нажал кнопку оплаты.

Все компоненты процессингового центра лояльности разделены на онлайн‑ и офлайн‑части. Расчёту кешбэка не нужны ни личный кабинет, ни отчёт для банка, ни регистрация нового клиента. Если они будут конкурировать за те же ресурсы, любая тяжёлая операция может повлиять на время начисления. 

Онлайн‑контур с помощью трёх компонентов отвечает за то, чтобы провести транзакцию по самому короткому пути: 

  1. Подготовка — получает сообщение о транзакции из СБП и проверяет её на возможность начисления кешбэка.

  2. Расчёт — рассчитывает кешбэк с учётом условий акций и данных о предыдущих операциях клиента.

  3. Отправка — отправляет в СБП поручение на выплату кешбэка.

Этот контур асинхронный и нереляционный, и только к нему относятся требования по скорости. В онлайн‑части используется Cassandra.

Офлайн‑контур — синхронный и реляционный, на PostgreSQL. Он занимается операциями, которым не нужно укладываться в полминуты:

  1. API — отвечает за регистрацию клиентов и настройку акций.

  2. Остальная лояльность (бэкенд) — обеспечивает работу личных кабинетов.

  3. Отчёты — формирует отчёты для банков и ТСП.

  4. Транспорт событий — передаёт данные из онлайн‑контура в офлайн.

Ничего из этого не должно задерживать расчёт. Поэтому оно живёт в другом физическом и логическом контуре. Между этими частями — шина данных на Kafka. По ней вверх едут транзакции и кешбэк, вниз — новые клиенты и новые акции из PostgreSQL. 

Схематическое устройство ПЦЛ СБП
Схематическое устройство ПЦЛ СБП

Как проходит одна транзакция

Условно путь выглядит так:

  1. Получаем сообщение из СБП. Компонент подготовки проверяет формат, тип операции и необходимые атрибуты. Здесь же по номеру телефона определяется клиент платформы и отсекаются дубликаты. После этого сообщение отправляется в Kafka.

  2. Считаем кешбэк. Компонент расчёта забирает сообщение из Kafka и проверяет его по активным акциям. Если клиент подходит под условия, система рассчитывает вознаграждение и публикует событие о начислении обратно в Kafka.

  3. Отправляем кешбэк и сохраняем результат. Одно событие дальше читают два компонента. Первый занимается многошаговым обменом с СБП и отправляет поручение на выплату. Второй сохраняет данные в PostgreSQL — они понадобятся для отчётов и личного кабинета.

Получается, что расчёт не зависит от того, что в этот момент происходит в интерфейсе или отчётности. Ключом сообщения в Kafka выбран идентификатор клиента. Тут всё сложилось исторически, ибо все события логичным образом собирались вокруг этого идентификатора.

Почему именно Kafka? Из‑за pull‑модели: обработчик сам забирает сообщения с той скоростью, с которой способен их обработать. Если транзакций вдруг стало в два раза больше, они не начинают одновременно бить в базу и ломать обработчик. Часть остаётся в очереди и ждёт своей обработки. Это означает, что при пике мы можем получить задержку, но не должны потерять данные. 

Ещё один плюс — устойчивость к падению отдельных компонентов. Если обработчик временно недоступен, сообщения остаются в Kafka. После восстановления он продолжает работу с накопившейся очереди. Все сообщения дойдут до обработчика. 

Не пересчитывать посчитанное

Вернёмся к механикам акций и их подводным камням. Простое промо вроде «3% от чека» считается по каждой транзакции. Такая схема понятна и проста. При этом может выставляться лимит кешбэка по акции.

Но продавцы любят механики похитрее. 7% на каждую третью покупку. 100 рублей за каждые 5000, потраченные в сети за месяц. Лимит выплат на одного клиента. Для такого нужно помнить историю.

А поднимать всю историю покупок по каждому пользователю после каждого нового платежа, укладываясь в считанные секунды, — это максимально плохая идея. Выход есть: не считать снова то, что уже посчитано. Для каждой пары «клиент — акция» платформа держит агрегат. 

Агрегат — это набор счётчиков, в которых накапливаются результаты транзакций пользователя в рамках акции, а именно: сколько транзакций клиент сделал по акции, на какую сумму и сколько кешбэка уже получил. К этим трём числам сводится состояние любой механики, которую можно завести в нашем конструкторе. Обратное тоже верно: механику, которая в три числа не помещается, завести нельзя. Агрегат связан с конкретным пользователем и конкретной акцией. 

Простая механика: фиксированный процент от суммы чека 
Простая механика: фиксированный процент от суммы чека 

Пример. Акция: 10 рублей за каждую покупку больше 100 рублей, лимит по акции — 15 рублей. Первая покупка на 56 рублей: агрегат «1, 56, 0», выплаты нет. Вторая на 120: агрегат «2, 176, 10», выплата 10 рублей. Третья на 99: «3, 275, 10», выплаты нет.

Четвёртая на 200 проходит по условиям, положено ещё 10. Но выплачено уже 10, а лимит 15. Выплата 5 рублей, агрегат «4, 475, 15», акция для этого клиента исчерпана.

Без агрегата на четвёртом шаге пришлось бы поднимать историю выплат. 

Сложная механика: N рублей за каждую третью покупку
Сложная механика: N рублей за каждую третью покупку

Хранится всё это в Cassandra. Из базы намеренно убрали всю семантику: ключ раздела — клиент, ключ группировки — тип записи и время, дальше JSON. На каждого клиента как будто своя папка в картотеке, и всё нужное для расчёта лежит в ней по порядку. Ни соединений таблиц, ни агрегирующих запросов.

Под такой профиль Cassandra и создана. Из специального — только TTL (Time to Live): один год у нас и срок давности возврата, и глубина хранения, так что записи старше года удаляются автоматически.

Когда всё же нужно пересчитать

По статистике у нас ~98% транзакций — покупки, ~2% — возвраты. Система заточена и оптимизирована именно под первое, но второе тоже приходится учитывать. 

Возврат меняет предыдущий расчёт. Клиент купил семь раз по акции «за каждую третью покупку» и получил кешбэк за третью и шестую. Потом вернул третью. Теперь четвёртая покупка стала третьей, а седьмая — шестой. Два старых кешбэка оказались невалидны, два новых валидны, но уже за другие покупки с другой суммой. 

Возврат для сложной механики
Возврат для сложной механики

Агрегат тут не помощник. Он знает итог, но не знает, из чего итог сложился.

Для возвратов есть отдельный, «холодный» путь. Платформа поднимает все транзакции клиента по акции за год, вычёркивает отменённую (полностью или частично) и заново, по порядку, пересчитывает все кешбэки и агрегаты. Потом берет список кешбэков, которые клиенту уже выплатили, и сравнивает с новым. Лишнее списывает, недостающее доначисляет.

Процесс обработки возвратов
Процесс обработки возвратов

Зачем такая дотошность? Потому что после отмены клиент может получить и меньше, и больше, чем без неё. Недодать своё нельзя, отдать лишнее — тоже. Плюс это защита от простого трюка: купить три раза, забрать кешбэк за третью и вернуть всё. 

Вместо заключения

Быстрый кешбэк — это не просто приятный бонус, а рабочий инструмент для повышения лояльности. Когда вознаграждение приходит практически в момент покупки, клиент сразу видит связь между оплатой и выгодой: понятно, где он совершил покупку и за какую акцию получил деньги. Такая связь запоминается лучше, чем строчка в выписке в конце месяца.

При этом запустить акцию может любое торгово‑сервисное предприятие, а не только крупные сети с собственными программами лояльности. Достаточно иметь эквайринговый договор с банком, присоединиться к программе лояльности НСПК и настроить механику на платформе «Привет!». Всё остальное, от расчёта до выплаты, берёт на себя наша инфраструктура.

Надеемся, что наш опыт и инструменты помогут бизнесу выстраивать отношения с покупателями и сделают СБП ещё более привлекательным способом оплаты — и для магазинов, и для их клиентов.

Комментарии (1)


  1. inkelyad
    30.09.2026 15:54

    И все это, в конечном итоге, сводится к тому, что в сумма в кошельке уменьшится не на ту сумму, что формально ценой считается. Тут бы (в очередной раз бурчу) вообще перестать делать вид, что цена одинаковая, но ладно.
    Но, отсюда вопрос - почему кэшбек нельзя посчитать до совершения транзакции - у вас же, вроде как, все равно шаг ее подготовки есть, в отличии от карточной транзакции. Потом показать(или нет) получившийся результат покупателю, прицепить результат к запросу на платеж и сделать сразу две операции туда-обратно, уже больше ничего не считая?