הפעלת גישה מצד השרת ל-Google Play Games Services

מומלץ לאמת נגנים להעביר באופן מאובטח את זהות הנגן לשרת העורפי. הפעולה הזאת מאפשרת של המשחק שלך כדי לאחזר באופן מאובטח את זהות השחקן ונתונים אחרים של חשיפה אפשרית לפריצה בזמן המעבר דרך המכשיר.

בתרחיש הזה, ברגע של הנגן נכנסים בהצלחה, ניתן לבקש קוד מיוחד לשימוש חד-פעמי (שנקרא קוד ההרשאה של השרת) מה-SDK של Play Games Services v2, שהלקוח מעביר לשרת. לאחר מכן, בשרת, את קוד אימות השרת לאסימון OAuth 2.0 שבו השרת יכול להשתמש כדי לבצע קריאות ממשק ה-API של Google Play Games Services.

לקבלת הנחיות נוספות על הוספת כניסה למשחקים, קראו את המאמר כניסה למשחקים ל-Android.

כדי לקבל גישה אופליין, צריך לבצע את הפעולות הבאות:

  1. ב-Google Play Console: יוצרים פרטי כניסה לשרת המשחקים. סוג הלקוח ב-OAuth של פרטי הכניסה יהיה 'אינטרנט'.
  2. באפליקציה ל-Android: כחלק מהכניסה, צריך לבקש קוד אימות שרת עבור של השרת שלך, ומעבירים אותם לשרת שלך.
  3. בשרת המשחקים: החלפת קוד ההרשאה של השרת בגישת OAuth באמצעות שירותי האימות של Google, ואז להשתמש בו כדי לקרוא API ל-REST ב-Play Games Services.

לפני שמתחילים

קודם צריך להוסיף את המשחק Google Play Console, כפי שמתואר מגדירים את Google Play Games Services ומשלבים את התכונה כניסה ל-Play Games Services במשחק.

יצירת אפליקציית אינטרנט משויכת בצד השרת למשחק

שירותי המשחקים של Google Play לא מספקים שירותי קצה עורפי תמיכה במשחקי אינטרנט. עם זאת, הוא מספק תמיכה בשרת עורפי לשרת של המשחק ל-Android.

כדי להשתמש בממשקי ה-API ל-REST של שירותי Google Play Games באפליקציה בצד השרת, צריך לפעול לפי השלבים הבאים:

  1. מהמשחק ב-Google Play Console, עוברים אל Play Games Services > הגדרה וניהול > הגדרה.
  2. בוחרים באפשרות Add credential (הוספת פרטי כניסה) כדי לעבור אל Add credential (הוספת פרטי כניסה). בוחרים באפשרות שרת משחקים כסוג פרטי הכניסה וממשיכים לקטע הרשאה.
    1. אם לשרת המשחקים כבר יש מזהה לקוח OAuth, בוחרים אותו מהתפריט הנפתח. לאחר שמירת השינויים, עוברים לקטע הבא.
    2. אם אין מזהה לקוח OAuth עבור שרת המשחקים שלכם, אפשר ליצור מזהה כזה.
      1. לוחצים על Create OAuth client ופועלים לפי ההוראות בקישור Create OAuth Client ID.
      2. תועברו לדף Create OAuth Client ID ב-Google Cloud Platform, עבור הפרויקט המשויך של המשחק ב-Cloud Platform.
      3. ממלאים את הטופס של הדף ולוחצים על 'יצירה'. חשוב להגדיר את Application type (סוג האפליקציה) כ-Web application (אפליקציית אינטרנט).
      4. חוזרים לקטע Add Credential page (הוספת פרטי כניסה), בוחרים את לקוח ה-OAuth החדש שנוצר ושומרים את השינויים.

קבלת קוד ההרשאה של השרת

