Google Play 游戏服务服务器端访问

我们建议您对玩家进行身份验证,并将玩家的身份安全地传递给后端服务器。这样,您的游戏就可以安全地检索玩家身份和其他数据,而无需担心在设备传输过程中可能遭到篡改。

在这种情况下,玩家成功登录后,您可以从 Play 游戏服务 v2 SDK 请求一个特殊的一次性代码(称为“服务器授权码”),客户端会将此代码传递给服务器。然后,在服务器上,将服务器授权码换取一个 OAuth 2.0 令牌,服务器可以使用该令牌调用 Google Play 游戏服务 API。

如需有关在游戏中添加登录功能的更多指导,请参阅Android 游戏登录

离线访问需要执行以下步骤

  1. 在 Google Play 管理中心:为您的游戏服务器创建凭据。凭据的 OAuth 客户端类型将是“网络”。
  2. 在 Android 应用中:作为登录的一部分,为您的服务器凭据请求一个服务器授权码,并将其传递给您的服务器。
  3. 在您的游戏服务器上:使用 Google 身份验证服务将服务器授权码换取 OAuth 访问令牌,然后使用该令牌调用 Play 游戏服务 REST API

开始之前

您首先需要在Google Play 管理中心添加您的游戏,如设置 Google Play 游戏服务中所述,并将其与您的游戏集成Play 游戏服务登录

创建服务器端 Web 应用

Google Play 游戏服务不为 Web 游戏提供后端支持。但是,它确实为您的 Android 游戏服务器提供后端支持。

如果您想在服务器端应用中使用Google Play 游戏服务 REST API,请按照以下步骤操作

  1. Google Play 管理中心,选择一个游戏。
  2. 转到 Play 游戏服务 > 设置和管理 > 配置
  3. 选择添加凭据以进入添加凭据页面。选择游戏服务器作为凭据类型,然后继续进入授权部分。
    1. 如果您的游戏服务器已拥有 OAuth 客户端 ID,请从下拉菜单中选择它。保存更改后,继续下一部分
    2. 如果您的游戏服务器没有现有的 OAuth 客户端 ID,您可以创建一个。
      1. 点击创建 OAuth 客户端,然后点击创建 OAuth 客户端 ID 链接。
      2. 这将带您进入 Google Cloud Platform 中与您的游戏关联的项目的创建 OAuth 客户端 ID 页面。
      3. 填写页面表单并点击创建。请务必将应用类型设置为“网络应用”。
      4. 返回添加凭据页面授权部分,选择新创建的 OAuth 客户端并保存您的更改。

获取服务器授权码

获取游戏可在后端服务器上用于访问令牌的服务器授权码

  1. 从客户端调用 requestServerSideAccess

    1. 请务必使用为您的游戏服务器注册的 OAuth 客户端 ID,而不是您的 Android 应用的 OAuth 客户端 ID。
    2. (可选)如果您的游戏服务器需要离线访问(使用刷新令牌进行长期访问)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.
        }
    });
    
  2. 将 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 shouldn't 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,并将 ID 设置为 'me'

好友

有关详情,请参阅好友指南。

成就

有关详情,请参阅成就指南。

排行榜

有关详情,请参阅排行榜指南。

  • 想要获取游戏中所有排行榜的列表?调用 Leaderboards.list

  • 如果玩家玩完游戏,您可以将其分数提交到 Scores.submit,并查看是否是新的最高分。

  • 要显示排行榜,请从 Scores.list 获取数据并将其显示给用户。

  • 使用 Scores.listWindow 查找接近用户最高分数的各种分数。

  • 要获取有关玩家在特定排行榜中分数(例如,如果玩家在前 12% 的所有玩家中)的更多信息,请调用 Scores.get

  • 如果您正在调试游戏,可以从管理 API 调用 Scores.reset,以重置该玩家在特定排行榜中的所有分数。