Ativar o acesso do lado do servidor aos serviços relacionados a jogos do Google Play

Se o jogo usa um servidor de back-end, recomendamos usar o Login do Google para autenticar os jogadores e transmitir a identidade do jogador com segurança para o servidor de back-end. Isso também permite que o jogo recupere a identidade do jogador e outros dados de maneira segura, sem estar exposto a possíveis adulterações durante a transmissão pelo dispositivo.

Nesse cenário, o jogo pede que o jogador faça login nos serviços relacionados a jogos do Google Play normalmente. Quando o jogador faz login, o objeto GoogleSignInAccount contém um código de uso único especial chamado de código de autenticação do servidor, que o cliente transmite para o servidor. Em seguida, no servidor, troque o código de autenticação por um token OAuth 2.0 que o servidor possa usar para fazer chamadas para a API dos serviços relacionados a jogos do Google Play.

Para mais orientações sobre como adicionar login nos seus jogos, consulte Fazer login em jogos Android.

Para conferir um exemplo de código detalhado que mostra como usar o Login do Google para autenticar jogadores, consulte o exemplo clientserverskeleton no GitHub.

Siga estas etapas para acesso off-line:

  1. No Google Play Console: crie uma credencial para seu servidor de jogos. O tipo de cliente OAuth da credencial será "Web".
  2. No app Android: como parte do login, solicite um código de autenticação para a credencial do seu servidor e transmita-o para ele.
  3. No servidor de jogos: troque o código de autenticação por um token de acesso OAuth usando os serviços de autenticação do Google. Depois, use-o para chamar as APIs REST dos serviços relacionados a jogos do Google Play.

Antes de começar

Antes de integrar o Login do Google ao seu jogo, adicione-o ao Google Play Console, conforme descrito em Como configurar os serviços relacionados a jogos do Google Play.

Criar um aplicativo da Web do lado do servidor associado para o jogo

Os serviços relacionados a jogos do Google Play não oferecem suporte de back-end para jogos na Web. No entanto, eles oferecem suporte do servidor de back-end para o servidor do seu jogo Android.

Se você quiser usar as APIs REST para serviços do Google Play Games no seu app do lado do servidor, siga estas etapas:

  1. Crie um app da Web associado ao jogo na seção Apps vinculados do Google Play Console. O launch_url não é usado para esse fluxo e pode ficar em branco.
  2. Para acessar as informações das credenciais do seu app, siga estas etapas:
    1. No seu jogo no Google Play Console, clique em Detalhes do jogo.
    2. Role a tela para baixo até a seção API Console Project e clique no link para o projeto do console de APIs.
    3. Na tela APIs e serviços > Credenciais do Console de APIs do Google, faça o download do arquivo client_secret.json do seu app da Web e salve-o em um local acessível pelo servidor. Registre o ID do cliente da credencial para referência futura.
  3. Reinicie o app do lado do servidor para que ele esteja pronto para aceitar solicitações do app cliente do jogo.

Fazer login no cliente

A classe GoogleSignInClient é o ponto de entrada principal para recuperar a conta do jogador que fez login e para fazer login no jogador, caso ele não tenha feito isso no seu app no dispositivo.

Para criar um cliente de login, siga estas etapas:

  1. Crie um cliente de login usando o objeto GoogleSignInOptions. No GoogleSignInOptions.Builder para configurar seu login, especifique GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN.
  2. Também é necessário especificar que o jogo exige um código de autenticação para o servidor de back-end chamando o método GoogleSignInOptions.Builder.requestServerAuthCode() com o ID do cliente do servidor como parâmetro. Você vai recuperar o código de autenticação mais tarde para tokens de acesso no servidor de back-end, conforme descrito em Receber o código de autenticação do servidor.
  3. Chame o método GoogleSignIn.getClient() e transmita as opções configuradas anteriormente. Se a chamada for bem-sucedida, a API Google Sign-In vai retornar uma instância de GoogleSignInClient.
  4. Depois de ter a instância GoogleSignInClient, faça o login do jogador silenciosamente no onResume() da atividade, conforme descrito em Como fazer login silencioso.

Veja um exemplo:

private static final int RC_SIGN_IN = 9001;
private GoogleSignInClient mGoogleSignInClient;

