دسترسی سمت سرور به خدمات بازی های Google Play

توصیه می‌کنیم از GamesSignInClient برای احراز هویت بازیکنان و انتقال ایمن هویت بازیکن به سرور backend استفاده کنید. این امر به بازی شما امکان می‌دهد تا هویت بازیکن و سایر داده‌های او را به طور ایمن بازیابی کند، بدون اینکه در حین عبور از دستگاه در معرض دستکاری‌های احتمالی قرار گیرد.

پس از احراز هویت موفقیت‌آمیز بازیکن، می‌توانید یک کد یکبار مصرف ویژه (به نام کد احراز هویت سرور ) را از Play Games Services v2 SDK درخواست کنید که کلاینت آن را به سرور ارسال می‌کند. سپس، در سرور، کد احراز هویت سرور را با یک توکن OAuth 2.0 که سرور می‌تواند برای برقراری تماس با API Google Play Games Services از آن استفاده کند، مبادله کنید.

برای راهنمایی بیشتر در مورد افزودن احراز هویت در بازی‌هایتان، به احراز هویت پلتفرم برای بازی‌های اندروید مراجعه کنید.

برای دسترسی آفلاین، مراحل زیر لازم است:

  1. در کنسول گوگل پلی: یک اعتبارنامه برای سرور بازی خود ایجاد کنید. نوع اعتبارنامه برای کلاینت OAuth، «وب» خواهد بود.
  2. در برنامه اندروید: به عنوان بخشی از احراز هویت پلتفرم، یک کد احراز هویت سرور برای اعتبارنامه سرور خود درخواست کنید و آن را به سرور خود ارسال کنید. GamesSigninClient می‌تواند هنگام درخواست دسترسی سمت سرور به APIهای وب Play Games Services، سه حوزه OAuth 2.0 درخواست کند. حوزه‌های اختیاری EMAIL ، PROFILE و OPEN_ID هستند. دو حوزه پیش‌فرض DRIVE_APPFOLDER و GAMES_LITE هستند.
  3. روی سرور بازی خود: کد احراز هویت سرور را با استفاده از سرویس‌های احراز هویت گوگل با یک توکن دسترسی OAuth جایگزین کنید و سپس از آن برای فراخوانی APIهای REST سرویس‌های Play Games استفاده کنید.

قبل از اینکه شروع کنی

ابتدا باید بازی خود را در کنسول گوگل پلی ، همانطور که در بخش «راه‌اندازی سرویس‌های بازی‌های گوگل پلی» توضیح داده شده است، اضافه کنید و احراز هویت پلتفرم سرویس‌های بازی‌های پلی را با بازی خود ادغام کنید.

ایجاد یک برنامه وب سمت سرور

سرویس‌های بازی گوگل پلی پشتیبانی بک‌اند برای بازی‌های وب ارائه نمی‌دهد. با این حال، پشتیبانی بک‌اند سرور را برای سرور بازی اندروید شما فراهم می‌کند.

اگر می‌خواهید از APIهای REST برای سرویس‌های بازی‌های گوگل پلی در برنامه سمت سرور خود استفاده کنید، این مراحل را دنبال کنید:

  1. در کنسول گوگل پلی ، یک بازی را انتخاب کنید.
  2. به سرویس‌های بازی‌های Play > راه‌اندازی و مدیریت > پیکربندی بروید.
  3. برای رفتن به صفحه افزودن اعتبارنامه، گزینه افزودن اعتبارنامه (Add credential) را انتخاب کنید. نوع اعتبارنامه را Game server انتخاب کنید و به بخش Authorization بروید.
    1. اگر سرور بازی شما از قبل شناسه کلاینت OAuth دارد، آن را از منوی کشویی انتخاب کنید. پس از ذخیره تغییرات، به بخش بعدی بروید.
    2. اگر شناسه کلاینت OAuth موجود برای سرور بازی خود ندارید، می‌توانید یکی ایجاد کنید.
      1. روی ایجاد کلاینت OAuth کلیک کنید و پیوند ایجاد شناسه کلاینت OAuth را دنبال کنید.
      2. این شما را به صفحه ایجاد شناسه کلاینت OAuth در پلتفرم ابری گوگل برای پروژه مرتبط با بازی‌تان هدایت می‌کند.
      3. فرم صفحه را پر کنید و روی ایجاد کلیک کنید. حتماً نوع برنامه را روی برنامه وب تنظیم کنید.
      4. به بخش مجوزها در صفحه افزودن اعتبارنامه برگردید، کلاینت OAuth تازه ایجاد شده را انتخاب کنید و تغییرات خود را ذخیره کنید.

دریافت کد احراز هویت سرور

