ตรวจสอบสิทธิ์โดยใช้บริการเกม Google Play ด้วย C++

คุณสามารถใช้บริการ Google Play Games เพื่อลงชื่อเข้าใช้ผู้เล่นในเกม Android ที่สร้างบน Firebase และเขียนด้วย C++ ในการใช้บริการ Google Play Games ลงชื่อเข้าใช้ด้วย Firebase ก่อนอื่นให้ลงชื่อเข้าใช้โปรแกรมเล่นด้วย Google Play Games และขอรหัสตรวจสอบสิทธิ์ OAuth 2.0 เมื่อคุณดำเนินการดังกล่าว จากนั้นส่งรหัสตรวจสอบสิทธิ์ไปที่ PlayGamesAuthProvider เพื่อสร้างข้อมูลรับรอง Firebase ซึ่งคุณใช้ตรวจสอบสิทธิ์กับ Firebase ได้

ก่อนจะเริ่ม

ก่อนที่คุณจะสามารถใช้ Firebase Authentication คุณต้อง:

  • ลงทะเบียนโปรเจ็กต์ C++ ของคุณและกำหนดค่าให้ใช้ Firebase

    หากโปรเจ็กต์ C++ ของคุณใช้ Firebase อยู่แล้ว แสดงว่าได้ลงทะเบียนและกำหนดค่าสำหรับ Firebase แล้ว

  • เพิ่ม Firebase C++ SDK ให้กับโปรเจ็กต์ C++ ของคุณ

โปรดทราบว่าการเพิ่ม Firebase ให้กับโปรเจ็กต์ C++ เกี่ยวข้องกับงานทั้งใน คอนโซล Firebase และในโปรเจ็กต์ C++ ที่เปิดอยู่ (เช่น คุณดาวน์โหลดไฟล์กำหนดค่า Firebase จากคอนโซล จากนั้นจึงย้ายไปยังโปรเจ็กต์ C++)

ตั้งค่าโปรเจ็กต์ Firebase

  1. หากคุณยังไม่ได้ตั้งค่า ให้ตั้งค่าลายนิ้วมือ SHA-1 ของเกมในหน้า การตั้งค่า ของคอนโซล Firebase

    คุณสามารถรับแฮช SHA ของใบรับรองการลงนามด้วยคำสั่ง signingReport :

    ./gradlew signingReport

  2. เปิดใช้งาน Google Play Games เป็นผู้ให้บริการลงชื่อเข้าใช้:

    1. ค้นหารหัสไคลเอ็นต์เว็บเซิร์ฟเวอร์ของโปรเจ็กต์และข้อมูลลับไคลเอ็นต์ รหัสไคลเอ็นต์ของเว็บเซิร์ฟเวอร์ระบุโปรเจ็กต์ Firebase ของคุณไปยังเซิร์ฟเวอร์การตรวจสอบสิทธิ์ของ Google Play

      หากต้องการค้นหาค่าเหล่านี้:

      1. เปิดโปรเจ็กต์ Firebase ในหน้าข้อมูลรับรอง คอนโซล Google APIs
      2. ในส่วน รหัสไคลเอ็นต์ OAuth 2.0 ให้เปิดหน้ารายละเอียด เว็บไคลเอ็นต์ (สร้างอัตโนมัติโดยบริการของ Google) หน้านี้แสดงรายการ ID และข้อมูลลับของไคลเอ็นต์เว็บเซิร์ฟเวอร์ของคุณ
    2. จากนั้น ใน คอนโซล Firebase ให้เปิดส่วนการ ตรวจสอบสิทธิ์

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