private void startSignInForAuthCode() {

  // Client ID for your backend server.
  String webClientId = getString(R.string.webclient_id);

  GoogleSignInOptions signInOption = new
      GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
      .requestServerAuthCode(webClientId)
      .build();

  GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption);
  Intent intent = signInClient.getSignInIntent();
  startActivityForResult(intent, RC_SIGN_IN);
}

Receber o código de autenticação do servidor

Para recuperar um código de autenticação do servidor que o jogo possa usar para tokens de acesso no servidor de back-end, chame o método getServerAuthCode() no objeto GoogleSignInAccount que o Google Sign-In retorna quando o jogador faz login.

Veja um exemplo:

// Auth code to send to backend server.
private String mServerAuthCode;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == RC_SIGN_IN) {
    GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
    if (result.isSuccess()) {
      mServerAuthCode = result.getSignInAccount().getServerAuthCode();
    } else {
      String message = result.getStatus().getStatusMessage();
      if (message == null || message.isEmpty()) {
        message = getString(R.string.signin_other_error);
      }
      new AlertDialog.Builder(this).setMessage(message)
          .setNeutralButton(android.R.string.ok, null).show();
    }
  }
}

Trocar o código de autenticação do servidor por um token de acesso no servidor

Envie o código de autenticação do servidor ao servidor de back-end para trocar por tokens de acesso e de atualização. Use o token de acesso para chamar a API Play Games Services em nome do jogador e, como opção, armazene o token de atualização para receber um novo token de acesso quando ele expirar.

O snippet de código a seguir mostra como implementar o código no lado do servidor na linguagem de programação Java para trocar o código de autenticação do servidor por tokens de acesso. Ele está usando o app de exemplo 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;
}

Para saber mais sobre como acessar APIs do Google em um servidor de back-end em nome de um jogador conectado, consulte Como ativar o acesso do lado do servidor.

Processar o logout do jogador

Para fazer os jogadores saírem do jogo, chame o método signOut() no GoogleSignInClient. Para conferir um exemplo de snippet de código, consulte Como fazer o logout do jogador.

Chamar APIs REST do servidor

Consulte APIs REST para serviços relacionados a jogos do Google Play para uma descrição completa das chamadas de API disponíveis.

Veja abaixo alguns exemplos de chamadas de APIs REST que podem ser úteis:

Jogador

  • Quer receber o ID do jogador conectado e os dados do perfil? Chame Players.get com 'me' como o ID.

Amigos

Leia o guia Amigos, que explica esse recurso em mais detalhes.

Conquistas

Leia o guia Conquistas, que explica conquistas em mais detalhes.

  • Deseja obter uma lista das conquistas atuais? Você pode fazer uma chamada para AchievementDefinitions.list.
  • Combine isso com uma chamada para Achievements.list para descobrir quais o jogador desbloqueou.
  • O jogador recebeu uma conquista? Use Achievements.unlock para desbloqueá-la.
  • O jogador fez progresso em direção a uma conquista parcial? Use Achievements.increment para informar o progresso (e para descobrir se o jogador a desbloqueou).
  • Está depurando um jogo que ainda não está em produção? Tente chamar Conquistas.reset ou Conquistas.resetAll nas APIs de gerenciamento para redefinir as conquistas ao estado original.

Placares

Leia o guia Placares de líderes, que explica o recurso em mais detalhes.

  • Quer uma lista de todos os placares no jogo? Faça uma chamada para Leaderboards.list.
  • O jogador acabou de jogar? Você pode enviar a pontuação dele para Scores.submit e descobrir se ela é uma nova pontuação mais alta.
  • Deseja exibir um placar de líderes? Acesse os dados de Scores.list e mostre-os ao usuário.
  • Use Scores.listWindow para descobrir pontuações próximas à pontuação mais alta do usuário.
  • Para saber mais sobre a pontuação do jogador em um placar de líderes específico (por exemplo, se o jogador está entre os 12% dos melhores jogadores), chame Scores.get.
  • Está depurando um jogo? Tente chamar Scores.reset das APIs de gerenciamento para redefinir todas as pontuações desse jogador de um placar de líderes específico.