כדי לאחזר קוד אימות שרת שאפשר להשתמש בו במשחק לאסימוני גישה בשרת הקצה העורפי:

  1. קוראים ל-requestServerSideAccess מהלקוח.

    1. חשוב לוודא שאתם משתמשים במזהה הלקוח ב-OAuth שרשום לשרת המשחקים ולא במזהה הלקוח ב-OAuth של אפליקציית Android.
    2. (אופציונלי) אם שרתי המשחקים שלכם דורשים גישה אופליין (גישה לטווח ארוך באמצעות אסימון רענון) ל-Play Games Services, תוכלו להגדיר את הפרמטר 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 לשרת הקצה העורפי כדי שניתן יהיה להמיר אותו, בודקים את מזהה השחקן מול ממשקי ה-API ל-REST של Play Games Services ואז מבצעים אימות באמצעות המשחק.

החלפת קוד אימות השרת באסימון גישה בשרת

שולחים את קוד האימות של השרת לשרת הקצה העורפי כדי להמיר אותו לאסימוני גישה ואסימוני רענון. משתמשים באסימון הגישה כדי להפעיל את Google Play Games Services 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;
}

קריאה לממשקי API בארכיטקטורת REST מהשרת

ממשקי API ל-REST לשירותי Google Play Games – תיאור מלא של קריאות ה-API הזמינות.

ריכזנו כאן דוגמאות לקריאות API ל-REST שיכולות להועיל:

שחקן

  • רוצים לקבל את המזהה ואת נתוני הפרופיל של השחקן שנכנס לחשבון? קוראים ל-Players.get עם 'me' בתור המזהה.

חברים

מומלץ לעיין במדריך חברים, שבו מוסבר בפירוט רב יותר על החברים.

  • רוצים לאחזר את רשימת החברים של השחקן? קוראים לפונקציה Players.list עם הערך 'friends_all' כ-collection.
  • בודקים אם יש לכם גישה לרשימת החברים. התקשרות אל Players.get תמורת me, וגם בודקים את השדה profileSettings.friendsListVisibility בתשובה.

הישגים

חשוב לקרוא את המדריך הישגים, שמסביר על הישגים בצורה מפורטת יותר.

  • רוצה לקבל רשימה של ההישגים הנוכחיים? אפשר לבצע קריאה ל-AchievementDefinitions.list.
  • אפשר לשלב זאת עם קריאה אל Achievements.list כדי לברר אילו מהשחקנים ביטלו את הנעילה שלהם.
  • האם השחקן צבר הישג? כדי לבטל את הנעילה, צריך להשתמש ב-Achievements.unlock.
  • האם השחקן התקדם להישג חלקי? משתמשים ב-Achievements.increment כדי לדווח על התקדמות (ולגלות אם השחקן ביטל את הנעילה שלו).
  • האם אתם מנסים לנפות באגים במשחק שעדיין לא עבר לסביבת הייצור? אפשר לנסות להפעיל את Achievements.reset או את Achievements.resetAll מ-Management APIs כדי לאפס את ההישגים למצב המקורי שלהם.

Leaderboards

מומלץ לקרוא את המדריך בנושא לוחות לידרבורד, שמסביר בצורה מפורטת יותר את לוחות הלידרבורד.

  • רוצים לקבל רשימה של כל לוחות התוצאות במשחק? מריצים את הפונקציה Leaderboards.list.
  • האם השחקן סיים משחק? אפשר לשלוח את התוצאה שלהם אל Scores.submit ולבדוק אם זו תוצאה גבוהה חדשה.
  • רוצה להציג Leaderboard? ניתן לקבל את הנתונים מ-Scores.list ולהציג אותם למשתמש.
  • משתמשים ב-Scores.listWindow כדי למצוא מגוון של ציונים שקרובים לתוצאה של המשתמש.
  • כדי לקבל מידע נוסף על הניקוד של השחקן בלידרבורד מסוים (לדוגמה, אם שהשחקן נמצא ב-12% המובילים מכל השחקנים, ניתן לקרוא ל-Scores.get.
  • אתם מתקנים באגים במשחק? אפשר לנסות להפעיל את Scores.reset מ-Management API כדי לאפס את כל הנקודות של השחקן הזה מ-Leaderboard מסוים.