กำหนดค่าบริการ Play Games ด้วยข้อมูลแอป Firebase ของคุณ

  1. ใน Google Play Console ให้เปิดแอป Google Play ของคุณหรือสร้างใหม่

  2. ในส่วน เติบโต ให้คลิก บริการ Play Games > การตั้งค่าและการจัดการ > การกำหนดค่า

  3. คลิก ใช่ เกมของฉันใช้ Google API อยู่ แล้ว เลือกโปรเจ็กต์ Firebase ของคุณจากรายการ จากนั้นคลิก ใช้

  4. ในหน้าการกำหนดค่าบริการ Play Games ให้คลิก เพิ่มข้อมูลรับรอง

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

    1. เลือกประเภท Android
    2. ในช่อง ไคลเอ็นต์ OAuth ให้เลือกรหัสไคลเอ็นต์ Android ของโปรเจ็กต์ (หากคุณไม่เห็น ID ไคลเอ็นต์ Android ของคุณ ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าลายนิ้วมือ SHA-1 ของเกมในคอนโซล Firebase)
    3. บันทึกการเปลี่ยนแปลงของคุณ
  6. ในหน้าผู้ ทดสอบ ให้เพิ่มที่อยู่อีเมลของผู้ใช้ที่ต้องการลงชื่อเข้าใช้เกมของคุณก่อนที่จะเผยแพร่ใน Play Store

รวมการลงชื่อเข้าใช้ Play Games เข้ากับเกมของคุณ

ก่อนที่คุณจะสามารถลงชื่อเข้าใช้ผู้เล่นในเกมของคุณ คุณต้องรวมการลงชื่อเข้าใช้ Google Play Games

วิธีที่ง่ายและแนะนำในการเพิ่มการสนับสนุนสำหรับการลงชื่อเข้าใช้ Play Games ในโครงการ C++ Android คือการใช้ Google Sign-in C++ SDK

หากต้องการเพิ่มการลงชื่อเข้าใช้ Play Games ให้กับเกมของคุณโดยใช้ Google Sign-in C++ SDK ให้ทำดังต่อไปนี้:

  1. โคลนหรือดาวน์โหลดที่ เก็บปลั๊กอิน Google Sign-in Unity ซึ่งมี C++ SDK ด้วย

  2. สร้างโปรเจ็กต์ที่มีอยู่ในไดเร็กทอรี staging/native/ ไม่ว่าจะใช้ Android Studio หรือ gradlew build

    บิลด์คัดลอกเอาต์พุตไปยังไดเร็กทอรีชื่อ google-signin-cpp

  3. รวม Google Sign-in C++ SDK ในไฟล์สร้างโค้ดเนทีฟของเกมของคุณ:

    CMake

    ในไฟล์ CMakeLists.txt ระดับบนสุดของคุณ:

    set(GSI_PACKAGE_DIR "/path/to/google-signin-cpp")
    add_library(lib-google-signin-cpp STATIC IMPORTED) set_target_properties(lib-google-signin-cpp PROPERTIES IMPORTED_LOCATION     ${GSI_PACKAGE_DIR}/lib/${ANDROID_ABI}/libgoogle-signin-cpp.a )
    ...
    target_link_libraries(     ...     lib-google-signin-cpp)

    ndk-build

    ในไฟล์ Android.mk ของคุณ:

    include $(CLEAR_VARS)
    LOCAL_MODULE := google-signin-cpp
    GSI_SDK_DIR := /path/to/google-signin-cpp
    LOCAL_SRC_FILES := $(GSI_SDK_DIR)/lib/$(TARGET_ARCH_ABI)/libgoogle-signin-cpp.a
    LOCAL_EXPORT_C_INCLUDES := $(GSI_SDK_DIR)/include
    include $(PREBUILT_STATIC_LIBRARY)
    

  4. ถัดไป รวมคอมโพเนนต์ตัวช่วย Java ซึ่ง C++ SDK ต้องการ

    ในไฟล์ build.gradle ระดับโปรเจ็กต์ของคุณ ให้เพิ่มไดเร็กทอรีเอาต์พุตการสร้าง SDK เป็นที่เก็บในเครื่อง:

    allprojects {
        repositories {
            // ...
            flatDir {
                dirs 'path/to/google-signin-cpp'
            }
        }
    }
    

    และในไฟล์ build.gradle ระดับโมดูลของคุณ ให้ประกาศคอมโพเนนต์ตัวช่วยเป็นการพึ่งพา:

    dependencies {
        implementation 'com.google.android.gms:play-services-auth:20.2.0'
        // Depend on the AAR built with the Google Sign-in SDK in order to add
        // the Java helper classes, which are used by the C++ library.
        compile(name:'google-signin-cpp-release', ext:'aar')
    }
    
  5. จากนั้น ในเกมของคุณ กำหนดค่าอ็อบเจ็กต์ GoogleSignIn เพื่อใช้การลงชื่อเข้าใช้ Play Games และเรียกรหัสการตรวจสอบสิทธิ์ของเซิร์ฟเวอร์:

    #include "google_signin.h"
    #include "future.h"
    
    using namespace google::signin;
    
    // ...
    
    GoogleSignIn::Configuration config = {};
    config.web_client_id = "YOUR_WEB_CLIENT_ID_HERE";
    config.request_id_token = false;
    config.use_game_signin = true;
    config.request_auth_code = true;
    
    GoogleSignIn gsi = GoogleSignIn(GetActivity(), GetJavaVM());
    gsi.Configure(config);
    
  6. สุดท้าย ให้เรียก SignIn() เพื่อลงชื่อเข้าใช้ Play Games:

    Future<GoogleSignIn::SignInResult> &future = gsi.SignIn();
    

    เมื่อ Future ส่งคืนโดย SignIn() คุณสามารถรับรหัสตรวจสอบเซิร์ฟเวอร์จากผลลัพธ์:

    if (!future.Pending()) {
        const GoogleSignIn::StatusCode status =
                static_cast<GoogleSignIn::StatusCode>(future.Status());
        if (status == GoogleSignIn::kStatusCodeSuccess) {
            // Player successfully signed in to Google Play! Get auth code to
            //   pass to Firebase
            const GoogleSignIn::SignInResult result =
                    static_cast<GoogleSignIn::SignInResult>(future.Result());
            const char* server_auth_code = result.User.GetServerAuthCode();
        }
    }
    

