PC 版 Play Integrity を使用すると、ゲーム イベントとサーバー リクエストが、正規の PC デバイス上の PC 版 Google Play Games の正規のインスタンスから送信されていることを確認できます。危険な可能性があるデバイスや不明なエミュレータを検出することで、ゲームのバックエンド サーバーは、不正行為、不正アクセス、不正なトラフィック、不正使用を防ぐための適切な措置を講じることができます。
前提条件
- SDK の設定を完了します。
- Integrity API のセキュリティに関する考慮事項を確認します。
- Integrity API 利用規約と データ処理に関する情報を読み、理解します。
- Google Cloud コンソールで、Cloud プロジェクトを作成するか、 PC 版 Play Integrity で使用する既存の Cloud プロジェクトを選択します。[**API とサービス**] に移動し、 Google Play Integrity API を有効にします。
- PC 版 Play Integrity のリクエストが 1 日あたり 1 万件を超えることが予想される場合は、1 日あたりの最大リクエスト数の引き上げをリクエストする必要があります 。
ステップ 1: ゲームで PC 版 Play Integrity を使用する方法を決定する
PC 版 Play Integrity を呼び出して環境に関する完全性判定の結果を取得するタイミングを決定します。たとえば、ゲームを開いたとき、プレーヤーがログインしたとき、プレーヤーがマルチプレーヤー ゲームに参加したときに判定結果をリクエストできます。次に、さまざまな完全性レスポンスの処理方法を決定します。たとえば、次のような方法があります。
- 強制措置を講じずにレスポンスを収集し、内部でデータを分析して、不正使用の有用なシグナルかどうかを判断します。
- レスポンスを収集し、バックエンド サーバーにロジックを実装して、完全性判定の結果に合格したデバイスがゲームを正常にプレイできるようにします。一方、疑わしい環境からのトラフィックに対しては、チャレンジまたはアクセス拒否を行います。
- レスポンスを収集し、バックエンドにロジックを実装して、完全性チェックに合格したデバイスのプレーヤーをマッチングし、疑わしい環境からのトラフィックをマッチングします。
ステップ 2: ゲームで完全性トークンをリクエストする
PC 版 Play Integrity をウォームアップする
PC 版 Play Integrity を準備(ウォームアップ)します。これにより、完全性判定の結果がリクエストされたときに、Google Play はクリティカル パスのレイテンシを短縮するためにデバイス上の部分的な証明書情報のスマート キャッシングを行うことができます。ゲームを開いたらすぐに非同期でこれを行うことで、必要に応じてオンデマンドで完全性リクエストを行うことができます。
void PrepareIntegrityToken( const PrepareIntegrityTokenParams & params, PrepareIntegrityTokenContinuation continuation )
成功すると、継続は、完全性トークンのリクエストに使用する RequestTokenDataを含む PrepareIntegrityTokenResultValueで呼び出されます。このデータはメモリ内にキャッシュに保存し、アプリケーションのセッションの 期間中、 RequestIntegrityTokenの呼び出しのために再利用する必要があります。
完全性判定の結果を完全に再評価する 必要があるとアプリケーションが判断した場合にのみ、 PrepareIntegrityTokenの呼び出しを行う必要があります。
| 詳細 | |
|---|---|
| パラメータ | params: Google Cloud プロジェクト番号を含むパラメータ。continuation: 完全性トークン プロバイダを返す非同期コールバック。 |
PrepareIntegrityToken アクションの呼び出し方法を示すコード スニペットを次に示します。
google::play::integrity::IntegrityClient client_;
google::play::integrity::PrepareIntegrityTokenResult
IntegrityInterface::PrepareIntegrityToken(int64_t cloud_project_number) {
google::play::integrity::PrepareIntegrityTokenParams params;
params.cloud_project_number = cloud_project_number;
auto promise = std::make_shared<
std::promise<google::play::integrity::PrepareIntegrityTokenResult>>();
client_.PrepareIntegrityToken(
params,
[promise](
google::play::integrity::PrepareIntegrityTokenResult result) {
promise->set_value(std::move(result));
});
return promise->get_future().get();
}
完全性トークンをリクエストする
完全性トークンは、デバイスが改ざんされていないことをゲームが確認するためのメカニズムです。真正なものかどうかを確認したいサーバー リクエストをゲームが実行するたびに、完全性トークンをリクエストして、複合と検証を行うためにゲームのバックエンド サーバーに送信できます。
PC 版 Play Integrity API を使用してアプリ内のユーザー アクションをチェックする場合は、RequestIntegrityTokenParams::request_hash フィールドを利用して改ざん攻撃を軽減できます。たとえば、プレーヤーのスコアをゲームのバックエンド サーバーにレポートするゲームで、プロキシ サーバーによってスコアが改ざんされていないことを確認したい場合があります。PC 版 Play Integrity は、このフィールドに設定した値を、署名付きの完全性レスポンス内で返します。requestHash がなければ、完全性トークンはデバイスにのみバインドされ、特定のリクエストにはバインドされないため、攻撃を受ける可能性が生じます。
void RequestIntegrityToken( const RequestIntegrityTokenParams & params, RequestIntegrityTokenContinuation continuation )
攻撃の可能性を軽減するため、完全性判定の結果をリクエストするときは、次のことを行います。
- 実行中のユーザー アクションまたはサーバー リクエストから、すべての関連するリクエスト パラメータ(安定したリクエストのシリアル化の SHA256 など)のダイジェストを計算します。
- RequestIntegrityTokenParams::request_hash フィールドを ダイジェストに設定します。
| 詳細 | |
|---|---|
| パラメータ | params: 準備された RequestTokenData と完全性チェック リクエスト ハッシュを含むパラメータ。continuation: データを返す非同期コールバック。 |
RequestIntegrityToken アクションの呼び出し方法を示すコード スニペットを次に示します。
absl::StatusOr<google::play::integrity::RequestIntegrityTokenResult>
IntegrityInterface::RequestIntegrityToken(
const google::play::integrity::PrepareIntegrityTokenResult&
prepare_integrity_token_result,
const std::string& request_hash) {
// Check if the prepare_integrity_token_result is OK
if (!prepare_integrity_token_result.ok()) {
return absl::FailedPreconditionError(
absl::StrCat("PrepareIntegrityTokenResult is not OK. Error code: ",
prepare_integrity_token_result.error_code));
}
google::play::integrity::RequestIntegrityTokenParams params{
.request_token_data =
prepare_integrity_token_result.request_token_data,
.request_hash = request_hash};
auto promise = std::make_shared<std::promise<
google::play::integrity::RequestIntegrityTokenResult>>();
client_.RequestIntegrityToken(
params,
[promise](google::play::integrity::RequestIntegrityTokenResult result) {
promise->set_value(std::move(result));
});
return promise->get_future().get();
}
ステップ 3: ゲームのバックエンド サーバーで完全性トークンを復号して検証する
完全性トークンを復号する
完全性判定の結果をリクエストすると、暗号化されたレスポンス トークンが Play Integrity API によって提供されます。デバイスの完全性判定の結果を取得するには、Google のサーバーで完全性トークンを復号する必要があります。
- サービス アカウントを作成します。このサービス アカウントは、アプリにリンクされている Google Cloud プロジェクト内に作成されます。
アプリのサーバーで、playintegrity スコープを使用してサービス アカウントの認証情報からアクセス トークンを取得し、次のリクエストを実行します。
playintegrity.googleapis.com/v1/<var>PACKAGE_NAME</var>:decodePcIntegrityToken -d \ '{ "integrity_token": "<var>INTEGRITY_TOKEN</var>" }'JSON レスポンスを読み取ります。
結果として返されるペイロードは、デベロッパー提供の情報とともに、完全性判定の結果と詳細を含む書式なしテキストのトークンです。復号された完全性トークンは次のようになります。
{
"requestDetails": {
"requestPackageName": "com.your.package.name",
"requestTime": "2025-08-29T13:10:37.285Z",
"requestHash": "your_request_hash_string"
},
"deviceIntegrity": {
"deviceRecognitionVerdict": [
"MEETS_PC_INTEGRITY"
]
},
"accountDetails": {
"appLicensingVerdict": "LICENSED"
}
}
完全性トークンを検証する
デコードされた完全性トークンの requestDetails フィールドには、リクエストに関する情報(requestHash
のデベロッパー提供の情報など)が含まれます。
requestHash フィールドと packageName フィールドは、元のリクエストの値と一致する必要があります。したがって、次のコード
スニペットに示すように、requestPackageName と requestHash が元のリクエストで送信されたものと一致することを確認して、JSON
ペイロードの requestDetails の部分を検証します。
const auto& request_details = json_payload["requestDetails"];
if (request_details.value("requestPackageName", "") != <YOUR_PACKAGE_NAME>) {
// Don't trust the verdicts.
}
// Check for the existence of the request_hash.
// If you set a request hash in the request and it's not present, you shouldn't
// trust the verdicts.
if (!request_details.contains("requestHash")) {
// Don't trust the verdicts.
}
// The requestHash from request_details needs to match the request hash your
// app provided.
if (request_details.value("requestHash", "") != <PROVIDED_REQUEST_HASH>) {
// Don't trust the verdicts.
}
// You can read the rest of payload's fields.
ステップ 4: 完全性判定の結果に基づいて行うアクションを決定する
deviceIntegrity フィールドには、単一の値 deviceRecognitionVerdict
を含めることができます。この値を使用して、ゲームが Play Integrity チェックに合格した PC(MEETS_PC_INTEGRITY
レスポンス)で実行されているかどうかを判断できます。accountDetails フィールドには、単一の値
appLicensingVerdict が含まれます。この値を使用して、ユーザーが Google Play
からライセンスを取得したかどうかを判断できます。ゲームのバックエンド
サーバーは、この情報を収集して、ゲーム イベントの続行を許可するか、危険なトラフィックへのアクセスを拒否するなど、ゲームが実行するアクションを決定するために使用できます。
"deviceIntegrity": {
"deviceRecognitionVerdict": ["MEETS_PC_INTEGRITY"]
}
"accountDetails": {
"appLicensingVerdict": "LICENSED"
}
デバイスの完全性判定の結果
deviceRecognitionVerdict は次のいずれかの値を取ります。
MEETS_PC_INTEGRITY- ゲームは、デバイス上の改ざんが検出されなかった正規の PC 環境で実行されています。
- 空(空の値)
- ゲームは、API フックなどの攻撃やデバイスが改ざんされた Google デスクトップ サービス バージョンを実行しているなどのシステム侵害の兆候があるデバイス、または Google Play の完全性チェックに合格していない仮想デバイス(エミュレータなど)で動作しています。
アカウントの詳細の判定結果
appLicensingVerdict は次のいずれかの値を取ります。
LICENSED- ユーザーはアプリの利用資格を持っています。つまり、ユーザーは Google Play からデバイスにアプリをインストールまたは更新しました。
UNLICENSED- ユーザーはアプリの利用資格を持っていません。ユーザーがアプリをサイドローディングした場合や、アプリを Google Play から取得したのではない場合などが該当します。
UNEVALUATED- 要件が満たされていないため、ライセンスの詳細は評価されませんでした。
これには、次のような理由が考えられます。
- デバイスの信頼性が十分でない。
- デバイスにインストールされているアプリのバージョンが Google Play に認識されていない。
- ユーザーが Google Play にログインしていない。
ステップ 5: エラーコードを処理する
ゲームが PC 版 Play Integrity リクエストを行い、呼び出しに失敗すると、ゲームはエラーコードを受け取ります。これらのエラーは、ネットワーク接続が不安定な環境の問題、API 統合の問題、悪意のあるアクティビティやアクティブな攻撃など、さまざまな理由で発生する可能性があります。
再試行可能なエラーコード
以下のエラーの原因は一時的な事象であることがあるため、指数バックオフ戦略で呼び出しを再試行する必要があります。
| IntegrityError | エラーの説明 | エラーコード |
|---|---|---|
kNetworkError |
デバイスのネットワーク接続の問題。 | 5 |
kTooManyRequests |
デバイスから送信されたリクエストが多すぎます。 | 6 |
kClientTransientError |
クライアントの一時的な問題。 | 7 |
再試行戦略に関するその他の推奨事項については、こちらをご覧ください。
再試行できないエラーコード
以下のようなケースでは、自動再試行を使用できない場合があります。ただし、問題の原因となった事象に対処することで、手動での再試行は可能です。
| IntegrityError | エラーの説明 | エラーコード | 推奨される対応 |
|---|---|---|---|
kError |
SDK の動作中に致命的なエラーが発生しました。 | 1 | 再試行する前に API 実装を確認してください。 |
kCloudProjectNumberIsInvalid |
Cloud プロジェクト番号が無効です。 | 2 | Google Cloud コンソールで Cloud プロジェクト番号が正しく構成されていること、および正しい Cloud プロジェクト 番号でリクエストが行われていることを確認してください。 |
kRequestHashTooLong |
リクエスト ハッシュが長すぎます。 | 3 | 生成されたリクエスト ハッシュが長すぎます。500 文字未満にしてください。 |
kNoValidPreparedTokenFound |
トークン リクエストを行う前に準備されたトークンがありません。 | 4 | [RequestIntegrityToken][request-integrity-token] 呼び出しを行う前に、[PrepareIntegrityToken][prepare-token] アクションを呼び出します。 |
kSdkRuntimeUpdateRequired |
ネイティブ用 Play SDK の更新が必要です。 | 8 | デバイス上の Google Play 開発者サービス クライアントが最新の状態であり、ネイティブ用 PC 版 Play SDK の最新バージョンを使用していることを確認してください。 |
アプリ内でさまざまな Play Integrity API レスポンスをテストする
Play Integrity API によるアプリの挙動を評価するために、テストを作成できます。
ユーザーのメールアドレスを使用して、Google グループ(必要な数だけ)を設定します。これらのユーザーが Google Play のサーバーからアプリで受け取る完全性判定の結果またはエラーコードを選択できます。これにより、可能性のあるすべてのレスポンスとエラーに対して、アプリがどのように反応するかをテストできます。
こちらでチケットを作成し、どの Google グループが どの API レスポンスを受け取るかを報告します。各グループには、次のいずれかを受け取るように割り当てられます。
デバイスの完全性判定の結果に不合格となった場合、ライセンス判定の結果は常に UNEVALUATED を返します。ライセンス判定の結果に合格する ライセンス判定の結果に不合格となる ライセンス判定の結果を評価できない デバイスの完全性に合格する ALLOWLIST_CONFIG_MEETS_PC_INTEGRITY_LICENSEDALLOWLIST_CONFIG_MEETS_PC_INTEGRITY_UNLICENSEDALLOWLIST_CONFIG_MEETS_PC_INTEGRITY_LICENSING_UNEVALUATEDデバイスの完全性に不合格となる なし なし ALLOWLIST_CONFIG_NO_PC_INTEGRITY_LICENSING_UNEVALUATEDリクエストが処理され、テストユーザーがテスト用の事前定義された完全性判定の結果を受け取るための許可リストに追加されると、通知が届きます。