建議您驗證玩家,安全地將玩家身分傳遞至後端伺服器。這樣一來, 即可安全地擷取玩家身分和其他資料 可能遭到裝置竄改
在這種情況下,玩家成功登入後,您就可以透過 Play 遊戲服務第 2 版 SDK 要求一組一次性代碼 (稱為「伺服器驗證碼」),然後用戶端就會傳遞至伺服器。接著,在伺服器上 交換伺服器驗證碼,以取得伺服器可使用的 OAuth 2.0 權杖 呼叫 Google Play Games Services API。
如需在遊戲中加入登入的其他指引,請參閱 登入 Android 遊戲。
離線存取必須採取以下步驟:
- 在 Google Play 管理中心:建立遊戲伺服器的憑證。 憑證的 OAuth 用戶端類型為「網站」。
- 在 Android 應用程式:在登入時要求取得伺服器憑證的伺服器驗證碼,然後將該驗證碼傳遞至伺服器。
- 在遊戲伺服器:使用 Google 驗證服務交換 OAuth 存取權杖的伺服器驗證碼,然後使用此驗證碼呼叫 Play 遊戲服務 REST API。
事前準備
首先,您需要將遊戲新增到 Google Play 管理中心, 設定 Google Play 遊戲服務。 將 Play 遊戲服務登入功能整合至遊戲。
建立伺服器端網頁應用程式
Google Play 遊戲服務不提供後端功能 支援網頁遊戲但是它會提供後端伺服器支援 以便擷取 YAML 檔案
如要使用 Google Play 遊戲服務的 REST API ,請按照下列步驟操作:
- 在 Google Play 管理中心的遊戲中,依序前往「Play 遊戲服務」>「設定與管理」>「設定」。
- 選取「新增憑證」,即可前往「新增憑證」頁面。選取「遊戲伺服器」做為憑證類型,然後繼續前往「授權」部分。
- 如果遊戲伺服器已有 OAuth 用戶端 ID,請從下拉式選單中選取該 ID。儲存變更後,請繼續前往下一節。
- 如果遊戲伺服器還沒有 OAuth 用戶端 ID,可以先建立。
- 點選「建立 OAuth 用戶端」,然後點選「建立 OAuth 用戶端 ID」連結。
- 系統會導向 Google Cloud Platform 的「建立 OAuth 用戶端 ID」頁面,顯示與遊戲相關聯的 Cloud Platform 專案。
- 填寫頁面的表單,然後按一下「建立」。請務必將應用程式類型設為網頁應用程式。
- 返回「新增憑證」頁面的「授權」部分,選取新建立的 OAuth 用戶端,然後儲存變更。
取得伺服器驗證碼
如要擷取遊戲在後端伺服器取得存取權杖使用的伺服器驗證碼,:
從用戶端呼叫
requestServerSideAccess
。- 請務必使用為遊戲伺服器註冊的 OAuth 用戶端 ID,而非 Android 應用程式的 OAuth 用戶端 ID。
- (選用) 如果遊戲伺服器需要離線存取 Play 遊戲服務 (即使用更新權杖的長期存取權),可將 forceRefreshToken 參數設為 true。
GamesSignInClient gamesSignInClient = PlayGames.getGamesSignInClient(this); gamesSignInClient .requestServerSideAccess(OAUTH_2_WEB_CLIENT_ID, /* forceRefreshToken= */ false) .addOnCompleteListener( task -> { if (task.isSuccessful()) { String serverAuthToken = task.getResult(); // Send authentication code to the backend game server to be // exchanged for an access token and used to verify the player // via the Play Games Services REST APIs. } else { // Failed to retrieve authentication code. } });
傳送 OAuth 驗證碼權杖至後端伺服器以允許進行交換,根據 Play 遊戲服務 REST API 驗證玩家 ID,然後透過遊戲進行驗證。
傳送伺服器驗證碼
傳送伺服器驗證碼至後端伺服器,以交換取得存取權, 重新整理符記請使用存取權杖代表玩家呼叫 Play 遊戲服務 API,然後可選擇是否儲存更新權杖,方便在存取權杖過期時取得新的存取權杖。
下列程式碼片段說明如何在 交換伺服器驗證碼以取得存取的 Java 程式設計語言 符記這會使用 clientserverskeleton 範例應用程式。
/**
* Exchanges the authcode for an access token credential. The credential
* is the associated with the given player.
*
* @param authCode - the non-null authcode passed from the client.
* @param player - the player object which the given authcode is
* associated with.
* @return the HTTP response code indicating the outcome of the exchange.
*/
private int exchangeAuthCode(String authCode, Player player) {
try {
// The client_secret.json file is downloaded from the Google API
// console. This is used to identify your web application. The
// contents of this file should not be shared.
//
File secretFile = new File("client_secret.json");
// If we don't have the file, we can't access any APIs, so return
// an error.
if (!secretFile.exists()) {
log("Secret file : " + secretFile
.getAbsolutePath() + " does not exist!");
return HttpServletResponse.SC_FORBIDDEN;
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
JacksonFactory.getDefaultInstance(), new
FileReader(secretFile));
// Extract the application id of the game from the client id.
String applicationId = extractApplicationId(clientSecrets
.getDetails().getClientId());
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
HTTPTransport,
JacksonFactory.getDefaultInstance(),
"https://oauth2.googleapis.com/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
authCode,
"")
.execute();
log("hasRefresh == " + (tokenResponse.getRefreshToken() != null));
log("Exchanging authCode: " + authCode + " for token");
Credential credential = new Credential
.Builder(BearerToken.authorizationHeaderAccessMethod())
.setJsonFactory(JacksonFactory.getDefaultInstance())
.setTransport(HTTPTransport)
.setTokenServerEncodedUrl("https://www.googleapis.com/oauth2/v4/token")
.setClientAuthentication(new HttpExecuteInterceptor() {
@Override
public void intercept(HttpRequest request)
throws IOException {
}
})
.build()
.setFromTokenResponse(tokenResponse);
player.setCredential(credential);
// Now that we have a credential, we can access the Games API.
PlayGamesAPI api = new PlayGamesAPI(player, applicationId,
HTTPTransport, JacksonFactory.getDefaultInstance());
// Call the verify method, which checks that the access token has
// access to the Games API, and that the player id used by the
// client matches the playerId associated with the accessToken.
boolean ok = api.verifyPlayer();
// Call a Games API on the server.
if (ok) {
ok = api.updatePlayerInfo();
if (ok) {
// persist the player.
savePlayer(api.getPlayer());
}
}
return ok ? HttpServletResponse.SC_OK :
HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
} catch (IOException e) {
e.printStackTrace();
}
return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}
從伺服器呼叫 REST API
請參閱 Google Play 遊戲服務的 REST API。 ,瞭解可用 API 呼叫的完整說明。
以下是幾個實用的 REST API 呼叫範例,歡迎參考:
球員
想要取得已登入玩家的 ID 和設定檔資料嗎?呼叫 [Players.get][]
是 'me'
。
六人行
詳情請參閱「好友」指南。
如要擷取玩家的好友名單,請呼叫 Players.list 搭配
friends_all
做為collection
。如要確認能否存取好友名單,請以
me
做為playerID
呼叫 Players.get,然後在回應中查看profileSettings.friendsListVisibility
欄位。
成就
詳情請參閱「成就」指南。
如要取得目前成就的清單,請呼叫 AchievementDefinitions.list。
然後結合對 Achievements.list 的呼叫,找出玩家已解鎖的成就。
致電 Achievements.unlock 解鎖玩家成就。
呼叫 Achievements.increment 回報成就的進度,瞭解玩家是否已解鎖成就。
如要對尚未發布正式版的遊戲進行偵錯,可以呼叫 Achievements.reset 或 Achievements.resetAll 以便將成就重設為原始狀態。
排行榜
詳情請參閱「排行榜」指南。
想要取得遊戲中所有計分板的清單嗎?撥打電話: Leaderboards.list。
如果玩家已完成遊戲,您可以將玩家分數提交至 Scores.submit,瞭解該分數是否為新的最高分記錄。
如要顯示排行榜,請從 Scores.list 取得資料,並向使用者顯示。
使用 Scores.listWindow 以找出接近使用者最高分的分數。
取得特定排行榜中的玩家得分詳細資訊 (舉例來說,如果玩家的排名是所有玩家中的前 12%),則呼叫 Scores.get。
如果要為遊戲偵錯,您可以從 Management API 呼叫 Scores.reset,重設玩家在特定排行榜的所有分數。