ตรวจสอบสิทธิ์ด้วย Firebase

หลังจากที่ผู้เล่นลงชื่อเข้าใช้ Play Games แล้ว คุณจะใช้รหัสตรวจสอบสิทธิ์เพื่อตรวจสอบสิทธิ์กับ Firebase ได้

  1. หลังจากที่ผู้เล่นลงชื่อเข้าใช้ Play Games สำเร็จแล้ว ให้รับรหัสตรวจสอบสิทธิ์สำหรับบัญชีของผู้เล่น

  2. จากนั้น แลกเปลี่ยนรหัสการตรวจสอบสิทธิ์จากบริการ Play Games สำหรับข้อมูลรับรอง Firebase และใช้ข้อมูลรับรอง Firebase เพื่อตรวจสอบสิทธิ์ผู้เล่น:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  3. หากโปรแกรมของคุณมีลูปการอัพเดทที่ทำงานเป็นประจำ (พูดที่ 30 หรือ 60 ครั้งต่อวินาที) คุณสามารถตรวจสอบผลลัพธ์ได้หนึ่งครั้งต่อการอัพเดทด้วย Auth::SignInWithCredentialLastResult :

    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredentialLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        firebase::auth::User* user = *result.result();
        printf("Sign in succeeded for `%s`\n", user->display_name().c_str());
      } else {
        printf("Sign in failed with error '%s'\n", result.error_message());
      }
    }

    หรือหากโปรแกรมของคุณเป็นแบบขับเคลื่อนด้วยเหตุการณ์ คุณอาจต้องการ ลงทะเบียนการโทรกลับในอนาคต

ลงทะเบียนโทรกลับในอนาคต

