Google Play की गेम सेवाओं का सर्वर साइड ऐक्सेस

हमारा सुझाव है कि खिलाड़ियों की पुष्टि करने के लिए, PgsGamesSignInClient का इस्तेमाल करें. साथ ही, खिलाड़ी की पहचान को बैकएंड सर्वर पर सुरक्षित तरीके से भेजें. इससे आपका गेम, खिलाड़ी की पहचान और अन्य डेटा को सुरक्षित तरीके से वापस पा सकता है. साथ ही, डिवाइस से पास होने के दौरान, डेटा में संभावित छेड़छाड़ से भी बचा जा सकता है.

खिलाड़ी की पुष्टि हो जाने के बाद, Play की गेम सेवाओं के v2 Native SDK (बीटा) से, एक बार इस्तेमाल किया जा सकने वाला खास कोड (इसे सर्वर ऑथराइज़ेशन कोड कहा जाता है) का अनुरोध किया जा सकता है. यह कोड, क्लाइंट से सर्वर को भेजा जाता है. इसके बाद, सर्वर पर सर्वर ऑथराइज़ेशन कोड को OAuth 2.0 टोकन के लिए बदलें. सर्वर इस टोकन का इस्तेमाल, Google Play की गेम सेवाओं के एपीआई को कॉल करने के लिए कर सकता है.

अपने गेम में पुष्टि करने की सुविधा जोड़ने के बारे में ज़्यादा जानकारी के लिए, प्लैटफ़ॉर्म की पुष्टि करना लेख पढ़ें.

ऑफ़लाइन ऐक्सेस के लिए, यह तरीका अपनाएं:

  1. Google Play Console में: अपने गेम सर्वर के लिए क्रेडेंशियल बनाएं. क्रेडेंशियल का OAuth क्लाइंट टाइप "वेब" होगा.
  2. Android ऐप्लिकेशन में: प्लैटफ़ॉर्म की पुष्टि करने के लिए, अपने सर्वर के क्रेडेंशियल के लिए सर्वर ऑथराइज़ेशन कोड का अनुरोध करें. इसके बाद, उसे अपने सर्वर को भेजें. Play की गेम सेवाओं के वेब एपीआई के लिए, सर्वर-साइड ऐक्सेस का अनुरोध करते समय PgsGamesSignInClient, OAuth 2.0 के तीन दायरों का अनुरोध कर सकता है. वैकल्पिक स्कोप ये हैं: PGS_AUTH_SCOPE_EMAIL, PGS_AUTH_SCOPE_PROFILE, और PGS_AUTH_SCOPE_OPENID. डिफ़ॉल्ट रूप से दो स्कोप उपलब्ध होते हैं: DRIVE_APPFOLDER और GAMES_LITE.
  3. अपने गेम सर्वर पर: Google की पुष्टि करने वाली सेवाओं का इस्तेमाल करके, सर्वर के ऑथराइज़ेशन कोड को OAuth ऐक्सेस टोकन के लिए बदलें. इसके बाद, इसका इस्तेमाल करके Play की गेम सेवाओं के REST API को कॉल करें.

शुरू करने से पहले

सबसे पहले, आपको अपने गेम को Google Play Console में जोड़ना होगा. इसके लिए, Google Play की गेम सेवाओं को सेट अप करना लेख पढ़ें.

सर्वर-साइड वेब ऐप्लिकेशन बनाना

Google Play Game services, वेब गेम के लिए बैकएंड सहायता उपलब्ध नहीं कराती है. हालांकि, यह आपके Android गेम के सर्वर के लिए बैकएंड सर्वर की सहायता उपलब्ध कराता है.

