Tích hợp API Tính toàn vẹn của Play cho máy tính vào ứng dụng

Tính năng Tính toàn vẹn của Play dành cho máy tính giúp bạn kiểm tra để đảm bảo các sự kiện trong trò chơi và yêu cầu gửi tới máy chủ đến từ một phiên bản chính hãng của Google Play Games dành cho máy tính trên một thiết bị máy tính chính hãng. Bằng cách phát hiện các thiết bị tiềm ẩn rủi ro và trình mô phỏng không xác định, máy chủ phụ trợ của trò chơi có thể phản hồi bằng những hành động thích hợp để ngăn chặn hành vi gian lận, truy cập trái phép, lưu lượng truy cập gian lận và hành vi sai trái.

Điều kiện tiên quyết

Bước 1: Quyết định cách bạn sẽ sử dụng API Tính toàn vẹn của Play cho máy tính trong trò chơi

Quyết định thời điểm bạn sẽ gọi API Tính toàn vẹn của Play cho máy tính để nhận kết quả về tính toàn vẹn của môi trường. Ví dụ: bạn có thể yêu cầu kết quả khi trò chơi được mở, khi người chơi đăng nhập hoặc khi người chơi tham gia trò chơi nhiều người chơi. Sau đó, hãy quyết định cách bạn sẽ xử lý các phản hồi khác nhau về tính toàn vẹn. Ví dụ, bạn có thể:

  • Thu thập phản hồi mà không áp dụng bất kỳ biện pháp thực thi nào và phân tích dữ liệu nội bộ để biết liệu đó có phải là tín hiệu hữu ích về hành vi sai trái hay không.
  • Thu thập phản hồi và triển khai logic trên máy chủ phụ trợ để cho phép những thiết bị vượt qua kết quả kiểm tra tính toàn vẹn chơi trò chơi của bạn bình thường, đồng thời thách thức hoặc từ chối quyền truy cập đối với lưu lượng truy cập đến từ các môi trường đáng ngờ.
  • Thu thập phản hồi và triển khai logic trên phần phụ trợ để ghép những người chơi trên các thiết bị vượt qua quy trình kiểm tra tính toàn vẹn với nhau, đồng thời ghép lưu lượng truy cập đến từ các môi trường đáng ngờ với nhau.

Bước 2: Yêu cầu mã thông báo về tính toàn vẹn trong trò chơi

Khởi động API Tính toàn vẹn của Play cho máy tính

Chuẩn bị (hoặc "khởi động") API Tính toàn vẹn của Play cho máy tính. Điều này cho phép Google Play lưu một phần thông tin chứng thực trên thiết bị vào bộ nhớ đệm một cách thông minh để giảm độ trễ trên đường dẫn quan trọng khi bạn yêu cầu kết quả về tính toàn vẹn. Bạn có thể thực hiện việc này không đồng bộ ngay khi trò chơi mở để có thể đưa ra các yêu cầu về tính toàn vẹn theo yêu cầu khi cần.

void PrepareIntegrityToken(
  const PrepareIntegrityTokenParams & params,
  PrepareIntegrityTokenContinuation continuation
)

Khi thành công, lệnh tiếp tục sẽ được gọi bằng một PrepareIntegrityTokenResultValue chứa một RequestTokenData mà bạn nên dùng để yêu cầu mã thông báo về tính toàn vẹn. Dữ liệu này phải được lưu vào bộ nhớ đệm và dùng lại trong suốt phiên hoạt động của ứng dụng cho các lệnh gọi đến RequestIntegrityToken.

Chỉ khi ứng dụng của bạn xác định rằng cần phải đánh giá lại hoàn toàn kết quả về tính toàn vẹn, thì bạn mới nên gọi PrepareIntegrityToken.

Chi tiết
Tham số params: Các tham số chứa số dự án trên Google Cloud.
continuation: Lệnh gọi lại không đồng bộ để trả về trình cung cấp mã thông báo về tính toàn vẹn.

Đoạn mã cho thấy cách gọi thao tác PrepareIntegrityToken được cung cấp như sau:

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();
}

Yêu cầu mã thông báo về tính toàn vẹn

