Dostęp po stronie serwera do usług gier Google Play

Zalecamy używanie GamesSignInClient do uwierzytelniania graczy i bezpiecznego przekazywania ich tożsamości do serwera. Dzięki temu gra może bezpiecznie pobierać dane tożsamości gracza i inne dane bez narażania się na potencjalne manipulowanie podczas przesyłania przez urządzenie.

Gdy gracz się zaloguje, możesz poprosić o specjalny kod jednorazowego użytku (nazywany kodem autoryzacji serwera) z pakietu SDK Usług gier Play w wersji 2, który klient przekazuje serwerowi. Następnie na serwerze wymień kod autoryzacji serwera na token OAuth 2.0, którego serwer może używać do wywoływania interfejsu API usług gier Google Play.

Więcej wskazówek na temat dodawania logowania w grach znajdziesz w artykule Logowanie w grach na Androida.

Aby uzyskać dostęp offline, wykonaj te czynności:

  1. W Konsoli Google Play: utwórz poświadczenia dla serwera gry. Typ klienta OAuth danych uwierzytelniających to „web” (sieć).
  2. W aplikacji na Androida: w ramach logowania poproś o kod uwierzytelniający serwer dla swoich danych logowania na serwer i przekaż go na serwer. Aplikacja GamesSigninClient może prosić o dostęp do interfejsów API usług gier Play po stronie serwera, podając 3 zakresy OAuth 2.0. Opcjonalne zakresy to EMAIL, PROFILE i OPEN_ID. Domyślne zakresy to DRIVE_APPFOLDERGAMES_LITE.
  3. Na serwerze gry: za pomocą usług uwierzytelniania Google zastąp kod autoryzacji serwera tokenem dostępu OAuth, a potem używaj go do wywoływania interfejsów REST API usług gier Play.

Zanim zaczniesz

Najpierw musisz dodać grę w Konsoli Google Play, zgodnie z instrukcjami w artykule Konfigurowanie usług gier Google Play, a potem zintegrować z nią logowanie w usługach gier Google Play.

Tworzenie aplikacji internetowej po stronie serwera

Usługi gier Google Play nie zapewniają obsługi backendu dla gier w przeglądarce. Zapewnia jednak obsługę serwera backendu dla serwera gry na Androida.

Jeśli chcesz używać interfejsów API REST do usług Google Play Games w aplikacji po stronie serwera, wykonaj te czynności:

  1. Konsoli Google Play wybierz grę.
  2. Kliknij Usługi gier Play > Konfiguracja i zarządzanie > Konfiguracja.
  3. Kliknij Dodaj dane logowania, aby otworzyć stronę dodawania danych logowania. Jako typ danych logowania wybierz Serwer gier i przejdź do sekcji Autoryzacja.
    1. Jeśli serwer gier ma już identyfikator klienta OAuth, wybierz go z menu. Po zapisaniu zmian przejdź do następnej sekcji.
    2. Jeśli nie masz identyfikatora klienta OAuth na potrzeby serwera gier, możesz go utworzyć.
      1. Kliknij Utwórz klienta OAuth i postępuj zgodnie z instrukcjami w sekcji Utwórz identyfikator klienta OAuth.
      2. Spowoduje to otwarcie strony Tworzenie identyfikatora klienta OAuth w Google Cloud Platform dla projektu powiązanego z Twoją grą.
      3. Wypełnij formularz strony i kliknij Utwórz. Upewnij się, że jako Typ aplikacji ustawisz Aplikacja internetowa.
      4. Wróć do sekcji Autoryzacja na stronie Dodaj dane logowania, wybierz nowo utworzonego klienta OAuth i zapisz zmiany.

Pobieranie kodu autoryzacji serwera

