Вердикты о честности

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

Формат возвращаемого вердикта о целостности

Полезная нагрузка представляет собой простой текст JSON и содержит сигналы целостности, а также информацию, предоставленную разработчиком.

Общая структура полезной нагрузки выглядит следующим образом:

{
  "requestDetails": { ... },
  "appIntegrity": { ... },
  "deviceIntegrity": { ... },
  "accountDetails": { ... },
  "environmentDetails": { ... }
}

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

Поле запроса данных

Поле requestDetails содержит информацию о запросе, включая предоставленную разработчиком информацию в requestHash для стандартных запросов и nonce для классических запросов.

Для стандартных запросов API:

"requestDetails": {
  // Application package name this attestation was requested for.
  // Note that this field might be spoofed in the middle of the request.
  "requestPackageName": "com.package.name",
  // Request hash provided by the developer.
  "requestHash": "aGVsbG8gd29scmQgdGhlcmU",
  // The timestamp in milliseconds when the integrity token
  // was requested.
  "timestampMillis": "1675655009345"
}

Эти значения должны совпадать со значениями исходного запроса. Поэтому проверьте часть requestDetails полезной нагрузки JSON, убедившись, что requestPackageName и requestHash соответствуют значениям, отправленным в исходном запросе, как показано в следующем фрагменте кода:

Котлин

val requestDetails = JSONObject(payload).getJSONObject("requestDetails")
val requestPackageName = requestDetails.getString("requestPackageName")
val requestHash = requestDetails.getString("requestHash")
val timestampMillis = requestDetails.getLong("timestampMillis")
val currentTimestampMillis = ...

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request
    || !requestHash.equals(expectedRequestHash)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Ява

RequestDetails requestDetails =
    decodeIntegrityTokenResponse
    .getTokenPayloadExternal()
    .getRequestDetails();
String requestPackageName = requestDetails.getRequestPackageName();
String requestHash = requestDetails.getRequestHash();
long timestampMillis = requestDetails.getTimestampMillis();
long currentTimestampMillis = ...;

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request.
    || !requestHash.equals(expectedRequestHash)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Для классических API-запросов:

"requestDetails": {
  // Application package name this attestation was requested for.
  // Note that this field might be spoofed in the middle of the
  // request.
  "requestPackageName": "com.package.name",
  // base64-encoded URL-safe no-wrap nonce provided by the developer.
  "nonce": "aGVsbG8gd29scmQgdGhlcmU",
  // The timestamp in milliseconds when the request was made
  // (computed on the server).
  "timestampMillis": "1617893780"
}

Эти значения должны совпадать со значениями исходного запроса. Поэтому проверьте часть requestDetails полезной нагрузки JSON, убедившись, что requestPackageName и nonce соответствуют значениям, отправленным в исходном запросе, как показано в следующем фрагменте кода:

Котлин

val requestDetails = JSONObject(payload).getJSONObject("requestDetails")
val requestPackageName = requestDetails.getString("requestPackageName")
val nonce = requestDetails.getString("nonce")
val timestampMillis = requestDetails.getLong("timestampMillis")
val currentTimestampMillis = ...

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request. See 'Generate a nonce'
        // section of the doc on how to store/compute the expected nonce.
    || !nonce.equals(expectedNonce)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Ява

JSONObject requestDetails =
    new JSONObject(payload).getJSONObject("requestDetails");
String requestPackageName = requestDetails.getString("requestPackageName");
String nonce = requestDetails.getString("nonce");
long timestampMillis = requestDetails.getLong("timestampMillis");
long currentTimestampMillis = ...;

// Ensure the token is from your app.
if (!requestPackageName.equals(expectedPackageName)
        // Ensure the token is for this specific request. See 'Generate a nonce'
        // section of the doc on how to store/compute the expected nonce.
    || !nonce.equals(expectedNonce)
        // Ensure the freshness of the token.
    || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) {
        // The token is invalid! See below for further checks.
        ...
}

