Serverseitiger Zugriff auf die Google Play-Spieldienste

Wir empfehlen, GamesSignInClient zu verwenden, um Spieler zu authentifizieren und die Identität des Spielers sicher an den Back-End- Server zu übergeben. So kann dein Spiel die Identität und andere Daten des Spielers sicher abrufen, ohne dass sie beim Durchlaufen des Geräts manipuliert werden können.

Sobald der Spieler authentifiziert wurde, kannst du im Play-Spieldienste SDK v2 einen speziellen Einmalcode (den Serverautorisierungscode) anfordern, den der Client an den Server übergibt. Tausche dann auf dem Server den Serverautorisierungscode gegen ein OAuth 2.0-Token ein, mit dem der Server Aufrufe an die Google Play Games-Dienste API senden kann.

Weitere Informationen zum Hinzufügen der Authentifizierung in deinen Spielen findest du unter Plattformauthentifizierung für Android-Spiele.

Für den Offlinezugriff sind die folgenden Schritte erforderlich:

  1. Google Play Console: Erstelle Anmeldedaten für deinen Game Server. Der OAuth-Clienttyp der Anmeldedaten ist „Web“.
  2. Android-App: Fordere im Rahmen der Plattformauthentifizierung einen Serverautorisierungscode für die Anmeldedaten deines Servers an und übergib ihn an deinen Server. Der GamesSigninClient kann drei OAuth 2.0-Bereiche anfordern, wenn er serverseitigen Zugriff auf die Web-APIs der Play Games-Dienste anfordert. Die optionalen Bereiche sind EMAIL, PROFILE und OPEN_ID. Die beiden Standardbereiche sind DRIVE_APPFOLDER und GAMES_LITE.
  3. Game Server: Tausche den Serverautorisierungscode mit den Google-Authentifizierungsdiensten gegen ein OAuth-Zugriffstoken ein und rufe damit die Play-Spieldienste REST APIs auf.

Hinweis

Zuerst musst du dein Spiel in der Google Play Console hinzufügen, wie unter Google Play Games-Dienste einrichten beschrieben, und die Plattformauthentifizierung der Play Games-Dienste in dein Spiel einbinden.

Serverseitige Web-App erstellen

Die Google Play-Spieldienste bieten keine Back-End-Unterstützung für Webspiele. Sie bieten jedoch Back-End-Serverunterstützung für den Server deines Android-Spiels.

Wenn du die REST APIs für die Google Play-Spieldienste in deiner serverseitigen App verwenden möchtest, gehe so vor:

  1. Wähle in der Google Play Console ein Spiel aus.
  2. Rufe Play Games-Dienste > Einrichtung und Verwaltung > Konfiguration auf.
  3. Wähle Anmeldedaten hinzufügen aus, um zur Seite Anmeldedaten hinzufügen zu gelangen. Wähle Game Server als Anmeldedatentyp aus und fahre mit dem Abschnitt Autorisierung fort.
    1. Wenn dein Game Server bereits eine OAuth-Client-ID hat, wähle sie im Drop-down-Menü aus. Speichere die Änderungen und fahre mit dem nächsten Abschnitt fort.
    2. Wenn du keine OAuth-Client-ID für deinen Game Server hast, kannst du eine erstellen.
      1. Klicke auf OAuth-Client erstellen und folge dem Link OAuth-Client-ID erstellen.
      2. Du wirst zur Seite OAuth-Client-ID erstellen der Google Cloud Platform für dein Projekt weitergeleitet, das mit deinem Spiel verknüpft ist.
      3. Fülle das Formular auf der Seite aus und klicke auf „Erstellen“. Setze den Anwendungstyp auf „Webanwendung“.
      4. Kehre zum Abschnitt Autorisierung der Seite Anmeldedaten hinzufügen zurück, wähle den neu erstellten OAuth-Client aus und speichere die Änderungen.

Serverautorisierungscode abrufen

