Включение серверного доступа к игровым сервисам Google Play

Если в вашей игре используется внутренний сервер, мы рекомендуем вам использовать вход в Google для аутентификации игроков и безопасной передачи личности игрока на внутренний сервер. Это также позволяет вашей игре безопасно получать личность игрока и другие данные, не подвергаясь потенциальному вмешательству при прохождении через устройство.

В этом случае игра предлагает игроку войти в игровые сервисы Google Play, как обычно. Когда игрок успешно входит в систему, объект GoogleSignInAccount содержит специальный одноразовый код (называемый кодом аутентификации сервера ), который клиент передает серверу. Затем на сервере замените код аутентификации сервера на токен OAuth 2.0, который сервер сможет использовать для вызовов API игровых сервисов Google Play.

Дополнительные инструкции по добавлению функции входа в игры см. в разделе Вход в игры для Android .

Подробный пример кода, показывающий, как использовать вход в Google для аутентификации игроков, см. в примере clientserverskeleton на GitHub.

Для автономного доступа необходимо выполнить следующие действия:

  1. В консоли Google Play: создайте учетные данные для своего игрового сервера. Тип учетных данных клиента OAuth будет «веб».
  2. В приложении Android: при входе в систему запросите код аутентификации сервера для учетных данных вашего сервера и передайте его на свой сервер.
  3. На игровом сервере: замените код аутентификации сервера на токен доступа OAuth с помощью служб аутентификации Google, а затем используйте его для вызова REST API игровых сервисов Play.

Прежде чем начать

Прежде чем вы сможете интегрировать вход в Google в свою игру, вам сначала необходимо добавить свою игру в консоль Google Play , как описано в разделе «Настройка игровых сервисов Google Play» .

Создайте связанное серверное веб-приложение для вашей игры.

Игровые сервисы Google Play не обеспечивают серверную поддержку веб-игр. Тем не менее, он обеспечивает поддержку внутреннего сервера для сервера вашей игры для Android.

Если вы хотите использовать REST API для сервисов Google Play Games в своем серверном приложении, выполните следующие действия:

  1. Создайте связанное веб-приложение для своей игры в разделе «Связанные приложения» консоли Google Play . Обратите внимание, что launch_url не используется для этого потока и его можно оставить пустым.
  2. Чтобы получить учетные данные для вашего приложения, выполните следующие действия:
    1. В игре в консоли Google Play нажмите «Сведения об игре» .
    2. Прокрутите вниз до раздела «Проект консоли API» и нажмите ссылку на проект консоли API.
    3. На экране «API и службы» > «Учетные данные» в консоли Google API загрузите файл client_secret.json для своего веб-приложения и сохраните его в месте, к которому будет иметь доступ ваш сервер. Запишите идентификатор клиента учетных данных для дальнейшего использования.
  3. Перезапустите серверное приложение, чтобы оно было готово принимать запросы от клиентского приложения вашей игры.

Выполнение входа в клиент

Класс GoogleSignInClient — это основная точка входа для получения учетной записи игрока, выполнившего вход в систему, а также для входа в систему игрока, если он ранее не сделал этого в вашем приложении на устройстве.

Чтобы создать клиент для входа, выполните следующие действия:

  1. Создайте клиент входа в систему с помощью объекта GoogleSignInOptions . В GoogleSignInOptions.Builder для настройки входа необходимо указать GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN .
  2. Вы также должны указать, что вашей игре требуется код авторизации для вашего внутреннего сервера, вызвав метод GoogleSignInOptions.Builder.requestServerAuthCode() с идентификатором клиента сервера в качестве параметра. Позже вы получите код аутентификации для токенов доступа на внутреннем сервере, как описано в разделе «Получение кода аутентификации сервера» .
  3. Вызовите метод GoogleSignIn.getClient() и передайте ранее настроенные параметры. Если вызов успешен, Google Sign-In API возвращает экземпляр GoogleSignInClient .
  4. После получения экземпляра GoogleSignInClient вам следует приступить к автоматическому входу игрока в систему из onResume() действия, как описано в разделе «Выполнение автоматического входа» .

Вот пример:

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

Получите код авторизации сервера

Чтобы получить код авторизации сервера, который ваша игра может использовать для токенов доступа на внутреннем сервере, вызовите метод getServerAuthCode() объекта GoogleSignInAccount , который Google Sign-In возвращает при успешном входе игрока в систему.

Вот пример:


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

Обменяйте код аутентификации сервера на токен доступа на сервере.

Отправьте код аутентификации сервера на внутренний сервер для обмена на токены доступа и обновления. Используйте токен доступа для вызова API игровых сервисов Google Play от имени игрока и, при необходимости, сохраните токен обновления, чтобы получить новый токен доступа по истечении срока действия токена доступа.

В следующем фрагменте кода показано, как можно реализовать серверный код на языке программирования 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;
}

Дополнительные сведения о доступе к API Google с внутреннего сервера от имени вошедшего в систему игрока см. в разделе Включение доступа на стороне сервера .

Обработка выхода игрока

Чтобы вывести игроков из вашей игры, вызовите метод signOut() в GoogleSignInClient . Пример фрагмента кода см. в разделе Выход игрока .

Вызов REST API с сервера

Полное описание доступных вызовов API см. в разделе REST API для сервисов Google Play Games .

Примеры вызовов REST API, которые могут оказаться полезными, включают следующее:

Игрок

  • Хотите получить идентификатор вошедшего в систему игрока и данные профиля? Вызовите Players.get, указав 'me' в качестве идентификатора.

Друзья

Обязательно просмотрите руководство «Друзья» , в котором более подробно описаны друзья.

  • Хотите получить список друзей игрока? Вызовите Players.list, указав в качестве collection 'friends_all' .
  • Проверьте, есть ли у вас доступ к списку друзей? Вызовите Players.get от me и посмотрите на поле profileSettings.friendsListVisibility в ответе.

Достижения

Обязательно ознакомьтесь с руководством по достижениям , в котором достижения описаны более подробно.

  • Хотите получить список текущих достижений? Вы можете позвонить в AchievementDefinitions.list .
  • Объедините это с вызовом Achievements.list, чтобы узнать, какие из них разблокировал игрок.
  • Получил ли игрок достижение? Используйте Achievements.unlock , чтобы разблокировать его!
  • Добился ли игрок прогресса в достижении частичного достижения? Используйте Achievements.increment, чтобы сообщить о прогрессе (и узнать, разблокировал ли игрок его).
  • Вы отлаживаете игру, которая еще не находится в производстве? Попробуйте вызвать Achievements.reset или Achievements.resetAll из API управления, чтобы сбросить достижения в исходное состояние.

Таблицы лидеров

Обязательно ознакомьтесь с руководством по таблицам лидеров , в котором таблицы лидеров описаны более подробно.

  • Хотите получить список всех табло в игре? Позвоните в Leaderboards.list .
  • Игрок закончил игру? Вы можете отправить их результат на Scores.submit и узнать, является ли это новым рекордом.
  • Хотите отобразить таблицу лидеров? Получите данные из Scores.list и покажите их пользователю.
  • Используйте Scores.listWindow , чтобы найти набор оценок, близких к наивысшему баллу пользователя.
  • Чтобы получить дополнительную информацию о счете игрока в определенной таблице лидеров (например, если игрок входит в число 12% лучших игроков), вызовите Scores.get .
  • Вы отлаживаете игру? Попробуйте вызвать Scores.reset из API управления, чтобы сбросить все очки этого игрока из определенной таблицы лидеров.