將電腦版 Play Integrity 整合至應用程式

電腦版 Play Integrity 可協助您檢查遊戲事件和伺服器要求,確認來源是正版電腦裝置上正規的 Google Play 遊戲電腦版執行個體。偵測到有潛在風險的裝置和不明模擬器後,遊戲的後端伺服器就能採取適當因應行動,防範作弊、未經授權的存取、詐欺流量和濫用情形。

先決條件

步驟 1:決定在遊戲中使用 Play Integrity for PC 的方式

決定何時呼叫 Play Integrity for PC,以取得環境的完整性判定結果。舉例來說,您可以在遊戲開啟、玩家登入或加入多人遊戲時要求判定結果。然後決定如何處理不同的完整性回應。例如,你可以執行下列動作:

  • 收集回覆內容,但不採取任何強制措施,並在內部分析資料,瞭解這是否為有用的濫用信號。
  • 收集回應,並在後端伺服器上實作邏輯,允許通過完整性判定結果的裝置正常執行遊戲,同時對來自可疑環境的流量提出質疑或拒絕存取。
  • 收集回應並在後端實作邏輯,將通過完整性檢查的裝置上的玩家配對在一起,同時將來自可疑環境的流量配對在一起。

步驟 2:在遊戲中要求完整性權杖

為電腦版 Play Integrity 服務預熱

準備 (或「暖機」) 電腦版 Play Integrity,讓 Google Play 能夠在裝置上智慧快取部分認證資訊,進而在您索取完整性判定結果時,縮短關鍵路徑上的延遲時間。您可以在遊戲開啟後立即非同步執行這項操作,以便在需要時發出完整性要求。

void PrepareIntegrityToken(
  const PrepareIntegrityTokenParams & params,
  PrepareIntegrityTokenContinuation continuation
)

成功時,系統會使用包含 RequestTokenDataPrepareIntegrityTokenResultValue 呼叫續傳,該資料應做為要求完整性權杖的依據。這項資料應快取在記憶體中,並在應用程式工作階段期間重複使用,以呼叫 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();
}

要求完整性權杖

完整性權杖是遊戲用來驗證裝置是否遭到竄改的機制。每當遊戲發出伺服器要求,而您想檢查這項要求是否確實時,都應索取完整性權杖,然後將其傳送至遊戲的後端伺服器,用於解密及驗證。

使用 Play Integrity API 檢查電腦版應用程式中的使用者動作時,您可以利用 RequestIntegrityTokenParams::request_hash 欄位應對竄改攻擊。舉例來說,您可能要向遊戲後端伺服器回報玩家分數,而您的伺服器想驗證 Proxy 伺服器未竄改分數,在此情況下,就適合使用上述欄位。電腦版 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 伺服器上解密完整性權杖,才能取得裝置完整性判定結果:

  1. 在連結至應用程式的 Google Cloud 專案中建立服務帳戶
  2. 在應用程式伺服器上,使用 playintegrity 範圍從服務帳戶憑證中擷取存取權杖,然後提出下列要求:

    playintegrity.googleapis.com/v1/<var>PACKAGE_NAME</var>:decodePcIntegrityToken -d \
     '{ "integrity_token": "<var>INTEGRITY_TOKEN</var>" }'
    
  3. 讀取 JSON 回應。

產生的酬載是包含完整性判定結果和詳細資料的純文字權杖,以及開發人員提供的資訊。解密後的完整性權杖如下所示:

{
  "requestDetails": {
    "requestPackageName": "com.your.package.name",
    "requestTime": "2025-08-29T13:10:37.285Z",
    "requestHash": "your_request_hash_string"
  },
  "deviceIntegrity": {
    "deviceRecognitionVerdict": [
      "MEETS_PC_INTEGRITY"
    ]
  },
}

驗證完整性權杖

解碼後的完整性權杖 requestDetails 欄位包含要求的相關資訊,包括開發人員在 requestHash 中提供的資訊。

requestHashpackageName 欄位應與原始要求的值相符。因此,請確認 requestPackageNamerequestHash 與原始要求中傳送的值相符,藉此驗證 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 檢查的電腦上執行 (這是 MEETS_PC_INTEGRITY 回應)。遊戲的後端伺服器可以收集這項資訊,並據此判斷遊戲應採取哪些行動,例如允許遊戲事件繼續進行,或拒絕存取高風險流量。

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_PC_INTEGRITY"]
}

deviceRecognitionVerdict 的值可能如下:

MEETS_PC_INTEGRITY
遊戲是在正版電腦環境中執行,且未偵測到任何裝置端竄改行為。
空白 (空白值)
執行遊戲的裝置可能遭受攻擊 (例如掛接 API) 或系統遭到入侵 (例如裝置執行的 Google 桌面服務版本遭到竄改);或者,遊戲不是在實體裝置上執行 (例如未通過 Google Play 完整性檢查的模擬器)。

步驟 5:處理錯誤代碼

如果遊戲發出 Play Integrity for PC 要求,但呼叫失敗,遊戲會收到錯誤代碼。發生這類錯誤的原因有很多,例如環境問題 (如網路連線不佳)、API 整合問題,或是惡意活動和進行中的攻擊。

可重試的錯誤代碼

這些錯誤有時是暫時性的,因此您應使用指數輪詢策略重試呼叫。

IntegrityError 錯誤說明 錯誤代碼
kNetworkError 裝置的網路連線問題。 5
kTooManyRequests 裝置傳送的要求過多。 6
kClientTransientError 用戶端發生暫時性問題。 7

如需重試策略的更多建議,請參閱這篇文章

無法重試的錯誤代碼

在這種情況下,自動重試可能無法解決問題。不過,如果使用者能解決造成問題的原因,就能透過手動重試方式解決問題。

IntegrityError 錯誤說明 錯誤代碼 建議採取的行動
kError 執行 SDK 動作期間發生嚴重錯誤。 1 請先驗證 API 實作,再重試。
kCloudProjectNumberIsInvalid Cloud 專案編號無效。 2 確認 Google Cloud 控制台已正確設定雲端專案編號,且要求是使用正確的雲端專案編號提出。
kRequestHashTooLong 要求雜湊過長。 3 產生的要求雜湊過長。請確認長度少於 500 個半形字元。
kNoValidPreparedTokenFound 在提出權杖要求前,沒有準備好的權杖。 4 在發出 [RequestIntegrityToken][request-integrity-token] 呼叫前,請先呼叫 [PrepareIntegrityToken][prepare-token] 動作。
kSdkRuntimeUpdateRequired Play for Native SDK 需要更新。 8 確認裝置上的 Google Play 服務用戶端為最新版本,且您使用的是最新版 Play for Native PC SDK。