บางโปรแกรมมีฟังก์ชัน Update ที่เรียกว่า 30 หรือ 60 ครั้งต่อวินาที ตัวอย่างเช่น หลายเกมตามรุ่นนี้ โปรแกรมเหล่านี้สามารถเรียกใช้ฟังก์ชัน LastResult เพื่อสำรวจการโทรแบบอะซิงโครนัสได้ อย่างไรก็ตาม หากโปรแกรมของคุณเป็นแบบขับเคลื่อนด้วยเหตุการณ์ คุณอาจต้องการลงทะเบียนฟังก์ชันเรียกกลับ ฟังก์ชันเรียกกลับถูกเรียกเมื่อเสร็จสิ้นอนาคต
void OnCreateCallback(const firebase::Future<firebase::auth::User*>& result,
                      void* user_data) {
  // The callback is called when the Future enters the `complete` state.
  assert(result.status() == firebase::kFutureStatusComplete);

  // Use `user_data` to pass-in program context, if you like.
  MyProgramContext* program_context = static_cast<MyProgramContext*>(user_data);

  // Important to handle both success and failure situations.
  if (result.error() == firebase::auth::kAuthErrorNone) {
    firebase::auth::User* user = *result.result();
    printf("Create user succeeded for email %s\n", user->email().c_str());

    // Perform other actions on User, if you like.
    firebase::auth::User::UserProfile profile;
    profile.display_name = program_context->display_name;
    user->UpdateUserProfile(profile);

  } else {
    printf("Created user failed with error '%s'\n", result.error_message());
  }
}

void CreateUser(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::User*> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // `&my_program_context` is passed verbatim to OnCreateCallback().
  result.OnCompletion(OnCreateCallback, &my_program_context);
}
ฟังก์ชันเรียกกลับสามารถเป็นแลมบ์ดาได้ ถ้าคุณต้องการ
void CreateUserUsingLambda(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::User*> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // The lambda has the same signature as the callback function.
  result.OnCompletion(
      [](const firebase::Future<firebase::auth::User*>& result,
         void* user_data) {
        // `user_data` is the same as &my_program_context, below.
        // Note that we can't capture this value in the [] because std::function
        // is not supported by our minimum compiler spec (which is pre C++11).
        MyProgramContext* program_context =
            static_cast<MyProgramContext*>(user_data);

        // Process create user result...
        (void)program_context;
      },
      &my_program_context);
}

ขั้นตอนถัดไป

หลังจากที่ผู้ใช้ลงชื่อเข้าใช้เป็นครั้งแรก บัญชีผู้ใช้ใหม่จะถูกสร้างขึ้นและเชื่อมโยงกับรหัส Play Games ของพวกเขา บัญชีใหม่นี้จัดเก็บเป็นส่วนหนึ่งของโปรเจ็กต์ Firebase และใช้เพื่อระบุผู้ใช้ในทุกแอปในโปรเจ็กต์ของคุณ

ในเกมของคุณ คุณสามารถรับ Firebase UID ของผู้ใช้ได้จาก firebase::auth::User object:

firebase::auth::User* user = auth->current_user();
if (user != nullptr) {
  std::string playerName = user->displayName();

  // The user's ID, unique to the Firebase project.
  // Do NOT use this value to authenticate with your backend server,
  // if you have one. Use firebase::auth::User::Token() instead.
  std::string uid = user->uid();
}

ในฐานข้อมูล Firebase Realtime Database และ Cloud Storage Security Rules คุณสามารถรับ ID ผู้ใช้เฉพาะของผู้ใช้ที่ลงชื่อเข้าใช้จากตัวแปร auth และใช้เพื่อควบคุมข้อมูลที่ผู้ใช้สามารถเข้าถึงได้

หากต้องการรับข้อมูลผู้เล่น Play Games ของผู้ใช้หรือเพื่อเข้าถึงบริการ Play Games ให้ใช้ API ที่จัดหาโดยบริการ Google Play Games C++ SDK

หากต้องการออกจากระบบผู้ใช้ โทร SignOut() :

auth->SignOut();