Как интегрировать Digital Fraud Protection в Android-приложение

По этой инструкции вы подключите DFP к своему Android-приложению: встроите Servicepipe Mobile SDK, получите результат проверки клиентского окружения и настроите его расшифровку и обработку на своём бэкенде.

Как работает интеграция

  1. Вы встраиваете Servicepipe Mobile SDK в приложение.

  2. Приложение вызывает SDK, когда пользователь пытается совершить действие, для которого нужна проверка окружения: например, вход в аккаунт, регистрация или подтверждение операции.

  3. SDK собирает локальные признаки Android-устройства и отправляет их на серверы DFP.

  4. DFP формирует результат проверки окружения и передаёт его SDK в зашифрованном виде.

  5. Приложение передаёт этот результат на ваш бэкенд.

  6. Ваш бэкенд расшифровывает результат и применяет настроенную вами бизнес-логику: например, разрешает или запрещает действие.

Требования

Android 7.0+ (min API 24)

Интеграция

1. Выберите, по какому домену приложение будет обращаться к API DFP

SDK будет отправлять собранные признаки Android-устройства в API DFP. SDK может обращаться к API через:

  • Стандартный адрес https://fp.servicepipe.tech/fp/. Работает по умолчанию, ничего настраивать не нужно.

  • Ваш поддомен. В этом случае мы выделим для вас IP, а вам нужно настроить A-запись своего поддомена на этот IP.

Если хотите использовать свой поддомен, сообщите нам. Если нет, ничего делать не нужно, просто переходите к шагу 2.

Ниже в примерах используется стандартный адрес API — https://fp.servicepipe.tech/fp/.

2. Получите токен и секретный ключ

Мы передадим вам два значения:

  • CUSTOMER-TOKEN — токен для вызова API DFP из SDK;

  • SECRET-KEY — секретный ключ (передаём в формате Hex), которым ваш бэкенд будет расшифровывать payload.

SECRET-KEY храните только на бэкенде. Не добавляйте его в код приложения и не передавайте на устройство пользователя.

3. Добавьте библиотеку в проект

Скопируйте AAR-файл SDK в каталог libs вашего Android-модуля. Затем добавьте библиотеку в зависимости приложения:

dependencies {
    implementation files("libs/servicepipe-core-1.2.0-release.aar")
}

4. Инициализируйте SDK в Application

В классе Application инициализируйте SDK. Передайте адрес API DFP и CUSTOMER-TOKEN, который получили на шаге 2.

import android.app.Application
import ru.servicepipe.core.FingerprintConfiguration
import ru.servicepipe.core.SPService

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        SPService.init(
            this,
            FingerprintConfiguration(
                "https://fp.servicepipe.tech/fp/",
                "<CUSTOMER-TOKEN>"
            )
        )
    }
}

Если используете свой поддомен, укажите его вместо стандартного адреса API:

FingerprintConfiguration(
    "https://fp-check.example.com/fp/",
    "<CUSTOMER-TOKEN>"
)

Если вызвать API SDK до инициализации, будет выброшено исключение IllegalStateException.

5. Добавьте вызовы getFingerprint() для защищаемых действий

Добавьте вызов getFingerprint() ко всем действиям, перед выполнением которых нужно проверить окружение с помощью DFP: например, входу в аккаунт, регистрации или подтверждению операции.

Метод getFingerprint():

  • собирает локальные признаки Android-устройства;

  • отправляет их в DFP для проверки;

  • получает зашифрованный результат DFP и передаёт его приложению.

getFingerprint() может использовать опции customData и customID. Добавьте их к нужным вызовам метода, если хотите в рамках вызова передать дополнительный контекст проверки:

  • customData — произвольная строка с вашими данными. DFP вернёт её в неизменном виде внутри payload как поле custom_data. Строка не участвует в создании отпечатка, она только помогает вашему бэкенду связать результат DFP с конкретным действием. Логику обработки вы настраиваете сами. Рекомендуем передавать в customData JSON с типом события и, если нужно, ID операции или формы.

    Не передавайте в customData пароли, платёжные данные, токены авторизации и другие секреты. Длина строки customData не должна превышать 4096 символов.

  • customID — стабильный идентификатор пользователя, аккаунта или другого объекта в вашей системе. Он позволяет связать этот объект с его user_id ещё на стороне Servicepipe.

    customID можно использовать только после согласования с нашими инженерами. Логика его обработки и влияние на результат DFP настраиваются на стороне Servicepipe индивидуально для каждого клиента. Длина значения customID не должна превышать 128 символов.

Если не используете customData или customID, вызовите getFingerprint() без опций:

import ru.servicepipe.core.SP
import ru.servicepipe.core.SPService
import ru.servicepipe.core.fingerprint.FingerprintResult

SPService.getSPInstance().getFingerprint(
    object : SP.FingerprintListener {
        override fun onSuccess(fingerprint: FingerprintResult) {
            // Передайте fingerprint на свой бэкенд.
        }

        override fun onError(errorMessage: String) {
            // Обработайте ошибку получения результата DFP.
        }
    }
)

Если используете customData или customID, перед вызовом getFingerprint() создайте FingerprintOptions и укажите в нём customData, customID или оба параметра. Затем передайте этот объект первым аргументом метода:

import ru.servicepipe.core.SP
import ru.servicepipe.core.SPService
import ru.servicepipe.core.fingerprint.FingerprintOptions
import ru.servicepipe.core.fingerprint.FingerprintResult

val options = FingerprintOptions()
    .withCustomData("""{"event":"login_attempt","form_id":"main_login"}""")
    .withCustomId("account_12345")

SPService.getSPInstance().getFingerprint(
    options,
    object : SP.FingerprintListener {
        override fun onSuccess(fingerprint: FingerprintResult) {
            // Передайте fingerprint на свой бэкенд.
        }

        override fun onError(errorMessage: String) {
            // Обработайте ошибку получения результата DFP.
        }
    }
)

После вызова getFingerprint() SDK соберёт локальные признаки Android-устройства, отправит их в DFP и получит зашифрованный результат проверки. Затем SDK передаст этот результат приложению: вызовет onSuccess у переданного FingerprintListener и передаст в него объект FingerprintResult. Если выполнить проверку или получить результат не удалось, SDK вызовет onError.

В onSuccess SDK передаёт объект FingerprintResult. Он содержит зашифрованный payload и служебные поля для его расшифровки и диагностики:

  • cipher_type — алгоритм шифрования;

  • iv — вектор инициализации;

  • payload — зашифрованный результат DFP;

  • tag — тег аутентичности;

  • request_id — идентификатор запроса для обращения в техническую поддержку;

  • success — признак успешного выполнения проверки.

Метод fingerprint.toString() возвращает эти данные в виде JSON. Его можно передать на ваш бэкенд.

6. Отправьте ответ DFP на бэкенд

Передайте результат из onSuccess на свой бэкенд. Именно там должна происходить расшифровка payload, проверка результата и принятие решения.

Если получили результат с success: false, сохраните request_id и передайте его в нашу техническую поддержку.

7. Расшифруйте payload на бэкенде

Для расшифровки:

  1. Декодируйте SECRET-KEY из Hex в бинарные данные.

  2. Декодируйте iv, payload и tag из Base64 в бинарные данные.

  3. Расшифруйте payload с помощью AES-256-GCM, используя SECRET-KEY, iv и tag.

  4. Интерпретируйте результат расшифровки как JSON.

Пример расшифровки на Node.js:

import * as crypto from "crypto";

const secretKey = Buffer.from("<SECRET-KEY>", "hex");
const iv = Buffer.from(input.iv, "base64");
const payload = Buffer.from(input.payload, "base64");
const tag = Buffer.from(input.tag, "base64");

const decipher = crypto.createDecipheriv(
  "aes-256-gcm",
  secretKey,
  iv
);

decipher.setAuthTag(tag);

const decrypted = Buffer.concat([
  decipher.update(payload),
  decipher.final()
]);

const result = JSON.parse(decrypted.toString("utf8"));

Пример расшифрованного payload:

{
  "details": {
    "bot_hosting": false,
    "bot_score": 0.1,
    "hosting": false,
    "isp_active_subnet": true,
    "os": "android",
    "vpn": false,
    "new_user": false,
    "confidence_score": 1
  },
  "user_id": "3849965ed6d75d7dc67568d620950bbb",
  "timestamp": 1777404974833,
  "version": 2,
  "custom_data": "{\"event\":\"login_attempt\",\"form_id\":\"main_login\"}"
}

О каждом поле подробнее читайте в статье Что значат поля из ответа DFP.

8. Проверьте свежесть результата

Ваш бэкенд должен сравнить значение поля timestamp с текущим временем UTC.

Не принимайте ответы старше нескольких секунд — это защитит ваш ресурс от replay-атак, то есть атак, в которых злоумышленник пытается выдать старый результат DFP за новый.

Если timestamp свежий, всё в порядке, можно продолжать обработку.

9. Обработайте данные в рамках своей бизнес-логики

Используйте значения полей user_id, bot_score, vpn, hosting, bot_hosting, isp_active_subnet, os, new_user, confidence_score и custom_data в правилах своего сервиса, чтобы решать ваши бизнес-задачи: например, проверять попытки входа в аккаунт.

Пример логики, которую можно настроить для обнаружения подозрительных попыток входа:

  1. Получите user_id из расшифрованного payload.

  2. Проверьте, связан ли этот user_id с аккаунтом пользователя в вашей базе.

  3. Если связь уже есть и bot_score низкий, обработайте вход по обычному сценарию.

  4. Если user_id новый и при этом bot_score средний или высокий, запросите дополнительное подтверждение.

  5. Сохраните user_id, результат дополнительной проверки и связь с аккаунтом, чтобы учитывать эти данные при следующих попытках входа.

Мы подготовили готовые инструкции, как использовать DFP для конкретных бизнес-задач:

10. Проверьте интеграцию

После настройки проверьте интеграцию в приложении:

  1. Запустите приложение с подключённым SDK.

  2. Выполните действие, для которого вы настроили проверку: например, войдите в аккаунт, отправьте форму или подтвердите операцию.

  3. Убедитесь, что SDK получил результат DFP, а приложение отправило его на бэкенд.

  4. Проверьте, что бэкенд расшифровал payload, проверил timestamp, обработал поля из ответа DFP и применил ваши правила.