การเข้าถึงบริการเกมของ Google Play ฝั่งเซิร์ฟเวอร์

เราขอแนะนำให้คุณใช้ GamesSignInClient เพื่อตรวจสอบสิทธิ์ผู้เล่นและส่งข้อมูลประจำตัวของผู้เล่นไปยังเซิร์ฟเวอร์แบ็กเอนด์อย่างปลอดภัย ซึ่งจะช่วยให้เกมดึงข้อมูลประจำตัวและ ข้อมูลอื่นๆ ของผู้เล่นได้อย่างปลอดภัยโดยไม่เสี่ยงต่อการถูกดัดแปลงขณะส่งผ่าน อุปกรณ์

เมื่อผู้เล่นตรวจสอบสิทธิ์สำเร็จแล้ว คุณจะขอรหัสแบบใช้ครั้งเดียวพิเศษ (เรียกว่ารหัสการให้สิทธิ์เซิร์ฟเวอร์) จาก Play Games Services SDK v2 ได้ ซึ่งไคลเอ็นต์จะส่งรหัสดังกล่าวไปยังเซิร์ฟเวอร์ จากนั้นในเซิร์ฟเวอร์ ให้แลกรหัสการให้สิทธิ์เซิร์ฟเวอร์ เป็นโทเค็น OAuth 2.0 ที่เซิร์ฟเวอร์ใช้เพื่อทำการเรียกไปยัง Google Play Games Services API ได้

ดูคำแนะนำเพิ่มเติมเกี่ยวกับการเพิ่มการตรวจสอบสิทธิ์ในเกมได้ที่ การตรวจสอบสิทธิ์แพลตฟอร์มสำหรับเกม Android

คุณต้องทำตามขั้นตอนต่อไปนี้เพื่อเข้าถึงแบบออฟไลน์

  1. ใน Google Play Console ให้สร้างข้อมูลเข้าสู่ระบบสำหรับเซิร์ฟเวอร์เกม ประเภทไคลเอ็นต์ OAuth ของข้อมูลเข้าสู่ระบบจะเป็น "เว็บ"
  2. ในแอป Android: ในขั้นตอนการตรวจสอบสิทธิ์แพลตฟอร์ม ให้ขอรหัสการตรวจสอบสิทธิ์เซิร์ฟเวอร์สำหรับข้อมูลเข้าสู่ระบบของเซิร์ฟเวอร์ แล้วส่งรหัสดังกล่าวไปยังเซิร์ฟเวอร์ GamesSigninClient สามารถขอขอบเขต OAuth 2.0 ได้ 3 รายการเมื่อขอสิทธิ์เข้าถึงฝั่งเซิร์ฟเวอร์ไปยังเว็บ API ของบริการเกม Play ขอบเขตที่ไม่บังคับคือ EMAIL, PROFILE และ OPEN_ID ขอบเขตเริ่มต้น 2 รายการ ได้แก่ DRIVE_APPFOLDER และ GAMES_LITE
  3. ในเซิร์ฟเวอร์เกม ให้แลกรหัสการให้สิทธิ์เซิร์ฟเวอร์เป็นโทเค็นการเข้าถึง OAuth โดยใช้บริการการตรวจสอบสิทธิ์ของ Google แล้วใช้โทเค็นนี้เพื่อเรียกใช้ บริการเกมของ Play REST API

ก่อนเริ่มต้น

ก่อนอื่นคุณต้องเพิ่มเกมใน Google Play Console ตามที่อธิบายไว้ในตั้งค่าบริการเกมของ Google Play และผสานรวมการตรวจสอบสิทธิ์แพลตฟอร์มบริการเกมของ Play กับเกม

สร้างเว็บแอปฝั่งเซิร์ฟเวอร์

บริการเกมของ Google Play ไม่รองรับแบ็กเอนด์สำหรับเกมบนเว็บ แต่จะให้การสนับสนุนเซิร์ฟเวอร์แบ็กเอนด์ สำหรับเซิร์ฟเวอร์ของเกม Android