Поле целостности приложения

Поле appIntegrity содержит информацию, связанную с пакетом.

"appIntegrity": {
  // PLAY_RECOGNIZED, UNRECOGNIZED_VERSION, or UNEVALUATED.
  "appRecognitionVerdict": "PLAY_RECOGNIZED",
  // The package name of the app.
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  "packageName": "com.package.name",
  // The sha256 digest of app certificates (base64-encoded URL-safe).
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  "certificateSha256Digest": ["6a6a1474b5cbbb2b1aa57e0bc3"],
  // The version of the app.
  // This field is populated iff appRecognitionVerdict != UNEVALUATED.
  "versionCode": "42"
}

appRecognitionVerdict может иметь следующие значения:

PLAY_RECOGNIZED
Приложение и сертификат соответствуют версиям, распространяемым Google Play.
UNRECOGNIZED_VERSION
Имя сертификата или пакета не соответствует записям Google Play.
UNEVALUATED
Целостность приложения не была оценена. Не было выполнено необходимое требование, например, устройство не должно быть достаточно надёжным.

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

Котлин

val appIntegrity = JSONObject(payload).getJSONObject("appIntegrity")
val appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict")

if (appRecognitionVerdict == "PLAY_RECOGNIZED") {
    // Looks good!
}

Ява

JSONObject appIntegrity =
    new JSONObject(payload).getJSONObject("appIntegrity");
String appRecognitionVerdict =
    appIntegrity.getString("appRecognitionVerdict");

if (appRecognitionVerdict.equals("PLAY_RECOGNIZED")) {
    // Looks good!
}

Вы также можете вручную проверить имя пакета приложения, версию приложения и сертификаты приложения.

Поле целостности устройства

Поле deviceIntegrity может содержать одно значение deviceRecognitionVerdict , которое имеет одну или несколько меток, отражающих эффективность обеспечения целостности приложения устройством. Если устройство не соответствует критериям ни одной из меток, поле deviceIntegrity не содержит deviceRecognitionVerdict .

"deviceIntegrity": {
  // "MEETS_DEVICE_INTEGRITY" is one of several possible values.
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"]
}

По умолчанию deviceRecognitionVerdict может содержать следующее:

MEETS_DEVICE_INTEGRITY
Приложение работает на подлинном и сертифицированном устройстве Android. На устройствах Android 13 и выше имеется аппаратное подтверждение того, что загрузчик устройства заблокирован, а загруженная ОС Android является сертифицированным образом производителя устройства.
Пусто (пустое значение)
Приложение запущено на устройстве, имеющем признаки атаки (например, перехват API) или взлома системы (например, наличие прав root), либо приложение не запущено на физическом устройстве (например, эмулятор, не прошедший проверку целостности Google Play).

Чтобы убедиться, что токен поступил от надежного устройства, проверьте, что deviceRecognitionVerdict соответствует ожидаемому значению, как показано в следующем фрагменте кода:

Котлин

val deviceIntegrity =
    JSONObject(payload).getJSONObject("deviceIntegrity")
val deviceRecognitionVerdict =
    if (deviceIntegrity.has("deviceRecognitionVerdict")) {
        deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString()
    } else {
        ""
    }

if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) {
    // Looks good!
}

Ява

JSONObject deviceIntegrity =
    new JSONObject(payload).getJSONObject("deviceIntegrity");
String deviceRecognitionVerdict =
    deviceIntegrity.has("deviceRecognitionVerdict")
    ? deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString()
    : "";

if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) {
    // Looks good!
}

Если у вас возникли проблемы с проверкой целостности устройства, убедитесь, что установлена ​​заводская прошивка (например, путём сброса настроек устройства) и загрузчик заблокирован. Вы также можете создать тесты Play Integrity API в Play Console .

Условные метки устройств

Если ваше приложение выпускается в Google Play Games для ПК , deviceRecognitionVerdict также может содержать следующую метку:

MEETS_VIRTUAL_INTEGRITY
Приложение работает на эмуляторе Android с сервисами Google Play. Эмулятор проходит проверку целостности системы и соответствует основным требованиям совместимости с Android.

Дополнительная информация об устройстве и отзыв устройства

Если вы согласитесь получать дополнительные метки в вердикте о целостности, deviceRecognitionVerdict может содержать следующие дополнительные метки:

MEETS_BASIC_INTEGRITY
Приложение запущено на устройстве, прошедшем базовые проверки целостности системы. Загрузчик устройства может быть заблокирован или разблокирован, а состояние загрузки может быть верифицированным или неверифицированным. Устройство может быть несертифицированным, в этом случае Google не может предоставить никаких гарантий безопасности, конфиденциальности или совместимости приложения. В Android 13 и более поздних версиях вердикт MEETS_BASIC_INTEGRITY требует только, чтобы корень доверия для аттестации был предоставлен Google.
MEETS_STRONG_INTEGRITY
Приложение работает на подлинном и сертифицированном устройстве Android с последним обновлением безопасности.
  • На устройствах Android 13 и выше вердикт MEETS_STRONG_INTEGRITY требует MEETS_DEVICE_INTEGRITY и обновлений безопасности за последний год для всех разделов устройства, включая исправление раздела ОС Android и исправление раздела поставщика.
  • На Android 12 и ниже для вердикта MEETS_STRONG_INTEGRITY требуется только аппаратное подтверждение целостности загрузки и не требуется наличие на устройстве последнего обновления безопасности. Поэтому при использовании MEETS_STRONG_INTEGRITY рекомендуется также учитывать версию Android SDK в поле deviceAttributes .

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

Атрибуты устройства

Вы также можете включить атрибуты устройства, которые сообщают версию Android SDK ОС Android, установленной на устройстве. В будущем этот список может быть расширен другими атрибутами устройства.

Значение версии SDK — это номер версии Android SDK, указанный в Build.VERSION_CODES . Версия SDK не оценивается, если необходимое требование не было выполнено. В этом случае поле sdkVersion не задано, поэтому поле deviceAttributes пусто. Это может произойти по следующим причинам:

  • Устройство недостаточно надежно.
  • На устройстве возникли технические неполадки.

Если вы согласитесь получать deviceAttributes , поле deviceIntegrity будет иметь следующее дополнительное поле:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceAttributes": {
    // 33 is one possible value, which represents Android 13 (Tiramisu).
    "sdkVersion": 33
  }
}

Если версия SDK не оценена, поле deviceAttributes будет установлено следующим образом:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceAttributes": {}  // sdkVersion field is not set.
}

Недавняя активность устройства

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

Если вы согласитесь получать recentDeviceActivity , поле deviceIntegrity будет иметь два значения:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "recentDeviceActivity": {
    // "LEVEL_2" is one of several possible values.
    "deviceActivityLevel": "LEVEL_2"
  }
}

Определения deviceActivityLevel различаются в зависимости от режима и могут иметь одно из следующих значений:

Уровень недавней активности устройства Стандартные запросы на маркер целостности API на этом устройстве за последний час для каждого приложения Запросы токена целостности классического API на этом устройстве за последний час для каждого приложения
LEVEL_1 (самый низкий) 10 или меньше 5 или меньше
LEVEL_2 От 11 до 25 От 6 до 10
LEVEL_3 От 26 до 50 лет Между 11 и 15
LEVEL_4 (высший) Более 50 Более 15
UNEVALUATED Недавняя активность устройства не была оценена. Это могло произойти по следующим причинам:
  • Устройство недостаточно надежно.
  • Версия вашего приложения, установленного на устройстве, неизвестна Google Play.
  • Технические проблемы с устройством.

Отзыв устройства (бета)

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