अगर आपको सर्वर-साइड ऐप्लिकेशन में, Google Play Games सेवाओं के लिए REST API का इस्तेमाल करना है, तो यह तरीका अपनाएं:

  1. Google Play Console में जाकर कोई गेम चुनें.
  2. Play की गेम सेवाएं > सेटअप और मैनेजमेंट > कॉन्फ़िगरेशन पर जाएं.
  3. क्रेडेंशियल जोड़ें को चुनें. इसके बाद, आपको क्रेडेंशियल जोड़ें पेज पर ले जाया जाएगा. क्रेडेंशियल टाइप के तौर पर गेम सर्वर चुनें और अनुमति सेक्शन पर जाएं.
    1. अगर आपके गेम सर्वर में पहले से ही OAuth क्लाइंट आईडी है, तो उसे ड्रॉप-डाउन मेन्यू से चुनें. बदलाव सेव करने के बाद, अगले सेक्शन पर जाएं.
    2. अगर आपके पास अपने गेम सर्वर के लिए कोई मौजूदा OAuth क्लाइंट आईडी नहीं है, तो उसे बनाया जा सकता है.
      1. OAuth क्लाइंट बनाएं पर क्लिक करें. इसके बाद, OAuth क्लाइंट आईडी बनाएं लिंक पर जाएं.
      2. इससे आपको Google Cloud Platform के OAuth क्लाइंट आईडी बनाएं पेज पर ले जाया जाएगा. यह पेज, आपके गेम से जुड़े प्रोजेक्ट के लिए है.
      3. पेज पर मौजूद फ़ॉर्म भरें और 'बनाएं' पर क्लिक करें. पक्का करें कि आपने ऐप्लिकेशन टाइप को वेब ऐप्लिकेशन पर सेट किया हो.
      4. क्रेडेंशियल पेज के 'अनुमति' सेक्शन जोड़ें पर वापस जाएं. इसके बाद, नया OAuth क्लाइंट चुनें और अपने बदलाव सेव करें.

सर्वर ऑथराइज़ेशन कोड पाना

अपने बैकएंड सर्वर पर ऐक्सेस टोकन के लिए, सर्वर के ऑथराइज़ेशन कोड को वापस पाने के लिए:

  1. क्लाइंट से PgsGamesSignInClient_requestServerSideAccess को कॉल करें.
    1. पक्का करें कि आपने अपने गेम सर्वर के लिए रजिस्टर किया गया OAuth क्लाइंट आईडी इस्तेमाल किया हो. Android ऐप्लिकेशन का OAuth क्लाइंट आईडी इस्तेमाल न करें.
    2. (ज़रूरी नहीं) अगर आपके गेम सर्वर को Play Games Services के ऑफ़लाइन ऐक्सेस (रीफ़्रेश टोकन का इस्तेमाल करके लंबे समय तक ऐक्सेस) की ज़रूरत है, तो force_refresh_token पैरामीटर को सही पर सेट किया जा सकता है.
  2. (ज़रूरी नहीं) पुष्टि करने की प्रक्रिया के दौरान, नए उपयोगकर्ताओं को अतिरिक्त स्कोप के लिए, सहमति देने वाली एक ही स्क्रीन दिखनी चाहिए. सहमति स्वीकार करने पर, आपको PgsAuthScope scopes पैरामीटर को PGS_AUTH_SCOPE_EMAIL, PGS_AUTH_SCOPE_PROFILE, और PGS_AUTH_SCOPE_OPENID OAuth स्कोप के साथ सेट करना होगा. अगर उपयोगकर्ता सहमति नहीं देते हैं, तो सिर्फ़ दो डिफ़ॉल्ट स्कोप DRIVE_APPFOLDER और GAMES_LITE को बैकएंड में भेजा जाता है.

    OAuth के अतिरिक्त दायरों के लिए सहमति वाली स्क्रीन.
    OAuth के अतिरिक्त दायरों के लिए सहमति वाली स्क्रीन. (ज़्यादा जानकारी के लिए इमेज पर क्लिक करें).

     // #include "google/games/pgs_games_sign_in_client.h"
     // 1. Define the Callback
     // This function is called when the server-side access request completes.
     // It provides the authorization code (on success) or an error (on failure).
     void OnServerSideAccessCallback(void* context, PgsError error, const char* serverAuthCode) {
         if (error == PgsError_Success) {
             if (serverAuthCode != nullptr) {
                 __android_log_print(ANDROID_LOG_INFO, "Games",
                     "Received Server Auth Code: %s", serverAuthCode);
                 // Send 'serverAuthCode' to your backend server immediately.
                 // Your server will exchange this code for an OAuth access token.
             }
         } else {
             __android_log_print(ANDROID_LOG_ERROR, "Games",
              "Failed to get server auth code. Error: %d", error);
         }
     }
     // 2. Define the Wrapper Function
     void RequestServerAccess(PgsGamesSignInClient* signInClient) {
         if (signInClient == nullptr) {
             return;
         }
         // This must match the "Web client ID" from your Google Cloud Console
         // (linked to your Play Console Game Server Credential).
         const char* SERVER_CLIENT_ID = "xxxx";
         // Set to 'true' if your server needs a Refresh Token (long-lived access).
         // Set to 'false' if you only need an Access Token (short-lived).
         bool forceRefreshToken = false;
         // Call the API
         PgsGamesSignInClient_requestServerSideAccess(
            signInClient,
            SERVER_CLIENT_ID,
            forceRefreshToken,
            OnServerSideAccessCallback, // The callback defined
            nullptr                     // User context (optional, passed to callback)
         );
     }
     // 3. Example Usage
     void TriggerSignInProcess(PgsGamesClient* gamesClient) {
          // Obtain the Sign-In Client from the main Games Client
          PgsGamesSignInClient* signInClient = PgsGamesClient_getSignInClient(gamesClient);
          RequestServerAccess(signInClient);
     }
     

  3. OAuth ऑथराइज़ेशन कोड टोकन को अपने बैकएंड सर्वर पर भेजें, ताकि उसे बदला जा सके. इसके बाद, Play की गेम सेवाओं के REST API के ज़रिए प्लेयर आईडी की पुष्टि की जा सके. इसके बाद, आपके गेम के साथ पुष्टि की जा सके.

