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

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

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

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

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

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

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

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

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

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

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

  1. В игре в консоли Google Play выберите Play Games Services > Настройка и управление > Конфигурация .
  2. Выберите «Добавить учетные данные» , чтобы перейти на страницу «Добавить учетные данные» . Выберите Игровой сервер в качестве типа учетных данных и перейдите в раздел «Авторизация» .
    1. Если на вашем игровом сервере уже есть идентификатор клиента OAuth, выберите его в раскрывающемся меню. После сохранения изменений перейдите к следующему разделу .
    2. Если у вас нет существующего идентификатора клиента OAuth для вашего игрового сервера, вы можете создать его.
      1. Нажмите «Создать клиент OAuth» и перейдите по ссылке «Создать идентификатор клиента OAuth» .
      2. Вы перейдете на страницу создания идентификатора клиента OAuth Google Cloud Platform для проекта Cloud Platform, связанного с вашей игрой.
      3. Заполните форму страницы и нажмите «Создать». Обязательно установите тип приложения «Веб-приложение».
      4. Вернитесь в раздел «Авторизация» на странице «Добавить учетные данные» , выберите вновь созданный клиент OAuth и сохраните изменения.

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

Чтобы получить код авторизации сервера, который ваша игра может использовать для токенов доступа на вашем внутреннем сервере:

  1. Вызовите requestServerSideAccess от клиента.

    1. Убедитесь, что вы используете идентификатор клиента OAuth, зарегистрированный для вашего игрового сервера , а не идентификатор клиента OAuth вашего приложения Android.
    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 на свой внутренний сервер, чтобы его можно было обменять, идентификатор игрока сверился с API-интерфейсами REST игровых сервисов Play Games, а затем прошел аутентификацию в вашей игре.

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

Отправьте код аутентификации сервера на внутренний сервер для обмена на токены доступа и обновления. Используйте токен доступа для вызова 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;
}

Вызов 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 управления, чтобы сбросить все очки этого игрока из определенной таблицы лидеров.