หากต้องการใช้ REST API สำหรับบริการเกมของ Google Play ในแอปฝั่งเซิร์ฟเวอร์ ให้ทำตามขั้นตอนต่อไปนี้

  1. เลือกเกมใน Google Play Console
  2. ไปที่บริการเกมของ Play > การตั้งค่าและการจัดการ > การกำหนดค่า
  3. เลือกเพิ่มข้อมูลเข้าสู่ระบบเพื่อไปยังหน้าเพิ่มข้อมูลเข้าสู่ระบบ เลือกเซิร์ฟเวอร์เกมเป็นประเภทข้อมูลเข้าสู่ระบบ แล้วไปที่ส่วนการให้สิทธิ์
    1. หากเซิร์ฟเวอร์เกมมีรหัสไคลเอ็นต์ OAuth อยู่แล้ว ให้เลือกรหัสจากเมนูแบบเลื่อนลง หลังจากบันทึกการเปลี่ยนแปลงแล้ว ให้ไปที่ส่วนถัดไป
    2. หากยังไม่มีรหัสไคลเอ็นต์ OAuth สำหรับเซิร์ฟเวอร์เกม คุณสามารถ สร้างรหัสได้
      1. คลิกสร้างไคลเอ็นต์ OAuth แล้วทำตามลิงก์สร้างรหัสไคลเอ็นต์ OAuth
      2. ซึ่งจะนำคุณไปยังหน้าสร้างรหัสไคลเอ็นต์ OAuth ของ Google Cloud Platform สำหรับโปรเจ็กต์ที่เชื่อมโยงกับเกม
      3. กรอกแบบฟอร์มของหน้าเว็บ แล้วคลิกสร้าง อย่าลืมตั้งค่า ประเภทแอปพลิเคชันเป็นเว็บแอปพลิเคชัน
      4. กลับไปที่ส่วนการให้สิทธิ์ของหน้าเพิ่มข้อมูลเข้าสู่ระบบ เลือกไคลเอ็นต์ OAuth ที่สร้างขึ้นใหม่ แล้วบันทึกการเปลี่ยนแปลง

รับรหัสการตรวจสอบสิทธิ์ของเซิร์ฟเวอร์

หากต้องการดึงรหัสการให้สิทธิ์เซิร์ฟเวอร์ที่เกมใช้สำหรับโทเค็นการเข้าถึงในเซิร์ฟเวอร์แบ็กเอนด์ ให้ทำดังนี้

  1. โทรหา requestServerSideAccess จากไคลเอ็นต์
    1. โปรดตรวจสอบว่าคุณใช้รหัสไคลเอ็นต์ OAuth ที่ลงทะเบียนสำหรับเซิร์ฟเวอร์เกม ไม่ใช่รหัสไคลเอ็นต์ OAuth ของแอปพลิเคชัน Android
    2. (ไม่บังคับ) หากเซิร์ฟเวอร์เกมของคุณต้องมีการเข้าถึงแบบออฟไลน์ (การเข้าถึงระยะยาว โดยใช้โทเค็นการรีเฟรช) เพื่อเข้าถึงบริการเกมของ Play คุณสามารถตั้งค่าพารามิเตอร์ forceRefreshToken เป็น true ได้
  2. (ไม่บังคับ) ในขั้นตอนการตรวจสอบสิทธิ์ ผู้ใช้ใหม่ควรเห็นหน้าจอความยินยอมเดียวสำหรับขอบเขตเพิ่มเติม เมื่อยอมรับความยินยอมแล้ว คุณจะตั้งค่าพารามิเตอร์ scopes ด้วยขอบเขต OAuth ของ EMAIL, PROFILE และ OPEN_ID หากผู้ใช้ปฏิเสธความยินยอม ระบบจะส่งเฉพาะขอบเขตเริ่มต้น 2 รายการ DRIVE_APPFOLDER และ GAMES_LITE ไปยังแบ็กเอนด์

    หน้าจอขอความยินยอมสำหรับขอบเขต 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 ไปยังเซิร์ฟเวอร์แบ็กเอนด์เพื่อให้สามารถแลกเปลี่ยน ยืนยันรหัสผู้เล่นกับ REST API ของบริการเกมของ Play แล้ว ตรวจสอบสิทธิ์กับเกมของคุณ

ส่งรหัสการตรวจสอบสิทธิ์ของเซิร์ฟเวอร์

ส่งรหัสการให้สิทธิ์ของเซิร์ฟเวอร์ไปยังเซิร์ฟเวอร์แบ็กเอนด์เพื่อแลกเป็นโทเค็นการเข้าถึงและ โทเค็นการรีเฟรช ใช้โทเค็นเพื่อการเข้าถึงเพื่อเรียกใช้ Play Games Services API ในนามของผู้เล่น และจัดเก็บโทเค็นรีเฟรช (ไม่บังคับ) เพื่อรับโทเค็นเพื่อการเข้าถึงใหม่เมื่อโทเค็นเพื่อการเข้าถึงหมดอายุ

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของรหัสผู้เล่นได้ที่รหัสผู้เล่นรุ่นใหม่

ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่คุณอาจใช้โค้ดฝั่งเซิร์ฟเวอร์ใน ภาษาการเขียนโปรแกรม Java เพื่อแลกเปลี่ยนรหัสการให้สิทธิ์ของเซิร์ฟเวอร์เป็นโทเค็นเพื่อเข้าถึง

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

