Рубріки: Back-end

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

Арсений Андреев

Привет! Меня зовут Арсений Андреев, я backend-разработчик в Solid — финтех-компании, которая помогает бизнесам принимать онлайн-платежи по всему миру. Также наша платформа обеспечивает их максимальную конверсию при минимальных рисках, используя дополнительные сервисы: антифрод, систему по предотвращению чарджбэков (принудительный возврат платежа), сервис подписок и многие другие.

Прежде чем перейти к техническим деталям, хочу объяснить, что такое антифрод и почему он необходим.

Фрод (fraud) — это мошеннические операции с данными банковской карты пользователя, в нашем случае, в интернете. Система антифрода позволяет обнаружить и предотвратить рисковые операции по картам, которые пытаются провести злоумышленники. Рост электронной коммерции сопровождается и ростом числа мошеннических операций, поэтому для компаний, которые принимают онлайн-платежи, система антифрода очень важна.

В Solid мы ежемесячно проводим миллионы транзакций, и качественная система антифрода — один из наших главных приоритетов.

Почему антифрод — неотъемлемая часть продукта

Мы занимаемся комплексной разработкой инструментов для онлайн-оплат, где один из ключевых инструментов — платежный шлюз. Он позволяет автоматизировать процесс приема платежей в интернете, а антифрод — его неотъемлемая часть.

Помимо предотвращения рисковых операций, система антифрода автоматически анализирует транзакции, минимизирует связанные с фродом расходы и помогает сохранить высокий уровень конверсии.

Риски и проблемы, которые решает антифрод

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

Основные показатели, на которые мы хотим влиять с помощью системы антифрода:

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

Итак, главная задача антифрода — минимизация рисков с сохранением высокого уровня конверсии платежей.

Требования к системам антифрода

Цель системы — выявить аномальные транзакции и принять решение о дальнейшем проведении таких платежей.

После проверки антифродом платежный шлюз должен получить четкую установку, что делать:

  • провести транзакцию;
  • отправить транзакцию на дополнительную проверку в банк-эмитент;
  • заблокировать транзакцию.

Для этого антифрод должен обладать такой информацией:

  • данными об аккаунтах антифрода;
  • историческими данными о платежах;
  • конфигурационными данными для различных проверок.

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

Система антифрода должна соответствовать многим требованиям, чтобы решать задачи риск-менеджмента.

Среди них можно выделить:

  • скорость проверки платежа — в 99% случаев она должна длиться не более 0,2 секунды;
  • возможность обработки большого потока данных;
  • динамическую настройку проверок на основе любых параметров, которые получает антифрод от платежного шлюза;
  • удобную инфраструктуру как для разработчиков, поддерживающих систему, так и для операторов, которые настраивают, проверяют систему и обучают модели.

Система антифрода критически важна. Ее остановка может привести к росту риск-показателей, например, увеличению процента чарджбэков. Как следствие, ваша компания попадет в программу мониторинга международной платежной системы. А это спровоцирует штрафы и санкции против платежного провайдера.

Скорость ответа антифрода — один из главных факторов его эффективности, поскольку проверка осуществляется в момент проведения платежа. Поэтому наш сервис написан на Go — этот язык позволяет распараллелить операции-проверки, необходимые для предоставления заключения платежному шлюзу.

Время проверки платежа. Источник: Solid

Как создать антифрод — пример Solid

Мы используем PostgreSQL в качестве базы для хранения конфигурационных данных, а Elastic — для сохранения информации о платежах.

Этапы проверки платежа. Источник: Solid

В систему антифрода входят такие этапы проверки:

  • по включающему/исключающему списку;
  • по набору динамических правил, которые настраивает оператор системы;
  • по скору, полученному от ML-системы, которая работает с моделями;
  • по скору, полученному с помощью стороннего сервиса.