So rufst du einen Serverautorisierungscode ab, den dein Spiel für Zugriffstokens auf deinem Back-End-Server verwenden kann:

  1. Rufe requestServerSideAccess vom Client auf.
    1. Verwende die OAuth-Client-ID, die für deinen Gameserver registriert ist , und nicht die OAuth-Client-ID deiner Android-App.
    2. Optional: Wenn dein Gameserver Offlinezugriff (langfristiger Zugriff mit einem Aktualisierungstoken) auf die Play Games-Dienste benötigt, kannst du den Parameter forceRefreshToken auf „true“ setzen.
  2. Optional: Im Rahmen der Authentifizierung sollten neue Nutzer einen einzigen Zustimmungsbildschirm für zusätzliche Bereiche sehen. Wenn du die Einwilligung erteilst, setze den scopes Parameter mit EMAIL, PROFILE und OPEN_ID OAuth-Bereichen. Wenn Nutzer die Einwilligung ablehnen, werden nur die beiden Standardbereiche DRIVE_APPFOLDER und GAMES_LITE an das Back-End gesendet.

    Zustimmungsbildschirm für zusätzliche OAuth-Bereiche.
    Zustimmungsbildschirm für zusätzliche OAuth-Bereiche. Zum Vergrößern klicken.

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

  3. Sende das OAuth-Autorisierungscode-Token an deinen Backend-Server, damit es ausgetauscht werden kann, die Spieler-ID anhand der REST APIs der Play Games-Dienste überprüft und dann mit deinem Spiel authentifiziert werden kann.

Serverautorisierungscode senden

Sende den Serverautorisierungscode an deinen Back-End-Server, um ihn gegen Zugriffs- und Aktualisierungstokens einzutauschen. Verwende das Zugriffstoken, um die Play Games-Dienste API im Namen des Spielers aufzurufen, und speichere optional das Aktualisierungstoken, um ein neues Zugriffstoken zu erhalten, wenn das Zugriffstoken abläuft.

Weitere Informationen zu Spieler-IDs findest du unter Spieler-IDs der nächsten Generation.

Das folgende Code-Snippet zeigt, wie du den serverseitigen Code in der Programmiersprache Java implementieren kannst, um den Serverautorisierungscode gegen Zugriffstokens einzutauschen.

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

Du kannst die OAuth-Bereiche mit den Google API-Clientbibliotheken in Java oder Python abrufen, um das GoogleIdTokenVerifier Objekt zu erhalten. Das folgende Code-Snippet zeigt die Implementierung in der Programmiersprache 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");

    // This ID is unique to each Google Account, making it suitable for use as
    // a primary key during account lookup. Email is not a good choice because
    // it can be changed by the user.
    String sub = payload.getSubject();

    // Use or store profile information
    // ...

    } else {
      System.out.println("Invalid ID token.");
    }
}

REST APIs vom Server aufrufen

Eine vollständige Beschreibung der verfügbaren API-Aufrufe findest du unter REST APIs für die Google Play-Spieldienste.

Beispiele für REST API-Aufrufe, die nützlich sein können:

Spieler

Möchtest du die ID und die Profildaten des authentifizierten Spielers abrufen? Rufe Players.get mit 'me' als ID auf.

Freunde

Weitere Informationen finden Sie im Friends-Leitfaden.

Erfolge

Weitere Informationen finden Sie im Leitfaden Erfolge.

  • Rufe AchievementDefinitions.list auf, um eine Liste der aktuellen Erfolge abzurufen.

  • Kombiniere das mit einem Aufruf von Achievements.list , um herauszufinden, welche Erfolge der Spieler freigeschaltet hat.

  • Rufe Achievements.unlock auf, um einen Erfolg für einen Spieler freizuschalten.

  • Rufe Achievements.increment auf, um den Fortschritt bei einem Erfolg zu melden und herauszufinden, ob der Spieler ihn freigeschaltet hat.

  • Wenn du ein Spiel debuggst, das noch nicht in der Produktion ist, kannst du mit den Management APIs Achievements.reset oder Achievements.resetAll aufrufen, um Erfolge auf ihren ursprünglichen Zustand zurückzusetzen.

Bestenlisten

Weitere Informationen finden Sie im Leitfaden zu den Bestenlisten.

  • Rufe Leaderboards.list auf, um eine Liste aller Bestenlisten im Spiel abzurufen.

  • Wenn ein Spieler ein Spiel beendet hat, kannst du seine Punktzahl mit Scores.submit senden und herausfinden, ob es ein neuer Highscore ist.

  • Rufe die Daten mit Scores.list ab und zeige sie dem Nutzer an, um eine Bestenliste anzuzeigen.

  • Verwende Scores.listWindow um eine Auswahl von Punktzahlen in der Nähe des Highscores des Nutzers zu finden.

  • Rufe Scores.get auf, um weitere Informationen zur Punktzahl des Spielers in einer bestimmten Bestenliste (z. B. ob der Spieler zu den besten 12% aller Spieler gehört) zu erhalten.

  • Wenn du ein Spiel debuggst, kannst du mit den Management APIs Scores.reset aufrufen, um alle Punktzahlen für diesen Spieler aus einer bestimmten Bestenliste zurückzusetzen.