Если вы включите deviceRecall , поле deviceIntegrity будет содержать информацию об отзыве устройства, которую вы установили для конкретного устройства:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceRecall": {
    "values": {
      "bitFirst": true,
      "bitSecond": false,
      "bitThird": true
    },
    "writeDates": {
      // Write time in YYYYMM format in UTC.
      "yyyymmFirst": 202401,
      // Note that yyyymmSecond is not set because bitSecond is false.
      "yyyymmThird": 202310
    }
  }
}

deviceRecall разделен на два поля:

  • values : вызовите значения битов, которые вы ранее установили для этого устройства.
  • writeDates : Вызов даты записи бита в формате UTC с точностью до года и месяца. Дата записи бита отзыва будет обновляться каждый раз, когда бит устанавливается в true , и будет удалена, когда бит устанавливается в false .

В случае, если информация об отзыве устройства недоступна, значение отзыва устройства будет пустым:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceRecall": {
    "values": {},
    "writeDates": {}
  }
}

Поле данных счета

Поле accountDetails содержит единственное значение appLicensingVerdict , которое отображает статус лицензии Google Play приложения для учётной записи пользователя, вошедшего в систему на устройстве. Если у учётной записи пользователя есть лицензия Google Play для приложения, это означает, что он скачал или купил его в Google Play.

"accountDetails": {
  // This field can be LICENSED, UNLICENSED, or UNEVALUATED.
  "appLicensingVerdict": "LICENSED"
}

appLicensingVerdict может иметь одно из следующих значений:

LICENSED
У пользователя есть право на использование приложения. Другими словами, пользователь установил или обновил ваше приложение из Google Play на своём устройстве.
UNLICENSED
У пользователя нет прав на приложение. Это происходит, например, когда пользователь загружает ваше приложение из сторонних источников или не приобретает его в Google Play. Чтобы исправить это, вы можете показать пользователям диалоговое окно GET_LICENSED .
UNEVALUATED

Детали лицензирования не были оценены, поскольку было пропущено необходимое требование.

Это может произойти по нескольким причинам, включая следующие:

  • Устройство недостаточно надежно.
  • Версия вашего приложения, установленного на устройстве, неизвестна Google Play.
  • Пользователь не авторизован в Google Play.

Чтобы проверить, есть ли у пользователя права на ваше приложение, проверьте, что appLicensingVerdict соответствует ожидаемому значению, как показано в следующем фрагменте кода:

Котлин

val accountDetails = JSONObject(payload).getJSONObject("accountDetails")
val appLicensingVerdict = accountDetails.getString("appLicensingVerdict")

if (appLicensingVerdict == "LICENSED") {
    // Looks good!
}

Ява

JSONObject accountDetails =
    new JSONObject(payload).getJSONObject("accountDetails");
String appLicensingVerdict = accountDetails.getString("appLicensingVerdict");

if (appLicensingVerdict.equals("LICENSED")) {
    // Looks good!
}

Поле сведений об окружающей среде

Вы также можете подписаться на дополнительные сигналы об окружающей среде. Анализ риска доступа к приложениям сообщает вашему приложению о наличии других запущенных приложений, которые могут использоваться для захвата экрана, отображения оверлеев или управления устройством. Вердикт Play Protect сообщает, включена ли на устройстве защита Google Play и обнаружено ли известное вредоносное ПО.

Если вы включили вердикт App Access Risk или Play Protect в Google Play Console, ваш ответ API будет включать поле environmentDetails . Поле environmentDetails может содержать два значения: appAccessRiskVerdict и playProtectVerdict .

Вердикт о риске доступа к приложению

После включения поле environmentDetails в полезной нагрузке API Play Integrity будет содержать новый вердикт о риске доступа к приложению.

{
  "requestDetails": { ... },
  "appIntegrity": { ... },
  "deviceIntegrity": { ... },
  "accountDetails": { ... },
  "environmentDetails": {
      "appAccessRiskVerdict": {
          // This field contains one or more responses, for example the following.
          "appsDetected": ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
      }
 }
}

