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 Backend-Server zu übergeben. So kann Ihr Spiel die Identität des Spielers und andere Daten sicher abrufen, ohne dass sie beim Durchlaufen des Geräts manipuliert werden können.

Sobald sich der Spieler erfolgreich authentifiziert hat, können Sie über das Play-Spieldienste v2 SDK einen speziellen Einmalcode (Serverautorisierungscode) anfordern, den der Client an den Server übergibt. Auf dem Server tauschen Sie den Serverautorisierungscode dann gegen ein OAuth 2.0-Token ein, mit dem der Server Aufrufe an die Google Play-Spieldienste-API ausführen kann.

Weitere Informationen zum Hinzufügen der Authentifizierung in Ihren Spielen finden Sie unter Plattformauthentifizierung für Android-Spiele.

Die folgenden Schritte sind für den Offlinezugriff erforderlich:

  1. Erstellen Sie in der Google Play Console Anmeldedaten für Ihren Spielserver. Der OAuth-Clienttyp der Anmeldedaten ist „Web“.
  2. In der Android-App: Fordern Sie im Rahmen der Plattformauthentifizierung einen Serverautorisierungscode für die Anmeldedaten Ihres Servers an und übergeben Sie ihn an Ihren Server. Die GamesSigninClient kann beim Anfordern des serverseitigen Zugriffs auf Play Games-Dienste-Web-APIs drei OAuth 2.0-Bereiche anfordern. Die optionalen Bereiche sind EMAIL, PROFILE und OPEN_ID. Die beiden Standardbereiche sind DRIVE_APPFOLDER und GAMES_LITE.
  3. Auf Ihrem Spielserver: Tauschen Sie den Serverautorisierungscode mit den Google-Authentifizierungsdiensten gegen ein OAuth-Zugriffstoken ein und rufen Sie damit die REST APIs der Play-Spieldienste auf.

Hinweis

Sie müssen Ihr Spiel zuerst in der Google Play Console hinzufügen, wie unter Google Play Games-Dienste einrichten beschrieben, und die Authentifizierung der Play Games-Dienste-Plattform in Ihr Spiel einbinden.

Serverseitige Webanwendung erstellen

Die Google Play-Spieldienste bieten keine Backend-Unterstützung für Webspiele. Es bietet jedoch Back-End-Serverunterstützung für den Server Ihres Android-Spiels.

Wenn Sie die REST APIs for Google Play Games services in Ihrer serverseitigen App verwenden möchten, gehen Sie so vor:

  1. Wählen Sie in der Google Play Console ein Spiel aus.
  2. Rufen Sie Play Games-Dienste > Einrichtung und Verwaltung > Konfiguration auf.
  3. Wählen Sie Anmeldedaten hinzufügen aus, um die Seite Anmeldedaten hinzufügen aufzurufen. Wählen Sie Game Server als Anmeldedatentyp aus und fahren Sie mit dem Bereich Autorisierung fort.
    1. Wenn Ihr Game-Server bereits eine OAuth-Client-ID hat, wählen Sie sie im Drop-down-Menü aus. Nachdem Sie Ihre Änderungen gespeichert haben, fahren Sie mit dem nächsten Abschnitt fort.
    2. Wenn Sie noch keine OAuth-Client-ID für Ihren Spieleserver haben, können Sie eine erstellen.
      1. Klicken Sie auf OAuth-Client erstellen und folgen Sie dem Link OAuth-Client-ID erstellen.
      2. Dadurch gelangen Sie zur Seite OAuth-Client-ID erstellen in der Google Cloud Platform für Ihr Projekt, das mit Ihrem Spiel verknüpft ist.
      3. Füllen Sie das Formular auf der Seite aus und klicken Sie auf „Erstellen“. Achten Sie darauf, dass der Anwendungstyp auf „Webanwendung“ festgelegt ist.
      4. Kehren Sie zum Abschnitt Autorisierung auf der Seite Anmeldedaten hinzufügen zurück, wählen Sie den neu erstellten OAuth-Client aus und speichern Sie die Änderungen.

Server-Authentifizierungscode abrufen