सर्वर का अनुमति कोड भेजना

सर्वर ऑथराइज़ेशन कोड को अपने बैकएंड सर्वर पर भेजें, ताकि इसे ऐक्सेस और रीफ़्रेश टोकन के लिए बदला जा सके. ऐक्सेस टोकन का इस्तेमाल करके, खिलाड़ी की ओर से Play की गेम सेवाओं के एपीआई को कॉल करें. साथ ही, अगर चाहें, तो रीफ़्रेश टोकन को सेव करें, ताकि ऐक्सेस टोकन की समयसीमा खत्म होने पर नया ऐक्सेस टोकन हासिल किया जा सके.

प्लेयर आईडी के काम करने के तरीके के बारे में ज़्यादा जानने के लिए, नई जनरेशन वाले प्लेयर आईडी लेख पढ़ें.

नीचे दिए गए कोड स्निपेट में बताया गया है कि सर्वर के ऑथराइज़ेशन कोड को ऐक्सेस टोकन के लिए बदलने के लिए, C++ प्रोग्रामिंग भाषा में सर्वर-साइड कोड को कैसे लागू किया जा सकता है.

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

GoogleIdTokenVerifier ऑब्जेक्ट पाने के लिए, Java या Python में Google API क्लाइंट लाइब्रेरी का इस्तेमाल करके, OAuth स्कोप वापस पाए जा सकते हैं. यहां दिया गया कोड स्निपेट, 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 API को कॉल करना

उपलब्ध एपीआई कॉल के बारे में पूरी जानकारी के लिए, Google Play की गेम सेवाओं के लिए REST API देखें.

REST API कॉल के कुछ उदाहरण यहां दिए गए हैं, जो आपके काम आ सकते हैं:

खिलाड़ी

क्या आपको प्लेयर के आईडी और प्रोफ़ाइल डेटा की पुष्टि करनी है? आईडी के तौर पर 'me' का इस्तेमाल करके, Players.get को कॉल करें.

उपलब्धियां

ज़्यादा जानकारी के लिए, उपलब्धियां गाइड देखें.

  • मौजूदा उपलब्धियों की सूची पाने के लिए, AchievementDefinitions.list को कॉल करें.

  • इसके बाद, Achievements.list को कॉल करके यह पता लगाएं कि खिलाड़ी ने कौनसी उपलब्धियां अनलॉक की हैं.

  • किसी खिलाड़ी की उपलब्धि को अनलॉक करने के लिए, Achievements.unlock को कॉल करें.

  • किसी उपलब्धि की प्रोग्रेस की जानकारी देने के लिए, Achievements.increment को कॉल करें. साथ ही, यह पता लगाएं कि खिलाड़ी ने उसे अनलॉक किया है या नहीं.

  • अगर आपको ऐसे गेम को डीबग करना है जो प्रोडक्शन में नहीं है, तो मैनेजमेंट एपीआई से Achievements.reset या Achievements.resetAll को कॉल करके, उपलब्धियों को उनकी मूल स्थिति में रीसेट किया जा सकता है.