Чтобы определить судьбу транзакции, платежному шлюзу необходим однозначный результат:

  • Reject — заблокировать платеж;
  • Pass — пропустить платеж;
  • Force 3D — отправить пользователя на идентификацию;
  • Review — необходима мануальная проверка оператором системы или клиентом.

Коротко рассмотрим каждый из этапов.

Проверка по включающему/исключающему списку

Это первый этап, потому что он наименее ресурсозатратный. Списки хранятся в базе данных (БД) и могут включать разные поля — например, идентификатор карты.

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

Списки хранятся в таблице с такими полями:

  • key — например, Card ID;
  • value — значение Card ID;
  • expire at — необходимость вносить значения на время, например, до перевыпуска карты.

Несложным SQL-запросом мы проверяем, есть ли совпадение по одному из параметров платежа. Важный момент — если получаем Reject, то следующие проверки уже не производятся.

Проверка по набору динамических правил

Пример динамических правил для проверки платежа:

  • использование большого количества карт с одного IP за определенный период времени;
  • использование одной карты из нескольких IP/имейлов/аккаунтов за определенный период;
  • большое количество неудачных попыток за определенный период;
  • наличие возвратного платежа или большого количества возвратов за определенный период.

Этот функционал мы реализовали с помощью агрегационных функций Elasticsearch. Все правила по аккаунту, хранящиеся в БД, собираются в один elastic-запрос — JSON-объект. В результате получаем «решение» по каждому из правил. Далее в каждом правиле проверяем значение, полученное из запроса, и формируем список решений (pass, reject и т.п.).

У оператора в арсенале есть набор доступных полей для агрегации:

  • Amount
  • Email
  • Payment IP
  • Country by Payment IP
  • Payment Status
  • Card ID
  • Card Bin
  • Card Brand
  • Card Type
  • Card Holder Name

Операторы сравнения: «in», «not in», «>», «<», «=», «>=», «<=», «!=».

Агрегационные функции:

  • Count
  • Unique Count
  • Average
  • Sum
  • Length

Таким образом, можно привести несколько примеров настроенных правил:

  1. Если страны банка, выпустившего карту, нет в списке тех, с которыми работает клиент — заблокировать.
  2. Если количество неуспешных платежей за время Y более X — заблокировать.
  3. Если сумма платежа больше, чем X, — отправить на 3D Secure верификацию.
  4. Если длина имейла более X — заблокировать.

Оператор системы может настроить любое правило.

Здесь важно выбрать оптимальный вариант хранения по индексам в elastic. Есть возможность хранить данные за короткий период (день) или за продолжительный (месяц).

Оба варианта имеют как плюсы, так и минусы. При хранении в «больших» индексах мы используем больше ресурсов при обновлении данных, что впоследствии негативно влияет на время выполнения поискового запроса. «Маленькие» индексы плохи тем, что при поиске за продолжительный период нужно тратить время на их объединение.

Наша команда выбрала оба варианта. Для выполнения правил, которые используют короткий период (3–5 дней), мы сохраняем данные по дням. Для правил за большой период (более 5 дней) сохраняем данные в одном индексе за продолжительное время. У нас большинство правил настроено на короткий период — 1–3 дня, поэтому такой подход устраивает.

В результате имеем такую ​​разбивку по индексам:

  • payment-{clientId} — данные за продолжительное время;
  • payment-{clientId}-y-m-d — данные за 3–5 дней.

Также стоит учесть, что частая реиндексация значительно влияет на время выполнения поискового запроса. Пример запроса: подсчитать среднюю сумму успешных платежей в USD за последние три часа. Подсчет происходит по нескольким параметрам, идентифицирующим пользователя, например: ID аккаунта, card_id, имейл.