برای بازیابی کد احراز هویت سرور که بازی شما می‌تواند برای توکن‌های دسترسی در سرور بک‌اند شما استفاده کند:

  1. فراخوانی requestServerSideAccess از سمت کلاینت.
    1. مطمئن شوید که از شناسه کلاینت OAuth ثبت‌شده برای سرور بازی خود استفاده می‌کنید و نه از شناسه کلاینت OAuth برنامه اندروید خود.
    2. (اختیاری) اگر سرور بازی شما نیاز به دسترسی آفلاین (دسترسی طولانی مدت با استفاده از توکن refresh) به سرویس‌های بازی‌های Play دارد، می‌توانید پارامتر forceRefreshToken را روی true تنظیم کنید.
  2. (اختیاری) به عنوان بخشی از احراز هویت، کاربران جدید باید برای دسترسی به حوزه‌های بیشتر، با یک صفحه رضایت واحد مواجه شوند. پس از پذیرش رضایت، پارامتر scopes با حوزه‌های EMAIL ، PROFILE و OPEN_ID OAuth تنظیم می‌کنید. اگر کاربران رضایت را رد کنند، فقط دو حوزه پیش‌فرض DRIVE_APPFOLDER و GAMES_LITE به backend ارسال می‌شوند.

    صفحه رضایت برای دامنه‌های اضافی OAuth.
    صفحه رضایت برای محدوده‌های اضافی 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.
         }
     });
     

  3. کد تایید OAuth را به سرور backend خود ارسال کنید تا مبادله شود، شناسه بازیکن با APIهای REST سرویس‌های Play Games تأیید شود و سپس با بازی شما احراز هویت شود.

ارسال کد احراز هویت سرور

کد احراز هویت سرور را برای تبادل توکن‌های دسترسی و به‌روزرسانی به سرور بک‌اند خود ارسال کنید. از توکن دسترسی برای فراخوانی API خدمات بازی‌های Play از طرف بازیکن استفاده کنید و به صورت اختیاری، توکن به‌روزرسانی را ذخیره کنید تا پس از انقضای توکن دسترسی، یک توکن دسترسی جدید دریافت کنید.

برای اطلاعات بیشتر در مورد نحوه عملکرد شناسه‌های پخش‌کننده، به شناسه‌های پخش‌کننده نسل بعدی مراجعه کنید.

قطعه کد زیر نشان می‌دهد که چگونه می‌توانید کد سمت سرور را در زبان برنامه‌نویسی جاوا پیاده‌سازی کنید تا کد احراز هویت سرور را با توکن‌های دسترسی مبادله کنید.

جاوا

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

شما می‌توانید با استفاده از کتابخانه‌های کلاینت API گوگل در جاوا یا پایتون، محدوده‌های OAuth را بازیابی کنید تا شیء GoogleIdTokenVerifier را دریافت کنید. قطعه کد زیر پیاده‌سازی آن را در زبان برنامه‌نویسی جاوا نشان می‌دهد.

جاوا

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

فراخوانی APIهای REST از سرور

برای شرح کامل فراخوانی‌های API موجود، به APIهای REST برای سرویس‌های بازی‌های Google Play مراجعه کنید.

نمونه‌هایی از فراخوانی‌های REST API که ممکن است برای شما مفید باشند عبارتند از:

بازیکن

می‌خواهید با شناسه و اطلاعات پروفایل بازیکن احراز هویت شوید؟ با استفاده از شناسه 'me' با Players.get تماس بگیرید.

دوستان

برای جزئیات بیشتر به راهنمای دوستان مراجعه کنید.

  • برای بازیابی لیست دوستان بازیکن، تابع Players.list را با friends_all به عنوان collection فراخوانی کنید.

  • برای تأیید اینکه آیا به لیست دوستان دسترسی دارید، Players.get را با me به عنوان playerID فراخوانی کنید و فیلد profileSettings.friendsListVisibility را در پاسخ مشاهده کنید.

دستاوردها

برای جزئیات بیشتر به راهنمای دستاوردها مراجعه کنید.

  • برای دریافت لیستی از دستاوردهای فعلی، AchievementDefinitions.list را فراخوانی کنید.

  • این را با فراخوانی Achievements.list ترکیب کنید تا بفهمید کدام یک از موارد قفل شده توسط بازیکن فعال شده است.

  • برای باز کردن قفل یک دستاورد بازیکن، Achievements.unlock را فراخوانی کنید.

  • برای گزارش پیشرفت در یک دستاورد و اطلاع از اینکه آیا بازیکن آن را قفل‌گشایی کرده است یا خیر، تابع Achievements.increment را فراخوانی کنید.

  • اگر در حال اشکال‌زدایی بازی‌ای هستید که به مرحله تولید نرسیده است، می‌توانید Achievements.reset یا Achievements.resetAll را از رابط‌های برنامه‌نویسی کاربردی مدیریت (Management APIs) فراخوانی کنید تا دستاوردها را به حالت اولیه‌شان بازنشانی کنید.

جدول امتیازات

برای جزئیات بیشتر به راهنمای جدول امتیازات مراجعه کنید.

  • برای دریافت لیستی از تمام تابلوهای امتیاز در بازی، با Leaderboards.list تماس بگیرید.

  • اگر بازیکنی بازی‌اش تمام شده باشد، می‌توانید امتیاز او را در Scores.submit ثبت کنید و ببینید که آیا این امتیاز، امتیاز بالایی است یا خیر.

  • برای نمایش جدول امتیازات، داده‌ها را از Scores.list دریافت کرده و به کاربر نشان دهید.

  • از Scores.listWindow برای یافتن مجموعه‌ای از امتیازات نزدیک به بالاترین امتیاز کاربر استفاده کنید.

  • برای دریافت اطلاعات بیشتر در مورد امتیاز بازیکن در یک جدول امتیازات خاص (برای مثال، اگر بازیکن جزو ۱۲٪ برتر از کل بازیکنان باشد)، با Scores.get تماس بگیرید.

  • اگر در حال اشکال‌زدایی یک بازی هستید، می‌توانید Scores.reset را از APIهای مدیریتی فراخوانی کنید تا تمام امتیازات آن بازیکن را از یک جدول امتیازات خاص، بازنشانی کنید.