Если риск доступа к приложению был оценен, appAccessRiskVerdict содержит поле appsDetected с одним или несколькими ответами. Эти ответы относятся к одной из следующих двух групп в зависимости от источника установки обнаруженных приложений:

  • Приложения Play или системные приложения : приложения, установленные через Google Play или предустановленные производителем устройства в системный раздел устройства (обозначается флагом FLAG_SYSTEM ). Ответы для таких приложений имеют префикс KNOWN_ .

  • Другие приложения : приложения, не установленные через Google Play. Сюда не входят приложения, предустановленные в системный раздел производителем устройства. Ответы для таких приложений начинаются с UNKNOWN_ .

Могут быть возвращены следующие ответы:

KNOWN_INSTALLED , UNKNOWN_INSTALLED
Установлены приложения, соответствующие соответствующему источнику установки.
KNOWN_CAPTURING , UNKNOWN_CAPTURING
Запущены приложения с разрешениями, которые могут использоваться для просмотра экрана во время работы вашего приложения. Это не относится ни к каким проверенным службам специальных возможностей, известным Google Play и работающим на устройстве.
KNOWN_CONTROLLING , UNKNOWN_CONTROLLING
Запущены приложения с разрешёнными разрешениями, которые можно использовать для управления устройством и непосредственного управления вводом данных в вашем приложении, а также для захвата входных и выходных данных вашего приложения. Это не относится ни к каким проверенным службам специальных возможностей, известным Google Play и работающим на устройстве.
KNOWN_OVERLAYS , UNKNOWN_OVERLAYS
Запущены приложения с разрешениями, которые могут использоваться для отображения оверлеев в вашем приложении. Это не относится ни к одному из проверенных сервисов специальных возможностей, известных Google Play и работающих на устройстве.
Пусто (пустое значение)

Риск доступа к приложению не оценивается, если необходимое требование не выполнено. В этом случае поле appAccessRiskVerdict пусто. Это может произойти по нескольким причинам, включая следующие:

  • Устройство недостаточно надежно.
  • Форм-фактор устройства не соответствует типу телефона, планшета или складного устройства.
  • Устройство не работает под управлением Android 6 (уровень API 23) или выше.
  • Версия вашего приложения, установленного на устройстве, неизвестна Google Play.
  • Версия Google Play Store на устройстве устарела.
  • Учетная запись пользователя не имеет лицензии Play.
  • Использован стандартный запрос с параметром verdictOptOut .
  • Стандартный запрос использовался с версией библиотеки Play Integrity API, которая пока не поддерживает риск доступа приложения для стандартных запросов.

Риск доступа приложения автоматически исключает проверенные службы доступности, прошедшие расширенную проверку доступности в Google Play (установленные любым магазином приложений на устройстве). «Исключено» означает, что проверенные службы доступности, работающие на устройстве, не возвращают ответ о захвате, контроле или наложении в вердикте о риске доступа приложения. Чтобы запросить расширенную проверку доступности в Google Play для вашего приложения, опубликуйте его в Google Play, убедившись, что флаг isAccessibilityTool в манифесте вашего приложения установлен в значение true, или запросите проверку .

Примеры вердиктов о риске доступа к приложению

В следующей таблице приведены некоторые примеры вердиктов о риске доступа к приложениям и их значения (в этой таблице не перечислены все возможные результаты):