Mã thông báo về tính toàn vẹn là một cơ chế để trò chơi của bạn xác minh rằng thiết bị không bị can thiệp. Bất cứ khi nào trò chơi của bạn tạo một yêu cầu đến máy chủ mà bạn muốn kiểm tra để đảm bảo yêu cầu đó là thật, bạn có thể yêu cầu một mã thông báo về tính toàn vẹn rồi gửi mã này đến máy chủ phụ trợ của trò chơi để giải mã và xác minh.

Khi kiểm tra hành động của người dùng trong ứng dụng bằng API Tính toàn vẹn của Play cho máy tính, bạn có thể dùng trường RequestIntegrityTokenParams::request_hash để giảm thiểu các cuộc tấn công can thiệp. Ví dụ: bạn có thể muốn báo cáo điểm số của người chơi cho máy chủ phụ trợ của trò chơi và máy chủ của bạn muốn xác minh rằng điểm số này không bị máy chủ proxy can thiệp. Play Integrity dành cho máy tính có thể trả về giá trị bạn đặt trong trường này, bên trong phản hồi về tính toàn vẹn đã ký. Nếu không có requestHash, mã thông báo về tính toàn vẹn sẽ chỉ được liên kết với thiết bị chứ không được liên kết với yêu cầu cụ thể, từ đó dẫn đến nguy cơ bị tấn công.

void RequestIntegrityToken(
  const RequestIntegrityTokenParams & params,
  RequestIntegrityTokenContinuation continuation
)

Để giảm thiểu khả năng xảy ra một cuộc tấn công, khi bạn yêu cầu kết quả về tính toàn vẹn:

  • Tính toán chuỗi đại diện của tất cả các tham số yêu cầu có liên quan (ví dụ: SHA256 của quá trình chuyển đổi tuần tự yêu cầu có tính ổn định) dựa trên hành động của người dùng hoặc yêu cầu tới máy chủ đang diễn ra.
  • Đặt trường RequestIntegrityTokenParams::request_hash thành thông báo.
Chi tiết
Tham số params: Các tham số chứa RequestTokenData đã chuẩn bị và hàm băm yêu cầu kiểm tra tính toàn vẹn.
continuation: Lệnh gọi lại không đồng bộ để trả về dữ liệu.

Sau đây là đoạn mã cho biết cách gọi thao tác 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();
}

Bước 3: Tiếp theo, hãy giải mã và xác minh mã thông báo về tính toàn vẹn trên máy chủ phụ trợ của trò chơi

Giải mã mã thông báo về tính toàn vẹn

Sau khi bạn yêu cầu kết quả về tính toàn vẹn, API Tính toàn vẹn của Play sẽ cung cấp mã thông báo phản hồi đã mã hoá. Để có được kết quả về tính toàn vẹn của thiết bị, bạn phải giải mã mã thông báo về tính toàn vẹn trên các máy chủ của Google:

  1. Tạo một tài khoản dịch vụ trong dự án Google Cloud được liên kết với ứng dụng của bạn.
  2. Trên máy chủ của ứng dụng, hãy tìm nạp mã truy cập từ thông tin xác thực tài khoản dịch vụ của bạn bằng phạm vi playintegrity và thực hiện yêu cầu sau:

    playintegrity.googleapis.com/v1/<var>PACKAGE_NAME</var>:decodePcIntegrityToken -d \
     '{ "integrity_token": "<var>INTEGRITY_TOKEN</var>" }'
    
  3. Đọc phản hồi JSON.

Tải trọng phát sinh là một mã thông báo dạng văn bản thuần tuý chứa các kết quả về tính toàn vẹn và thông tin chi tiết cùng với thông tin do nhà phát triển cung cấp. Mã thông báo về tính toàn vẹn đã giải mã có dạng như sau:

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

Xác minh mã thông báo tính toàn vẹn

Trường requestDetails của mã thông báo về tính toàn vẹn đã giải mã chứa thông tin về yêu cầu, bao gồm cả thông tin do nhà phát triển cung cấp trong requestHash.

Các trường requestHashpackageName phải khớp với các trường trong yêu cầu ban đầu. Do đó, hãy xác minh phần requestDetails trong tải trọng JSON bằng cách đảm bảo rằng requestPackageNamerequestHash khớp với nội dung đã gửi trong yêu cầu ban đầu, như minh hoạ trong đoạn mã sau:

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.

