Мы рекомендуем вам использовать GamesSignInClient для аутентификации игроков и безопасной передачи личности игрока на внутренний сервер. Это позволяет вашей игре безопасно извлекать личность игрока и другие данные, не подвергаясь потенциальному вмешательству при прохождении через устройство.
После успешного входа игрока вы можете запросить специальный одноразовый код (называемый кодом аутентификации сервера ) из Play Games Services v2 SDK, который клиент передает серверу. Затем на сервере обменяйте код аутентификации сервера на токен OAuth 2.0, который сервер может использовать для вызовов API Google Play Games Services.
Дополнительные рекомендации по добавлению входа в игры см. в разделе Вход в игры для Android .
Для офлайн-доступа необходимо выполнить следующие шаги:
- В Google Play Console: создайте учетные данные для вашего игрового сервера. Тип клиента OAuth учетных данных будет "web".
- В приложении Android: как часть входа, запросите код аутентификации сервера для учетных данных вашего сервера и передайте его на свой сервер.
GamesSigninClient
может запросить три области OAuth 2.0 при запросе доступа на стороне сервера к веб-API Play Games Services. Необязательные области —EMAIL
,PROFILE
иOPEN_ID
. Две области по умолчанию —DRIVE_APPFOLDER
иGAMES_LITE
. - На вашем игровом сервере: обменяйте код аутентификации сервера на токен доступа OAuth с помощью служб аутентификации Google, а затем используйте его для вызова API REST игровых сервисов Play.
Прежде чем начать
Сначала вам необходимо добавить свою игру в Google Play Console , как описано в разделе Настройка игровых сервисов Google Play , и интегрировать вход в игровые сервисы Play с вашей игрой.
Создать серверное веб-приложение
Google Play Game services не предоставляет поддержку бэкенда для веб-игр. Однако он предоставляет поддержку бэкенда для сервера вашей игры Android.
Если вы хотите использовать REST API для сервисов Google Play Games в своем серверном приложении, выполните следующие действия:
- В Google Play Console выберите игру.
- Перейдите в раздел «Игровые сервисы Play» > «Настройка и управление» > «Конфигурация» .
- Выберите Добавить учетные данные , чтобы перейти на страницу Добавить учетные данные . Выберите Игровой сервер в качестве типа учетных данных и перейдите в раздел Авторизация .
- Если на вашем игровом сервере уже есть идентификатор клиента OAuth, выберите его из выпадающего меню. После сохранения изменений перейдите к следующему разделу .
- Если у вас нет существующего идентификатора клиента OAuth для вашего игрового сервера, вы можете создать его.
- Нажмите «Создать клиент OAuth» и перейдите по ссылке «Создать идентификатор клиента OAuth» .
- Это приведет вас на страницу создания идентификатора клиента OAuth на платформе Google Cloud Platform для вашего проекта, связанного с вашей игрой.
- Заполните форму страницы и нажмите «Создать». Обязательно установите Тип приложения на Веб-приложение.
- Вернитесь в раздел «Авторизация» на странице «Добавить учетные данные» , выберите только что созданный клиент OAuth и сохраните изменения.
Получить код аутентификации сервера
Чтобы получить код аутентификации сервера, который ваша игра может использовать для токенов доступа на вашем внутреннем сервере:
Вызовите
requestServerSideAccess
с клиента.- Убедитесь, что вы используете идентификатор клиента OAuth, зарегистрированный для вашего игрового сервера , а не идентификатор клиента OAuth вашего приложения Android.
- (Необязательно) Если вашему игровому серверу требуется автономный доступ (долгосрочный доступ с использованием токена обновления) к игровым сервисам Play, вы можете установить для параметра
forceRefreshToken
значение true. (Необязательно) В рамках входа новые пользователи должны увидеть единый экран согласия для дополнительных областей. Приняв согласие, вы устанавливаете параметр
scopes
с областями OAuthEMAIL
,PROFILE
иOPEN_ID
. Если пользователи отклоняют согласие, на бэкэнд отправляются только две области по умолчаниюDRIVE_APPFOLDER
иGAMES_LITE
.Экран согласия для дополнительных областей OAuth. (нажмите, чтобы увеличить). GamesSignInClient gamesSignInClient = PlayGames.getGamesSignInClient(this); gamesSignInClient.requestServerSideAccess(OAUTH_2_WEB_CLIENT_ID, /* forceRefreshToken= / false, / Additional AuthScope */ scopes) .addOnCompleteListener( task -> { if (task.isSuccessful()) { AuthResponse authresp = task.getResult(); // Send the authorization code as a string and a // list of the granted AuthScopes that were granted by the // user. Exchange for an access token. // Verify the player with Play Games Services REST APIs. } else { // Failed to retrieve authentication code. } });
Отправьте токен кода аутентификации OAuth на ваш внутренний сервер, чтобы его можно было обменять, проверить идентификатор игрока с помощью API REST игровых сервисов Play, а затем выполнить аутентификацию в вашей игре.
Отправьте серверу код аутентификации
Отправьте код аутентификации сервера на ваш внутренний сервер для обмена на токены доступа и обновления. Используйте токен доступа для вызова API Play Games Services от имени игрока и, по желанию, сохраните токен обновления для получения нового токена доступа, когда истекает срок действия токена доступа.
В следующем фрагменте кода показано, как можно реализовать серверный код на языке программирования Java для обмена кода аутентификации сервера на токены доступа.
Ява
/** * Exchanges the authcode for an access token credential. The credential * is 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(); TokenVerifier(tokenResponse); 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; }
Вы можете получить области OAuth, используя клиентские библиотеки Google API в Java или Python, чтобы получить объект GoogleIdTokenVerifier
. Следующий фрагмент кода показывает реализацию на языке программирования Java.
Ява
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; /** * Gets the GoogleIdTokenVerifier object and additional OAuth scopes. * If additional OAuth scopes are not requested, the idToken will be null. * * @param tokenResponse - the tokenResponse passed from the exchangeAuthCode * function. * **/ void TokenVerifier(GoogleTokenResponse tokenResponse) { string idTokenString = tokenResponse.getIdToken(); GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) // Specify the WEB_CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(WEB_CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3)) .build(); GoogleIdToken idToken = verifier.verify(idTokenString); // The idToken can be null if additional OAuth scopes are not requested. if (idToken != null) { Payload payload = idToken.getPayload(); // Print user identifier String userId = payload.getSubject(); System.out.println("User ID: " + userId); // Get profile information from payload String email = payload.getEmail(); boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); String name = (String) payload.get("name"); String pictureUrl = (String) payload.get("picture"); String locale = (String) payload.get("locale"); String familyName = (String) payload.get("family_name"); String givenName = (String) payload.get("given_name"); // Use or store profile information // ... } else { System.out.println("Invalid ID token."); } }
Вызов REST API с сервера
Полное описание доступных вызовов API см. в разделе API REST для сервисов Google Play Games .
Примеры вызовов REST API, которые могут оказаться вам полезными, включают следующее:
Игрок
Хотите получить ID и данные профиля вошедшего в систему игрока? Вызовите Players.get , указав 'me'
в качестве ID.
Друзья
Подробности смотрите в руководстве « Друзья» .
Чтобы получить список друзей игрока, вызовите Players.list с
friends_all
в качествеcollection
.Чтобы проверить, есть ли у вас доступ к списку друзей, вызовите Players.get с
me
playerID
и просмотрите поле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 управления, чтобы сбросить все очки этого игрока из определенной таблицы лидеров.