Google Play Games サービスへのサーバーサイド アクセスを有効にする

プレーヤーを認証し、プレーヤーの ID をバックエンド サーバーに安全に渡すことをおすすめします。そうすることでゲームは、プレーヤーの ID やその他のデータを安全に取得できます。デバイスを通過する間に改ざんの危険にさらされることはありません。

このシナリオでは 1 回限り使用可能な特別なコードをリクエストしたり、 (サーバー認証コードといいます)を Play Games サービス v2 SDK から取得し、クライアントがサーバーに渡します。次に、サーバー上で サーバーが OAuth 2.0 トークンのサーバー認証コードを使用して、このトークンを使用して Google Play Games Services API。

ゲームにログイン機能を追加する方法について詳しくは、 Android ゲームにログインします

オフライン アクセスに必要な手順は次のとおりです。

  1. Google Play Console の場合: ゲームサーバーの認証情報を作成します。「 認証情報の OAuth クライアント タイプは「web」です。
  2. Android アプリで: ログインの一環として、サーバーの認証情報についてサーバー認証コードをリクエストし、サーバーに渡します。
  3. ゲームサーバー上で: サーバー認証コードを交換して OAuth アクセスを実現する Google 認証サービスを使用してトークンを作成し、そのトークンを使用して Play Games サービスの REST API

始める前に

まず、 Google Play ConsoleGoogle Play Games サービスをセットアップし、Play Games サービスのログインをゲームに統合します。

ゲームに関連するサーバーサイド ウェブ アプリケーションを作成する

Google Play Games サービスは、ウェブゲームのバックエンド サポートを提供しません。ただし、Android ゲームのサーバーのバックエンド サポートは提供します。

Google Play Games サービスの REST API をサーバーサイド アプリで使用する場合は、次の手順を行います。

  1. Google Play Console のゲームから、[Play ゲームサービス] > [設定と管理] > [設定] に移動します。
  2. [認証情報を追加] を選択して [認証情報を追加] ページを表示します。認証情報タイプとして [ゲームサーバー] を選択し、[認証] セクションに進みます。
    1. すでにゲームサーバーに OAuth クライアント ID がある場合は、プルダウン メニューから選択します。変更を保存したら、次のセクションに進みます。
    2. ゲームサーバーに既存の OAuth クライアント ID がない場合は、作成します。
      1. [OAuth クライアントを作成] をクリックし、[OAuth クライアント ID の作成] のリンクを開きます。
      2. ゲームに関連付けられた Cloud Platform プロジェクトの Google Cloud Platform の [OAuth クライアント ID の作成] ページが表示されます。
      3. ページのフォームに記入して、[作成] をクリックします。[アプリケーションの種類] は [ウェブアプリ] に設定してください。
      4. [認証情報を追加] ページの [認証] セクションに戻り、新しく作成した OAuth クライアントを選択し、変更を保存します。

サーバー認証コードを取得する

ゲームがバックエンド サーバーのアクセス トークンに使用できるサーバー認証コードを取得するには:

  1. クライアントから requestServerSideAccess を呼び出します。

    1. Android アプリの OAuth クライアント ID ではなく、ゲームサーバーに登録されている OAuth クライアント ID を使用していることを確認してください。
    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 認証コードトークンをバックエンド サーバーに送信して交換されるようにし、プレーヤー ID が Play ゲームサービスの REST API に対して検証され、ゲームに対して認証されるようにします。

サーバー認証コードをサーバーのアクセス トークンと交換する

サーバー認証コードをバックエンド サーバーに送信して、アクセス トークンと更新トークンと交換します。 アクセス トークンを使用して、プレーヤーの代わりに Google Play Games サービス API を呼び出します。必要に応じて、 更新トークンを保存して、アクセス トークンの有効期限が切れたときに新しいアクセス トークンを取得します。

次のコード スニペットは、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 を呼び出す

詳しくは、Google Play Games サービスの REST API をご覧ください。 をご覧ください。

REST API 呼び出しのうち、有用だと思われるものの例を次に示します。

プレーヤー

  • ログインしているプレーヤーの ID とプロフィール データを取得する場合は、Players.get を呼び出します。 ID は 'me' です。

友だち

友達について詳しくは、友達ガイドをご覧ください。

  • プレーヤーの友だちリストを取得しますか?次のコマンドで Players.list を呼び出します。 collection として 'friends_all'
  • 友達リストにアクセスできるかどうかを確認します。me について Players.get を呼び出し、 レスポンスの profileSettings.friendsListVisibility フィールドを確認します。

実績

実績についての説明が記載された実績ガイドをご覧ください。 詳しく説明します。

  • 現在の実績のリストを取得しますか?AchievementDefinitions.list を呼び出すことができます。
  • これと Achievements.list の呼び出しを組み合わせて、プレーヤーがロック解除した実績を確認します。
  • 実績を獲得しましたか?Achievements.unlock を使用してロックを解除してください。
  • 部分的な達成に向けて前進しましたか?Achievements.increment を使用する 進行状況を報告し、プレーヤーがロック解除したかどうかを確認します。
  • まだ本番環境にないゲームをデバッグしていますか?発信してみてください Management API の Achievements.reset または Achievements.resetAll 実績を元の状態にリセットできます。

リーダーボード

リーダーボードについて詳しくは、リーダーボードに関するガイドをご覧ください。

  • ゲームの全スコアボードのリストを取得する場合は、Leaderboards.list を呼び出します。
  • プレーヤーのゲーム終了そのスコアを Scores.submit に送信し、 ハイスコアを更新しています
  • リーダーボードを表示しますか?Scores.list からデータを取得し、ユーザーに表示します。
  • Scores.listWindow を使用して、ユーザーのハイスコアに近い一連のスコアを見つけます。
  • 特定のリーダーボードでのプレーヤーのスコアに関する詳細情報( プレイヤーがすべてのプレーヤーの上位 12% に入っている場合、Scores.get を呼び出します。
  • ゲームをデバッグしていますか?管理チームから Scores.reset を呼び出して 特定のリーダーボードからそのプレーヤーのすべてのスコアをリセットする API