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

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

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

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

כדי לראות דוגמת קוד מפורטת שמראה איך להשתמש ב'כניסה באמצעות חשבון Google' לאימות שחקנים, אפשר לעיין ב דוגמה אחת (clientserverskeleton) ב-GitHub.

כדי לקבל גישה במצב אופליין, נדרשים השלבים הבאים:

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

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

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

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

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

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

  1. יוצרים אפליקציית אינטרנט משויכת למשחק בקטע אפליקציות מקושרות של מ-Google Play Console. שימו לב השדה launch_url לא משמש לתהליך הזה ואפשר להשאיר אותו ריק.
  2. כדי לקבל את פרטי פרטי הכניסה של האפליקציה, יש לפעול לפי השלבים הבאים:
    1. מהמשחק ב-Google Play Console, לוחצים על פרטי המשחק.
    2. גוללים למטה לקטע API Console (פרויקט של מסוף API) ולוחצים על הקישור. לפרויקט במסוף ה-API.
    3. מתוך ממשקי API שירותים > המסך Credentials ב-Google API במסוף, מורידים את הקובץ client_secret.json עבור אפליקציית האינטרנט ושומרים אותו במיקום שהשרת יכול לגשת אליו. הקלטת הלקוח המזהה של פרטי הכניסה לשימוש במועד מאוחר יותר.
  3. מפעילים מחדש את האפליקציה בצד השרת כדי שהיא תהיה מוכנה לקבל בקשות מ- לאפליקציית הלקוח של המשחק.

מתבצעת כניסה אל הלקוח

המחלקה GoogleSignInClient היא נקודת הכניסה העיקרית לשחזור החשבון של המשתמש הנוכחי בנגן שמחובר לחשבון, ולהיכנס לחשבון של הנגן אם הוא לא עשה זאת בעבר באפליקציה במכשיר.

כדי ליצור לקוח לכניסה, פועלים לפי השלבים הבאים:

  1. יוצרים לקוח לכניסה באמצעות האובייקט GoogleSignInOptions. ב GoogleSignInOptions.Builder כדי להגדיר את הכניסה, צריך לציין GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN
  2. צריך גם לציין שנדרש אימות למשחק של שרת הקצה העורפי שלכם באמצעות קריאה השיטה GoogleSignInOptions.Builder.requestServerAuthCode() עם מזהה הלקוח של השרת בתור הפרמטר. אחזור קוד ההרשאה מאוחר יותר עבור אסימוני גישה בשרת הקצה העורפי, כפי שמתואר בקטע קבלת קוד הרשאת השרת.
  3. קוראים לשיטה GoogleSignIn.getClient() ומעבירים את האפשרויות שהגדרתם בעבר. אם השיחה הפעולה בוצעה בהצלחה, Google Sign-In API מחזיר מופע של GoogleSignInClient.
  4. אחרי שמקבלים את המופע של GoogleSignInClient, צריך להמשיך בתהליך כניסת הנגן בשקט מ-onResume() של הפעילות, כפי שמתואר ב- כניסה שקטה.

לדוגמה:

private static final int RC_SIGN_IN = 9001;
private GoogleSignInClient mGoogleSignInClient;

private void startSignInForAuthCode() {

  // Client ID for your backend server.
  String webClientId = getString(R.string.webclient_id);

  GoogleSignInOptions signInOption = new
      GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
      .requestServerAuthCode(webClientId)
      .build();

  GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption);
  Intent intent = signInClient.getSignInIntent();
  startActivityForResult(intent, RC_SIGN_IN);
}

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

כדי לאחזר קוד אימות שרת שהמשחק יכול להשתמש בו לאסימוני גישה בשרת העורפי: להתקשר אל getServerAuthCode() ל-GoogleSignInAccount אובייקט שמוחזר מכניסה באמצעות חשבון Google בכניסה מוצלחת של נגן.

לדוגמה:


// Auth code to send to backend server.
private String mServerAuthCode;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == RC_SIGN_IN) {
    GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
    if (result.isSuccess()) {
      mServerAuthCode = result.getSignInAccount().getServerAuthCode();
    } else {
      String message = result.getStatus().getStatusMessage();
      if (message == null || message.isEmpty()) {
        message = getString(R.string.signin_other_error);
      }
      new AlertDialog.Builder(this).setMessage(message)
          .setNeutralButton(android.R.string.ok, null).show();
    }
  }
}

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

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

קטע הקוד הבא מראה איך ליישם את הקוד בצד השרת ב-Java שפת תכנות כדי להחליף את קוד ההרשאה של השרת באסימוני גישה. זה כן באמצעות clientserverskeleton לדוגמה app:

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

כדי לקבל מידע נוסף על גישה ל-Google APIs משרת קצה עורפי מטעם נגן שמחובר לחשבון, למידע נוסף, ראו הפעלת גישה בצד השרת.

טיפול ביציאה של השחקן

כדי לנתק את השחקנים מהמשחק, יש להפעיל את השיטה signOut() ב-GoogleSignInClient. עבור קטע קוד לדוגמה, מוציאים את הנגן מהחשבון.

קריאה לממשקי 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 דרך ממשקי ה-API של ניהול. לאפס את ההישגים למצבם המקורי.

Leaderboards

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

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