Xác thực Sử dụng Dịch vụ Trò chơi của Google Play với C ++

Bạn có thể sử dụng dịch vụ Google Play Trò chơi để đăng nhập người chơi vào trò chơi Android được xây dựng trên Firebase và được viết bằng C ++. Để sử dụng các dịch vụ của Google Play Trò chơi, hãy đăng nhập bằng Firebase, trước tiên hãy đăng nhập vào trình phát bằng Google Play Trò chơi và yêu cầu mã xác thực OAuth 2.0 khi bạn làm như vậy. Sau đó, chuyển mã xác thực cho PlayGamesAuthProvider để tạo thông tin xác thực Firebase, bạn có thể sử dụng thông tin này để xác thực với Firebase.

Trước khi bắt đầu

Trước khi có thể sử dụng Xác thực Firebase , bạn cần:

  • Đăng ký dự án C ++ của bạn và định cấu hình nó để sử dụng Firebase.

    Nếu dự án C ++ của bạn đã sử dụng Firebase, thì dự án đó đã được đăng ký và định cấu hình cho Firebase.

  • Thêm Firebase C ++ SDK vào dự án C ++ của bạn.

Lưu ý rằng việc thêm Firebase vào dự án C ++ của bạn liên quan đến các tác vụ trong bảng điều khiển Firebase và trong dự án C ++ đang mở của bạn (ví dụ: bạn tải xuống tệp cấu hình Firebase từ bảng điều khiển, sau đó di chuyển chúng vào dự án C ++ của bạn).

Thiết lập dự án Firebase của bạn

  1. Nếu bạn chưa đặt, hãy đặt vân tay SHA-1 cho trò chơi của bạn trong trang Cài đặt của bảng điều khiển Firebase.

    Bạn có thể lấy mã băm SHA của chứng chỉ ký của mình bằng lệnh signingReport :

    ./gradlew signingReport

  2. Bật Google Play Trò chơi với tư cách là nhà cung cấp dịch vụ đăng nhập:

    1. Tìm ID ứng dụng khách máy chủ web của dự án và bí mật của ứng dụng khách. ID ứng dụng khách của máy chủ web xác định dự án Firebase của bạn với các máy chủ xác thực của Google Play.

      Để tìm các giá trị này:

      1. Mở dự án Firebase của bạn trong trang thông tin đăng nhập bảng điều khiển API của Google .
      2. Trong phần ID ứng dụng khách OAuth 2.0 , hãy mở trang chi tiết về ứng dụng khách Web (do Dịch vụ của Google tạo tự động) . Trang này liệt kê bí mật và ID ứng dụng khách máy chủ web của bạn.
    2. Sau đó, trong bảng điều khiển Firebase , hãy mở phần Xác thực .

    3. Trên tab Phương thức đăng nhập, hãy bật nhà cung cấp dịch vụ đăng nhập Play Trò chơi . Bạn sẽ cần chỉ định ID ứng dụng khách máy chủ web và bí mật ứng dụng khách của dự án mà bạn nhận được từ bảng điều khiển API.

Định cấu hình dịch vụ Play Trò chơi bằng thông tin ứng dụng Firebase của bạn

  1. Trong Google Play Console , hãy mở ứng dụng Google Play của bạn hoặc tạo một ứng dụng.

  2. Trong phần Phát triển , nhấp vào Dịch vụ Play Trò chơi> Thiết lập & Quản lý> Cấu hình .

  3. Nhấp vào Có, trò chơi của tôi đã sử dụng các API của Google , hãy chọn dự án Firebase của bạn từ danh sách, sau đó nhấp vào Sử dụng .

  4. Trên trang cấu hình dịch vụ Play Trò chơi, nhấp vào Thêm thông tin đăng nhập .

    1. Chọn loại máy chủ trò chơi .
    2. Trong trường ứng dụng khách OAuth , hãy chọn ID ứng dụng khách web của dự án của bạn. Đảm bảo rằng đây là cùng một ID khách hàng mà bạn đã chỉ định khi bật đăng nhập Play Trò chơi.
    3. Lưu các thay đổi của bạn.
  5. Vẫn trên trang cấu hình dịch vụ Play Trò chơi, nhấp lại vào Thêm thông tin đăng nhập.

    1. Chọn loại Android .
    2. Trong trường ứng dụng khách OAuth , hãy chọn ID ứng dụng khách Android của dự án của bạn. (Nếu bạn không thấy ID ứng dụng khách Android của mình, hãy đảm bảo bạn đã đặt tệp tham chiếu SHA-1 của trò chơi trong bảng điều khiển Firebase.)
    3. Lưu các thay đổi của bạn.
  6. Trên trang Người thử nghiệm , hãy thêm địa chỉ email của bất kỳ người dùng nào cần để có thể đăng nhập vào trò chơi của bạn trước khi bạn phát hành trò chơi đó trên Cửa hàng Play.