Aby pobrać kod autoryzacji serwera, którego Twoja gra może używać do tokenów dostępu na serwerze zaplecza:

  1. Zadzwoń pod numer requestServerSideAccess z telefonu klienta.

    1. Upewnij się, że używasz identyfikatora klienta OAuth zarejestrowanego dla serwera gry, a nie identyfikatora klienta OAuth Twojej aplikacji na Androida.
    2. (Opcjonalnie) Jeśli serwer gry wymaga dostępu offline (długotrwałego dostępu za pomocą tokena odświeżania) do Usług w Grach Play, możesz ustawić parametr forceRefreshToken na wartość true.
    3. (Opcjonalnie) Podczas logowania nowi użytkownicy powinni zobaczyć jeden ekran zgody na dodatkowe zakresy. Po wyrażeniu zgody ustawiasz parametr scopes z zakresami OAuth EMAIL, PROFILEOPEN_ID. Jeśli użytkownicy odmówią wyrażenia zgody, na serwer zostaną wysłane tylko 2 domyślne zakresy DRIVE_APPFOLDERGAMES_LITE.

      Ekran zgody dla dodatkowych zakresów uprawnień OAuth.
      Ekran zgody dla dodatkowych zakresów uprawnień OAuth. (kliknij, aby powiększyć).

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

  2. Wysyłanie tokena kodu autoryzacji OAuth do serwera backendu, aby można go było wymienić, sprawdzanie identyfikatora gracza w interfejsach REST usług gier Play, a następnie uwierzytelnianie go w grze.

Wysyłanie kodu uwierzytelniania serwera

Wyślij kod autoryzacji serwera do serwera backendu, aby wymienić go na tokeny dostępu i odświeżania. Użyj tokena dostępu, aby wywołać interfejs Play Games Services API w imieniu gracza, i opcjonalnie zapisz token odświeżania, aby po upływie ważności tokena dostępu pobrać nowy token dostępu.

Ten fragment kodu pokazuje, jak zastosować kod po stronie serwera w języku programowania Java, aby zamienić kod uwierzytelniający serwer na tokeny dostępu.

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

Zakresy OAuth możesz pobrać za pomocą bibliotek klienta interfejsu API Google w języku Java lub Python, aby uzyskać obiekt GoogleIdTokenVerifier. Poniższy fragment kodu pokazuje implementację w języku programowania Java.

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

Wywoływanie interfejsów API REST z serwera

Pełny opis dostępnych wywołań interfejsu API znajdziesz w artykule Interfejsy REST API usług gier Google Play.

Przykłady wywołań interfejsu API REST, które mogą Ci się przydać:

Zawodnik

Chcesz poznać identyfikator i dane profilu zalogowanego gracza? Zadzwoń do Players.get z identyfikatorem 'me'.

Znajomi

Szczegółowe informacje znajdziesz w przewodniku Friends (znajomi).

  • Aby pobrać listę znajomych gracza, wywołaj funkcję Players.list z wartością friends_all jako collection.

  • Aby sprawdzić, czy masz dostęp do listy znajomych, wywołaj funkcję Players.get z wartością me w parametry playerID i sprawdź pole profileSettings.friendsListVisibility w odpowiedzi.

Osiągnięcia

Szczegółowe informacje znajdziesz w przewodniku Osiągnięcia.

  • Aby uzyskać listę bieżących osiągnięć, wywołaj funkcję AchievementDefinitions.list.

  • Połącz to z wywołaniem Achievements.list, aby dowiedzieć się, które z nich gracz odblokował.

  • Wywołaj metodę Achievements.unlock, aby odblokować osiągnięcie gracza.

  • Aby zgłosić postępy w uzyskiwaniu osiągnięcia i sprawdzić, czy gracz je odblokował, wywołaj funkcję Achievements.increment.

  • Jeśli debugujesz grę, która nie została jeszcze wdrożona, możesz wywołać metodę Achievements.reset lub Achievements.resetAll z interfejsów Management API, aby zresetować osiągnięcia do ich pierwotnego stanu.

Tabele wyników

Szczegółowe informacje znajdziesz w przewodniku po tabelach liderów.

  • Chcesz zobaczyć listę wszystkich tablic wyników w grze? Wykonaj wywołanie Leaderboards.list.

  • Jeśli gracz skończył grę, możesz przesłać jego wynik za pomocą wywołania Scores.submit i sprawdzić, czy jest to nowy rekord.

  • Aby wyświetlić tablicę wyników, pobierz dane z Scores.list i pokaż je użytkownikowi.

  • Użyj funkcji Scores.listWindow, aby znaleźć asortyment wyników zbliżonych do najwyższego wyniku użytkownika.

  • Aby uzyskać więcej informacji o wyniku gracza w konkretnej tabeli wyników (np. czy należy do 12% najlepszych graczy), wywołaj Scores.get.

  • Podczas debugowania gry możesz wywołać metodę Scores.reset z interfejsów Management API, aby zresetować wszystkie wyniki danego gracza w konkretnej tabeli wyników.