So rufen Sie einen Serverautorisierungscode ab, den Ihr Spiel für Zugriffstokens auf Ihrem Backend-Server verwenden kann:

  1. Rufen Sie requestServerSideAccess über den Client auf.
    1. Verwende die für deinen Gameserver registrierte OAuth-Client-ID und nicht die OAuth-Client-ID deiner Android-App.
    2. (Optional) Wenn Ihr Gameserver Offlinezugriff (langfristiger Zugriff mit einem Aktualisierungstoken) auf Play Games-Dienste benötigt, können Sie den Parameter forceRefreshToken auf „true“ setzen.
  2. Optional: Im Rahmen der Authentifizierung sollten neue Nutzer einen einzelnen Zustimmungsbildschirm für zusätzliche Bereiche sehen. Wenn Sie die Einwilligung akzeptieren, legen Sie den Parameter scopes mit den OAuth-Bereichen EMAIL, PROFILE und OPEN_ID fest. Wenn Nutzer die Einwilligung ablehnen, werden nur die beiden Standardbereiche DRIVE_APPFOLDER und GAMES_LITE an das Backend 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. Senden Sie das OAuth-Autorisierungscode-Token an Ihren Backend-Server, damit es ausgetauscht, die Spieler-ID anhand der Play Games-Dienste-REST-APIs überprüft und dann für Ihr Spiel authentifiziert werden kann.

Server-Authentifizierungscode senden

Senden Sie den Serverautorisierungscode an Ihren Backend-Server, um ihn gegen Zugriffs- und Aktualisierungstokens einzutauschen. Verwenden Sie das Zugriffstoken, um die Play-Spieldienste-API im Namen des Spielers aufzurufen, und speichern Sie optional das Aktualisierungstoken, um ein neues Zugriffstoken zu erhalten, wenn das Zugriffstoken abläuft.

Weitere Informationen zur Funktionsweise von Spieler-IDs finden Sie unter Spieler-IDs der nächsten Generation.

Im folgenden Code-Snippet sehen Sie, wie Sie den serverseitigen Code in der Programmiersprache Java implementieren können, 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;
}

Sie können 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 aus aufrufen

Eine vollständige Beschreibung der verfügbaren API-Aufrufe finden Sie unter REST APIs for Google Play Games services.

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

Spieler

Möchten Sie die ID und die Profildaten des authentifizierten Spielers abrufen? Rufen Sie Players.get mit 'me' als ID auf.

Freunde

Weitere Informationen

  • Rufen Sie Players.list mit friends_all als collection auf, um die Freundesliste des Spielers abzurufen.

  • Wenn Sie prüfen möchten, ob Sie Zugriff auf eine Freundesliste haben, rufen Sie Players.get mit me als playerID auf und sehen Sie sich das Feld profileSettings.friendsListVisibility in der Antwort an.

Erfolge

Weitere Informationen

  • Rufen Sie AchievementDefinitions.list auf, um eine Liste der aktuellen Erfolge zu erhalten.

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

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

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

  • Wenn Sie ein Spiel debuggen, das noch nicht in der Produktion ist, können Sie die Methoden Achievements.reset oder Achievements.resetAll aus den Management APIs aufrufen, um Erfolge auf ihren ursprünglichen Zustand zurückzusetzen.

Bestenlisten

Weitere Informationen

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

  • Wenn ein Spieler ein Spiel beendet hat, können Sie seinen Punktestand mit Scores.submit einreichen und herausfinden, ob es sich um einen neuen Highscore handelt.

  • Wenn Sie eine Bestenliste anzeigen möchten, rufen Sie die Daten mit Scores.list ab und präsentieren Sie sie dem Nutzer.

  • Mit Scores.listWindow können Sie eine Auswahl von Punktzahlen in der Nähe des Highscores des Nutzers abrufen.

  • Wenn Sie weitere Informationen zum Score des Spielers in einer bestimmten Bestenliste erhalten möchten, z. B. ob der Spieler zu den besten 12% aller Spieler gehört, rufen Sie Scores.get auf.

  • Wenn Sie ein Spiel debuggen, können Sie Scores.reset über die Management APIs aufrufen, um alle Punktzahlen für diesen Spieler aus einer bestimmten Bestenliste zurückzusetzen.