{
  "aggs": {
    "avgUsdSum": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "payment_status": ":order_status"
              }
            },
            {
              "range": {
                "created_at": {
                  "gte": "now-180m",
                  "format": "yyyy-MM-dd"
                }
              }
            }
          ]
        }
      },
      "aggs": {
        "avgUsd": {
          "avg": {
            "field": "amount_usd"
          }
        }
      }
    }
  },
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              {
                "term": {
                  "email": ":customer_email"
                }
              },
              {
                "term": {
                  "card_id": ":card_id"
                }
              },
              {
                "term": {
                  "customer_account_id": ":customer_account_id"
                }
              }
            ]
          }
        }

Конфигурационные данные хранятся в базе данных. С помощью кода записи в БД, правила трансформируются в запросы (примеры такого запроса приведены выше). После получения данных в ответ на запрос, мы их парсим и сравниваем с заданными в правилах значениями.

Проверка по скору, полученному от ML-системы

В данном случае применяем реализованный аналитиками сервис, который использует модели, построенные на исторических данных клиента. Скор — это число от -100 до 100. Оператор добавляет маппинг в настройках аккаунта, например:

  • От -100 до -75 — Reject.
  • От -75 до -25 — Force 3d.
  • От -25 до 25 — Review.
  • От 25 до 100 — Pass.

В этот сервис отправляются данные, которые:

  • пришли от платежного шлюза;
  • являются результатами динамических правил;
  • являются агрегационными данными, которые аналитик может вытянуть сам с помощью elastic-запроса.

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

Проверка по скору с помощью стороннего сервиса

Интеграция со сторонним сервисом — это последний этап проверки. Сервис возвращает не только скор, но и другие параметры, которые можно использовать в конфигурации правил. У каждого сервиса есть свой флоу, но в целом они похожи. Необходимо передать определенное количество параметров, которые помогут этому сервису определить скор.

Одна из проблем реализации антифрода как отдельной системы — наполнение базы данных этой системы платежами. Для получения корректных проверок необходимо держать информацию в актуальном состоянии, в первую очередь — статус платежа.

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

В нашем антифроде обновление данных происходит сразу же после изменения статуса платежа. Таким образом, данные в системе всегда в актуальном состоянии.

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

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

Результаты

Нам удалось реализовать систему антифрода, которую можно гибко настраивать под различные типы бизнесов. Для каждого из них есть ряд уникальных параметров, например, размер среднего чека, особенности товаров и услуг. Важно учитывать специфические для бизнеса параметры, поскольку это позволяет не только держать конверсию на высоком уровне, но и предупредить финансовые потери, связанные с фродом.

Платежный шлюз здорово упрощает жизнь своим клиентам, поскольку им не надо реализовывать сложную систему, которая помимо разработки требует еще и поддержки.

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

Важно, что разработчик исключается из процессов риск-менеджмента. То есть, система предоставляет полноценный функционал по управлению, настройке и мониторингу ее работы. Это позволяет аналитикам выполнять свои повседневные задачи без помощи программистов.

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Останні статті

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

В благословенные офисные времена, когда не было большой войны и коронавируса, люди гораздо больше общались…

07.12.2023

Делать что-то впервые всегда очень трудно. Две истории о начале карьеры PM

Вот две истории из собственного опыта, с тех пор, когда только начинал делать свою карьеру…

04.12.2023

«Тыжпрограммист». Как люди не из ІТ-отрасли обесценивают профессию

«Ты же программист». За свою жизнь я много раз слышал эту фразу. От всех. Кто…

15.11.2023

Почему чат GitHub Copilot лучше для разработчиков, чем ChatGPT

Отличные новости! Если вы пропустили, GitHub Copilot — это уже не отдельный продукт, а набор…

13.11.2023

Как мы используем ИИ и Low-Code технологии для разработки IT-продукта

Несколько месяцев назад мы с командой Promodo (агентство инвестировало в продукт более $100 000) запустили…

07.11.2023

Университет или курсы. Что лучше для получения IT-образования

Пару дней назад прочитал сообщение о том, что хорошие курсы могут стать альтернативой классическому образованию.…

19.10.2023