คุณสามารถดึงขอบเขต OAuth ได้โดยใช้ไลบรารีของไคลเอ็นต์ Google API ใน Java หรือ Python เพื่อรับออบเจ็กต์ GoogleIdTokenVerifier ข้อมูลโค้ดต่อไปนี้ แสดงการติดตั้งใช้งานในภาษาโปรแกรม 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");

    // Use or store profile information
    // ...

    } else {
      System.out.println("Invalid ID token.");
    }
}

เรียกใช้ REST API จากเซิร์ฟเวอร์

ดูคำอธิบายแบบเต็มของการเรียก API ที่ใช้ได้ที่ REST API สำหรับบริการเกมของ Google Play

ตัวอย่างการเรียก REST API ที่คุณอาจเห็นว่ามีประโยชน์ ได้แก่

ผู้เล่น

หากต้องการรับการตรวจสอบสิทธิ์ด้วยรหัสและข้อมูลโปรไฟล์ของผู้เล่น เรียกใช้ Players.get โดยใช้ 'me' เป็นรหัส

เพื่อน

ดูรายละเอียดได้ในคำแนะนำเกี่ยวกับเพื่อน

  • หากต้องการดึงรายชื่อเพื่อนของผู้เล่น ให้เรียกใช้ Players.list โดยใช้ friends_all เป็น collection

  • หากต้องการยืนยันว่าคุณมีสิทธิ์เข้าถึงรายชื่อเพื่อนหรือไม่ ให้เรียกใช้ Players.get โดยใช้ me เป็น playerID และ ดูฟิลด์ profileSettings.friendsListVisibility ในการตอบกลับ

ความสำเร็จ

ดูรายละเอียดได้ในคำแนะนำเกี่ยวกับรางวัลพิเศษ

  • หากต้องการดูรายการรางวัลพิเศษปัจจุบัน ให้เรียกใช้ AchievementDefinitions.list

  • รวมเข้ากับการเรียกใช้ Achievements.list เพื่อดูว่าผู้เล่นปลดล็อกรางวัลใดบ้าง

  • เรียกใช้ Achievements.unlock เพื่อปลดล็อกรางวัลพิเศษของผู้เล่น

  • เรียกใช้ Achievements.increment เพื่อรายงานความคืบหน้าของรางวัลพิเศษ และดูว่าผู้เล่นปลดล็อกรางวัลพิเศษหรือไม่

  • หากคุณกำลังแก้ไขข้อบกพร่องของเกมที่ยังไม่ถึงเวอร์ชันที่ใช้งานจริง คุณสามารถเรียกใช้ Achievements.reset หรือ Achievements.resetAll จาก Management API เพื่อรีเซ็ตรางวัลพิเศษให้กลับสู่สถานะเดิม

ลีดเดอร์บอร์ด

ดูรายละเอียดได้ในคำแนะนำลีดเดอร์บอร์ด

  • หากต้องการดูรายการกระดานคะแนนทั้งหมดในเกม ให้เรียกใช้ Leaderboards.list

  • หากผู้เล่นเล่นเกมจบแล้ว คุณสามารถส่งคะแนนของผู้เล่นไปยัง Scores.submit และดูว่าคะแนนดังกล่าวเป็นคะแนนสูงสุดใหม่หรือไม่

  • หากต้องการแสดงลีดเดอร์บอร์ด ให้รับข้อมูลจาก Scores.list แล้วแสดงต่อผู้ใช้

  • ใช้ Scores.listWindow เพื่อค้นหาคะแนนที่หลากหลายซึ่งใกล้เคียงกับคะแนนสูงสุดของผู้ใช้

  • หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับคะแนนของผู้เล่นในลีดเดอร์บอร์ดหนึ่งๆ (เช่น หากผู้เล่นอยู่ในกลุ่มผู้เล่น 12% แรก) ให้เรียกใช้ Scores.get

  • หากกำลังแก้ไขข้อบกพร่องของเกม คุณสามารถเรียกใช้ Scores.reset จาก Management API เพื่อรีเซ็ตคะแนนทั้งหมดของผู้เล่นจากลีดเดอร์บอร์ด หนึ่งๆ