Tích hợp đăng nhập Play Trò chơi vào trò chơi của bạn

Trước khi bạn có thể đăng nhập người chơi vào trò chơi của mình, bạn phải tích hợp đăng nhập Google Play Trò chơi.

Cách dễ nhất và được đề xuất để thêm hỗ trợ đăng nhập Play Trò chơi vào dự án C ++ Android là sử dụng SDK đăng nhập C ++ của Google .

Để thêm đăng nhập Play Trò chơi vào trò chơi của bạn bằng SDK đăng nhập C ++ của Google, hãy làm như sau:

  1. Sao chép hoặc tải xuống kho lưu trữ plugin Unity Đăng nhập Google , cũng chứa C ++ SDK.

  2. Xây dựng dự án có trong thư mục staging/native/ , sử dụng Android Studio hoặc gradlew build .

    Bản dựng sao chép đầu ra của nó vào một thư mục có tên google-signin-cpp .

  3. Bao gồm SDK C ++ đăng nhập Google trong tệp tạo mã gốc của trò chơi của bạn:

    CMake

    Trong tệp CMakeLists.txt cấp cao nhất của bạn:

    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

    Trong tệp Android.mk của bạn:

    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. Tiếp theo, bao gồm thành phần trình trợ giúp Java, được yêu cầu bởi C ++ SDK.

    Để làm như vậy, trong tệp build.gradle cấp dự án của bạn, hãy thêm thư mục đầu ra bản dựng SDK làm kho lưu trữ cục bộ:

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

    Và, trong tệp build.gradle cấp mô-đun của bạn, hãy khai báo thành phần trợ giúp dưới dạng phụ thuộc:

    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. Sau đó, trong trò chơi của bạn, hãy định cấu hình đối tượng GoogleSignIn để sử dụng đăng nhập Play Trò chơi và để truy xuất mã xác thực máy chủ:

    #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. Cuối cùng, gọi SignIn() để đăng nhập người chơi vào Play Trò chơi:

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

    Khi Tương lai do SignIn() trả về giải quyết, bạn có thể lấy mã xác thực máy chủ từ kết quả:

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

Xác thực bằng Firebase

Sau khi người chơi đăng nhập bằng Play Trò chơi, bạn có thể sử dụng mã xác thực để xác thực với Firebase.

  1. Sau khi người chơi đăng nhập thành công bằng Play Trò chơi, hãy nhận mã xác thực cho tài khoản của người chơi.

  2. Sau đó, trao đổi mã xác thực từ các dịch vụ Play Trò chơi để lấy thông tin đăng nhập Firebase và sử dụng thông tin đăng nhập Firebase để xác thực người chơi:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  3. Nếu chương trình của bạn có vòng lặp cập nhật chạy thường xuyên (giả sử ở tốc độ 30 hoặc 60 lần mỗi giây), bạn có thể kiểm tra kết quả mỗi lần cập nhật với 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());
      }
    }

    Hoặc, nếu chương trình của bạn theo hướng sự kiện, bạn có thể muốn đăng ký một cuộc gọi lại trong Tương lai .

Đăng ký cuộc gọi lại trong tương lai

Một số chương trình có chức năng Update được gọi là 30 hoặc 60 lần mỗi giây. Ví dụ, nhiều trò chơi theo mô hình này. Các chương trình này có thể gọi các hàm LastResult để thăm dò ý kiến ​​của các cuộc gọi không đồng bộ. Tuy nhiên, nếu chương trình của bạn theo hướng sự kiện, bạn có thể thích đăng ký các hàm gọi lại. Một hàm gọi lại được gọi khi hoàn thành Tương lai.
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);
}
Hàm gọi lại cũng có thể là một lambda, nếu bạn thích.
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);
}

Bước tiếp theo

Sau khi người dùng đăng nhập lần đầu tiên, một tài khoản người dùng mới sẽ được tạo và liên kết với ID Play Trò chơi của họ. Tài khoản mới này được lưu trữ như một phần của dự án Firebase của bạn và có thể được sử dụng để xác định người dùng trên mọi ứng dụng trong dự án của bạn.

Trong trò chơi của mình, bạn có thể lấy UID Firebase của người dùng từ 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();
}

Trong Cơ sở dữ liệu thời gian thực Firebase và Quy tắc bảo mật lưu trữ đám mây, bạn có thể lấy ID người dùng duy nhất của người dùng đã đăng nhập từ biến auth và sử dụng nó để kiểm soát dữ liệu nào mà người dùng có thể truy cập.

Để nhận thông tin trình phát Play Trò chơi của người dùng hoặc truy cập các dịch vụ Play Trò chơi, hãy sử dụng các API được cung cấp bởi SDK C ++ của các dịch vụ Google Play Trò chơi .

Để đăng xuất một người dùng, hãy gọi SignOut() :

auth->SignOut();