Bước 4: Quyết định hành động cần thực hiện dựa trên kết quả về tính toàn vẹn

Trường deviceIntegrity có thể chứa một giá trị deviceRecognitionVerdict duy nhất. Bạn có thể sử dụng giá trị này để xác định xem trò chơi của bạn có đang chạy trên máy tính vượt qua quy trình kiểm tra tính toàn vẹn của Play hay không (đây là một phản hồi MEETS_PC_INTEGRITY). Máy chủ phụ trợ của trò chơi có thể thu thập thông tin này và sử dụng thông tin đó để xác định hành động mà trò chơi nên thực hiện, chẳng hạn như cho phép một sự kiện trong trò chơi tiếp tục hoặc từ chối quyền truy cập vào lưu lượng truy cập có rủi ro.

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

deviceRecognitionVerdict có thể có các giá trị sau:

MEETS_PC_INTEGRITY
Trò chơi đang chạy trên một môi trường máy tính chính thống, nơi không phát hiện thấy hành vi giả mạo trên thiết bị.
Trống (giá trị trống)
Trò chơi đang chạy trên một thiết bị có dấu hiệu bị tấn công (chẳng hạn như hook API) hoặc bị xâm phạm hệ thống (chẳng hạn như thiết bị đang chạy một phiên bản Google Desktop Services bị can thiệp), hoặc ứng dụng không chạy trên một thiết bị thực (chẳng hạn như trình mô phỏng không vượt qua được quy trình kiểm tra tính toàn vẹn của Google Play).

Bước 5: Xử lý mã lỗi

Nếu trò chơi của bạn đưa ra yêu cầu về Tính toàn vẹn của Play cho máy tính và lệnh gọi không thành công, thì trò chơi sẽ nhận được một mã lỗi. Những lỗi này có thể xảy ra vì nhiều lý do, chẳng hạn như các vấn đề về môi trường như kết nối mạng kém, vấn đề với việc tích hợp API hoặc hoạt động độc hại và các cuộc tấn công đang diễn ra.

Mã lỗi có thể thử lại

Nguyên nhân của những lỗi này đôi khi là do các điều kiện tạm thời. Do đó, bạn nên thử lại lệnh gọi bằng chiến lược thời gian đợi luỹ thừa.

IntegrityError Nội dung mô tả về lỗi Mã lỗi
kNetworkError Vấn đề về kết nối mạng trên thiết bị. 5
kTooManyRequests Thiết bị đã gửi quá nhiều yêu cầu. 6
kClientTransientError Vấn đề tạm thời với ứng dụng. 7

Xem tại đây để biết thêm các đề xuất về chiến lược thử lại.

Mã lỗi không thể thử lại

Bạn không thể thử lại theo cách tự động trong những trường hợp này. Tuy nhiên, việc thử lại theo cách thủ công có thể giúp ích nếu người dùng giải quyết tình trạng gây ra sự cố.

IntegrityError Nội dung mô tả về lỗi Mã lỗi Việc nên làm
kError Có lỗi nghiêm trọng trong thao tác SDK. 1 Xác minh việc triển khai API trước khi thử lại.
kCloudProjectNumberIsInvalid Số dự án trên đám mây không hợp lệ. 2 Xác minh rằng bạn đã định cấu hình số dự án trên đám mây một cách chính xác trên Bảng điều khiển Google Cloud và các yêu cầu được thực hiện bằng số dự án trên đám mây chính xác.
kRequestHashTooLong Hàm băm yêu cầu quá dài. 3 Hàm băm yêu cầu được tạo quá dài. Đảm bảo rằng các giá trị này có ít hơn 500 ký tự.
kNoValidPreparedTokenFound Không có mã thông báo được chuẩn bị trước khi đưa ra yêu cầu mã thông báo. 4 Gọi thao tác [PrepareIntegrityToken][prepare-token] trước khi thực hiện lệnh gọi [RequestIntegrityToken][request-integrity-token].
kSdkRuntimeUpdateRequired Bạn cần cập nhật SDK Play cho ứng dụng gốc. 8 Đảm bảo rằng ứng dụng Dịch vụ Google Play trên thiết bị đã được cập nhật và bạn đang sử dụng phiên bản mới nhất của SDK Play cho máy tính gốc.