Пример ответа о вердикте о риске доступа к приложению Интерпретация
appsDetected:
["KNOWN_INSTALLED"]
Устанавливаются только те приложения, которые распознаются Google Play или предустановлены в системный раздел производителем устройства.
Не запущено ни одного приложения, которое могло бы привести к вердиктам «захват, управление или наложение».
appsDetected:
["KNOWN_INSTALLED",
"UNKNOWN_INSTALLED",
"UNKNOWN_CAPTURING"]
Имеются приложения, установленные Google Play или предустановленные в системном разделе производителем устройства.
Запущены и другие приложения, которым предоставлены разрешения, позволяющие просматривать экран или захватывать другие входные и выходные данные.
appsDetected:
["KNOWN_INSTALLED",
"KNOWN_CAPTURING",
"UNKNOWN_INSTALLED",
"UNKNOWN_CONTROLLING"]
Запущены системные приложения или приложения Play с включенными разрешениями, которые можно использовать для просмотра экрана или захвата других входов и выходов.
Также запущены и другие приложения, имеющие включенные разрешения, которые можно использовать для управления устройством и непосредственного управления вводом в ваше приложение.
appAccessRiskVerdict: {} Риск доступа к приложению не оценивается, поскольку не было выполнено необходимое требование. Например, устройство оказалось недостаточно надёжным.

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

Котлин

val environmentDetails =
    JSONObject(payload).getJSONObject("environmentDetails")
val appAccessRiskVerdict =
    environmentDetails.getJSONObject("appAccessRiskVerdict")

if (appAccessRiskVerdict.has("appsDetected")) {
    val appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString()
    if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) {
        // Looks good!
    }
}

Ява

JSONObject environmentDetails =
    new JSONObject(payload).getJSONObject("environmentDetails");
JSONObject appAccessRiskVerdict =
    environmentDetails.getJSONObject("appAccessRiskVerdict");

if (appAccessRiskVerdict.has("appsDetected")) {
    String appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString()
    if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) {
        // Looks good!
    }
}
Устранение вердиктов о рисках доступа к приложениям

В зависимости от уровня риска вы можете решить, какие вердикты о риске доступа к приложению следует принимать, прежде чем разрешить пользователю выполнить запрос или действие. Существуют необязательные уведомления Google Play, которые можно показывать пользователю после проверки вердикта о риске доступа к приложению. Вы можете показать CLOSE_UNKNOWN_ACCESS_RISK , чтобы попросить пользователя закрыть неизвестные приложения, вызывающие вердикт о риске доступа к приложению, или CLOSE_ALL_ACCESS_RISK , чтобы попросить пользователя закрыть все приложения (известные и неизвестные), вызывающие вердикт о риске доступа к приложению.

Вердикт Play Protect

После включения поле environmentDetails в полезной нагрузке Play Integrity API будет содержать вердикт Play Protect:

"environmentDetails": {
  "playProtectVerdict": "NO_ISSUES"
}

playProtectVerdict может иметь одно из следующих значений:

NO_ISSUES
Play Protect включен и не обнаружил никаких проблем с приложением на устройстве.
NO_DATA
Play Protect включен, но сканирование ещё не проводилось. Возможно, устройство или приложение Play Маркет недавно были сброшены.
POSSIBLE_RISK
Функция Play Protect отключена.
MEDIUM_RISK
Функция Play Protect включена и обнаружила на устройстве потенциально опасные приложения.
HIGH_RISK
Функция Play Protect включена и обнаружила на устройстве опасные приложения.
UNEVALUATED

Вердикт Play Protect не был оценен.

Это может произойти по нескольким причинам, включая следующие:

  • Устройство недостаточно надежно.
  • Учетная запись пользователя не имеет лицензии Play.

Руководство по использованию вердикта Play Protect

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

NO_ISSUES
Play Protect включен и не обнаружил никаких проблем, поэтому никаких действий со стороны пользователя не требуется.
POSSIBLE_RISK и NO_DATA
При получении таких вердиктов попросите пользователя убедиться, что Play Protect включён и выполнено сканирование. NO_DATA может появляться только в редких случаях.
MEDIUM_RISK и HIGH_RISK
В зависимости от вашей готовности к риску вы можете попросить пользователя запустить Play Protect и принять меры в соответствии с предупреждениями Play Protect. Если пользователь не может выполнить эти требования, вы можете заблокировать ему доступ к серверу.