跳轉至

登录注销

登入驗證包括以下步驟。

Note
  • SDK 4.7.0 以下的版本不支持 Helper。请参考 [以下内容] 了解现有的登录应用程序方法。
  • 有关 AuthV4.Helper 的描述,请参考 身份验证 页面。

登入

登入驗證包括以下步驟。

  1. 自動登入和隱式登入
  2. 顯式登入
  3. 檢查 IdP 帳戶在設備上是否已登入
  4. 訪客登入

Authv4Helper 是一个执行与登录相关的一系列过程的类,并根据响应值配置为导航到适当的屏幕。 配置登录时,请参考以下几点。

Note

Apple 不支持 iOS 企业版本中的 Apple Game Center 和应用内购买。因此,在 iOS 企业版本中无法使用 Apple Game Center 账户的隐式登录,显式登录也无法使用 Apple Game Center。当为 iOS 企业构建时,控制台中的 登录类型 不能包含 Apple Game Center。

Note
  • 如果遊戲主要針對13歲以下的兒童,則無法應用Google Play遊戲服務,並且在Google構建中無法使用隱式登錄。欲了解更多信息,請參閱Google Play遊戲服務質量檢查清單
Note
  • 在中國,Google Play 遊戲無法使用,因此在 Android 上無法使用隱式登錄。
  • 在中國,Facebook 無法使用,因此 Facebook 不在 IdP 列表中。
  • 在中國,只有經過實名認證的用戶才能充值或消費服務(自 2017 年 5 月 1 日起生效),因此來自中國 IP 的登錄不包括訪客登錄在 IdP 列表中。
Note

iOS 即使在取消 Apple Game Center 登入的情況下也不會顯示登入畫面。因此,指導訊息可以由 SDK 直接顯示,通過調用 AuthV4Helper 類的 showGameCenterLoginCancelDialog() 方法,或者由遊戲選擇顯示。如果您想為用戶提供重新連接其 Game Center 帳戶的訊息,當 AuthV4.signIn(AuthV4.ProviderType.APPLE, ...)AuthV4.connect(AuthV4.ProviderType.APPLE, ...) 的回調結果為取消時,請使用 Game Center 取消指導訊息

Note

如果用户尝试在未使用 Apple ID 登录的设备上使用 Apple 登录,则在调用 AuthV4Helper 类的 connect()signIn() 方法的过程中会发生 AuthV4SignInAppleUnknown 错误 这里。Apple ID 登录指导弹出窗口会自动显示,因此游戏工作室无需显示单独的指导弹出窗口。

如果用户尝试使用 Apple 登录,而他们的设备没有使用 Apple ID 登录,则在调用 AuthV4Helper 类的 connect()signIn() 方法 的过程中会发生 AuthV4SignInAppleUnknown 错误。Apple ID 登录指导弹出窗口会自动显示,因此游戏工作室不需要显示单独的 弹出窗口 进行指导。

Note

對於 PC X IdP 登入,可以使用 X 帳戶登入,但在 X 登入畫面上不支援使用 Google 和 Apple 帳戶整合登入。 要使用 Google 或 Apple 帳戶整合登入 X,您必須先在外部瀏覽器中使用相應的帳戶登入,然後在遊戲中進行 X 登入。
對於 Steam Deck X IdP 登入,僅支援使用 X 帳戶登入。

自動登入和隱式登入

自動登入

這是指用戶未選擇登錄方法的登錄方式,在iOS上,它自動鏈接到Apple遊戲中心賬戶,而在Android上,它鏈接到Google Play遊戲賬戶。它實現自動登錄,並在自動登錄失敗的情況下執行隱式登錄。

要在 iOS 環境中使用自動登錄,您需要添加 Game Center 權限,Unity 會通過 Unity PostProcess 自動添加此權限,前提是您勾選了「Apple GameCenter」依賴項。在 iOS 原生環境中,Xcode 會自動添加 Game Center 權限。

離線模式

在 Hive SDK v4 23.1.0 及以上版本中,即使在应用程序启动时用户设备未连接到网络,也可以提供自动登录功能(AuthV4.signIn 使用 ProviderType.AUTO,或 AuthV4.Helper.signIn)。要使用离线模式,请按照以下说明进行操作。

  1. 您必須成功在線執行應用程式以進行明確、隱式、訪客或自定義登錄,並收到 playerIdplayerToken

从应用程序开发者的角度来看,必须至少在线成功执行过一次 AuthV4.Helper.signInAuthV4.showSignInAuthV4.signInWithAuthKey,才能通过回调接收 playerIdplayerToken。从用户的角度来看,用户必须在设备连接到网络时至少成功登录过一次应用程序。然而,如果用户的账户在上次在线登录尝试时被暂停或限制,用户即使在离线模式下也无法登录。

  1. 在 Hive 控制台中激活离线模式 应用中心 > 项目管理 > 游戏详情 > Hive 产品设置
Note

若要在離線模式下為 Android 作業系統設備的用戶提供隱式 Google 登入,請參考 以下內容

在 Windows 環境中的自動登入

Windows 環境也支持自動登入,可以在 Hive 控制台應用中心 中啟用/禁用。然而,Windows 中的自動登入行為與移動設備不同。以下是 Windows 中自動登入的差異。

  • 在移动设备上,登录后,登录状态始终通过自动登录保持,但在Windows上,仅当用户激活“保持我登录”复选框(在登录UI中的IdP列表底部显示)时,登录状态才会保持。在其他情况下,登录状态不会保持。
  • 当执行 AuthV4Helper.Connect 时,在移动设备上,如果切换到新帐户,新帐户也会保持自动登录状态,但在Windows上,如果切换到新帐户,新帐户将不会保持自动登录状态。

隱式登錄

  • 隱式登入流程

AuthV4.Helper.signIn 嘗試使用 PlayerID 的身份驗證令牌金鑰自動登錄。如果沒有現有的身份驗證令牌金鑰,它會自動登錄到 iOS 的 Apple Game Center 和 Android 的 Google Play Games。如果登錄失敗,它會根據響應值配置適當的登錄畫面。

Note

要使用自動登錄,您必須添加 Game Center 權限。如果您檢查了 'Apple GameCenter' 依賴項,它將通過 Unity PostProcess 自動添加相應的權限。

Note

使用 AuthV4Helper 類別時

如果已啟動遊戲的用戶在 PGS 期間拒絕隱式登錄嘗試,系統將記住這一點,並不再嘗試隱式登錄。即使在玩家會話保持的情況下可以自動登錄,它仍將繼續記住拒絕隱式登錄的狀態。這些內容基於 Google Play 遊戲服務指南。

以下是執行自動登錄的示例代碼。

API 參考: hive.AuthV4.Helper.signIn

// 嘗試使用 Hive SDK 登入 (signIn)
AuthV4.Helper.signIn (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {

    if (result.isSuccess()) {
        // 登录成功
    } else if (result.needExit()) {
        // TODO: 实现应用退出功能
        // 例如:Application.Quit();
    } else {
        switch (result.code) {
            case ResultAPI.Code.AuthV4ConflictPlayer:
                // 账户冲突
                break;
            case ResultAPI.Code.AuthV4HelperImplifiedLoginFail:
                // 隐式登录失败
                // 例如)AuthV4.showSignIn(...);
                break;
            default:
  k              // 其他异常
                break;
        }
    }
});
#include "HiveAuthV4.h"

// 嘗試登錄 (signIn) 到 Hive SDK
FHiveAuthV4::Helper::SignIn(FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& PlayerInfo) {
    if (Result.IsSuccess()) {
        // 登錄成功
    } else if (Result.NeedExit()) {
        // TODO: 實現應用程序退出功能
        // 例如) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
    } else {
        switch (Result.Code) {
            case FHiveResultAPI::ECode::AuthV4ConflictPlayer:
                // 帳戶衝突
                break;
            case FHiveResultAPI::ECode::AuthV4HelperImplifiedLoginFail:
                // 隱式登錄失敗
                // 例如) FHiveAuthV4::ShowSigIn()
                break;
            default:
                // 其他異常
                break;
        }
    }
}));

API 參考: Auth4::Helper::signIn

// 使用 Hive SDK 嘗試登錄 (signIn)
AuthV4::Helper::signIn([=](ResultAPI const & result, std::shared_ptr playerInfo) {

    if (result.isSuccess()) {
        // 登录成功
    } else if (result.needExit()) {
        // TODO: 实现应用程序退出功能
        // 对于 Cocos2d-x 引擎用户
        // 例如 exit(0);
        // 对于 Unreal 引擎用户
        // 例如 UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
    } else {
        switch (result.code) {
            case ResultAPI::AuthV4ConflictPlayer:
                // 账户冲突
                break;
            case ResultAPI::AuthV4HelperImplifiedLoginFail:
                // 隐式登录失败
                // 例如 AuthV4.showSignIn(...);
                break;
            default:
                break;
        }
    }
});

API 參考: hive.AuthV4.Helper.signIn

// 嘗試使用 Hive SDK 登入
AuthV4.Helper.signIn(object : AuthV4.Helper.AuthV4HelperListener {
    override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // 登入成功
        } else if (result.needExit()) {
            // TODO: 實現應用程式退出功能
            // e.g.) exitProcess(0)
        } else {
            when (result.code) {
                ResultAPI.Code.AuthV4ConflictPlayer -> {
                    // 帳戶衝突
                }
                ResultAPI.Code.AuthV4HelperImplifiedLoginFail -> {
                    // 隱式登入失敗
                    // e.g.) AuthV4.showSignIn(...)
                }
                else -> {
                    // 其他異常情況
                }
            }
        }
    }
})

API 參考: com.hive.AuthV4.Helper.signIn

// Hive SDK AuthV4 authentication UI request
AuthV4.Helper.signIn(new AuthV4.Helper.AuthV4HelperListener() {
    @Override
    public void onAuthV4Helper(ResultAPI result, PlayerInfo playerInfo) {

        if (result.isSuccess()) {
            // 認證成功
        } else if (result.needExit()) {
            // TODO: 實現應用程式退出功能
            // 例如)System.exit(0);
        } else {
            switch (result.code) {
                case ResultAPI.Code.AuthV4ConflictPlayer:
                    // 帳戶衝突
                    break;
                case ResultAPI.Code.AuthV4HelperImplifiedLoginFail:
                    // 隱式登錄失敗
                    // 例如)AuthV4.showSignIn(...);
                    break;
                default:
                    // 其他異常情況
                    break;    
            }
        }
    }
});

API 參考: HIVEAuthV4Helper:signIn

// Hive SDK AuthV4 authentication UI request
AuthV4Interface.helper().signIn { (result, playerInfo) in

    if result.isSuccess() {
        // 認證成功
    } else if result.needExit() {
        // TODO: 實現應用程序退出功能
        // e.g.) exit(0)
    } else {
        switch result.getCode() {
            case .authV4ConflictPlayer:
                // 帳戶衝突
                break
            case .authV4HelperImplifiedLoginFail:
                // 隱式登錄失敗
                // ex) AuthV4.showSignIn(...)
                break
            default:
                // 其他異常情況
                break
            }
        }
    }
}

API 參考: HIVEAuthV4:signIn

// 嘗試登錄 (signIn) 到 Hive SDK    
[[HIVEAuthV4 helper] signIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {

    if (result.isSuccess) {
        // 登录成功 
    }
    else if (result.needExit) {
        // TODO: 实现应用退出功能
        // ex) exit(0);
    }
    else {
        switch (result.code) {
            case kAuthV4ConflictPlayer:
                // 账户冲突
                break;    
            case kAuthV4HelperImplifiedLoginFail:
                // 隐式登录失败
                // ex) [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
                // // 做一些事情...
                // }];
                break;
            default:
                // 其他异常
                break;   
        }
    }
}];

隱式登錄行為:移動

移動設備的隱式登錄(Hive SDK Unity Android 等 Android/iOS 平台)(AuthV4.Helper.signIn) 在初次登錄後使用不同帳戶登錄時會導致帳戶衝突情況,返回結果代碼 AuthV4ConflictPlayer,並會提示用戶一個對話框,詢問是否使用最後登錄的帳戶進行登錄(AuthV4.Helper.showConflict 執行)。


然而,Android 移动环境中的隐式 Google 登录行为如下所示。


在 Android 移动环境中,Google 登录的隐式登录返回成功或失败,而不会导致帐户冲突(AuthV4ConflictPlayer),与其他移动环境不同。在上面的图像中,传统支持 Google 身份验证 指的是 Android 移动环境中 Google 登录的隐式登录。

成功登入後,如果用戶嘗試IdP整合或呼叫Google成就和排行榜,將顯示一個用於選擇Google帳戶的UI(創建新的登入會話)。如果檢查已登入帳戶的PlayerInfo,而新選擇的Google帳戶與此信息不同,將發生帳戶衝突(AuthV4ConflictPlayer)。此時,如果您處理帳戶衝突情況,您可以使用新選擇的Google帳戶登入。


在沒有現有登錄會話的情況下(例如,當應用程序首次安裝和運行時),Android 移動環境中的 Google 登錄隱式登錄根據情況表現不同,如下所示。

  1. 在 Android 操作系統設備的帳戶設置中存在一個已登錄應用的 Google 帳戶的情況(Google 帳戶已登錄到 Android 操作系統設備的情況)
    • 使用 Google 帳戶登錄
  2. 在 Android 操作系統設備的帳戶設置中存在兩個或更多已登錄應用的 Google 帳戶的情況(特定 Google 帳戶已登錄到 Android 操作系統設備的情況)
    • 顯示一個 UI 以選擇已登錄的 Google 帳戶之一
    • 從 UI 中選擇帳戶後登錄
    • 如果用戶在未選擇任何 Google 帳戶的情況下關閉 UI,則顯示包含 Android 操作系統設備帳戶設置中所有 Google 帳戶的列表的 UI
    • 如果用戶從所有 Google 帳戶 UI 的列表中選擇所需的 Google 帳戶,則使用該帳戶登錄
  3. 沒有 Google 帳戶登錄到應用的情況
    • 顯示包含 Android 操作系統設備帳戶設置中所有 Google 帳戶的列表的 UI
    • 如果用戶從所有 Google 帳戶 UI 的列表中選擇所需的 Google 帳戶,則使用該帳戶登錄


下圖顯示了上述三種情況的 UI 範例。從左側開始,它們分別對應於情況 1、2 和 3。

Note

有關 Google 認證的更多資訊,請參閱 Google Credential Manager

隱式登錄行為:PC

在PC(如Hive SDK Unity Windows等Windows平台)上的隱式登錄(AuthV4.Helper.signIn)在初次登錄後使用不同帳戶登錄時,會自動使用最後登錄的帳戶進行登錄。將不會出現帳戶衝突的情況。

明確登錄

明確登錄是指用戶選擇身份提供者(IdP)進行身份驗證的過程。如果自動登錄和隱式登錄都失敗,則實現當用戶在移動到遊戲標題屏幕後點擊標題時執行明確登錄。

顯式登錄 UI 可以使用 Hive SDK 提供的 UI,也可以使用 Hive SDK 初始化完成後返回的 IdP 列表進行自定義。如果您正在自定義 UI,請參考 顯式登錄自定義 部分。

身份提供者列表由Hive平台根据各国的政策进行控制和提供。例如,在中国,Google Play游戏和Facebook对访客不可用。

明確的登錄截圖

由 SDK 提供的 IdP 選擇 UI

使用 SDK 提供的 UI 进行实现时

要使用 SDK 提供的 UI 實現明確登錄,您可以簡單地調用 showSignIn() 方法來調用 IdP 列表 UI。

Note

用戶必須提供再次登錄的方式,如果他們在 SDK 提供的 IdP 選擇 UI 中關閉 'X' 按鈕。用戶仍然沒有登錄。

Note

要自訂明確的登入,請參考以下內容

API 參考: hive.AuthV4.showSignIn

// Hive SDK AuthV4 認證 UI 請求
AuthV4.showSignIn((ResultAPI result, AuthV4.PlayerInfo playerInfo)=>{
    if (result.isSuccess()) {
        // 認證成功
        // playerInfo : 已認證的用戶信息

        // 獲取電子郵件信息的示例
        foreach (KeyValuePair<AuthV4.ProviderType, AuthV4.ProviderInfo> entry in playerInfo.providerInfoData) {

            AuthV4.ProviderInfo providerInfo = entry.Value;
            if(providerInfo.providerEmail != null && providerInfo.providerEmail != "") {
                string email = providerInfo.providerEmail;
                break;
            }
        }
    }
    else if (result.needExit()) {
        // TODO: Implement the app exit functionality
        // e.g.) Application.Quit();
    }
});
#include "HiveAuthV4.h"

// Hive SDK AuthV4 認證 UI 請求
FHiveAuthV4::ShowSignIn(FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {
    if (Result.IsSuccess()) {
        // 認證成功 (PlayerInfo: 已認證的用戶信息) 

        // 取得電子郵件資訊的範例
        for (const auto& ProviderInfoEntry : PlayerInfo.ProviderInfoData) {
            FHiveProviderInfo ProviderInfo = ProviderInfoEntry.Value;
            FString Email = ProviderInfo.ProviderEmail;
        }
    } else if (Result.NeedExit()) {
        // TODO: 實作應用程式退出功能
        // 範例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
    }
}));

API 參考: AuthV4::showSignIn

// Hive SDK AuthV4 authentication UI request
AuthV4::showSignIn([=](ResultAPI const & result, PlayerInfo const & playerInfo) {
    if (result.isSuccess()) {
        // Authentication successful
        // playerInfo: authenticated user information

        // 獲取電子郵件信息的示例
        for(auto it = playerInfo.providerInfoData.begin(); it != playerInfo.providerInfoData.end(); ++it) {
            hive::ProviderInfo providerInfo = it->second;
            if(!providerInfo.providerEmail.empty()) {
                std::string email = providerInfo.providerEmail;
                break;
            }
        }
    }
    else if (result.needExit()) {
        // TODO: 實現應用退出功能
        // Cocos2d-x 引擎用戶
        // 示例) exit(0);
        // Unreal 引擎用戶
        // 示例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
    }
});

API 參考: com.hive.AuthV4.showSignIn

// Hive SDK AuthV4 認證 UI 請求
AuthV4.showSignIn(object : AuthV4.AuthV4SignInListener {
    override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // 認證成功
            // playerInfo: 已認證的用戶信息

            // 取得電子郵件資訊的範例
            playerInfo?.let {
                for ((key, value) in it.providerInfoData) {
                    var providerInfo: AuthV4.ProviderInfo = value
                    if(providerInfo.providerEmail.isNotEmpty()) {
                        val email = providerInfo.providerEmail
                        break
                    }
                }
            }
        } else if (result.needExit()) {
            // TODO: 實現應用程式退出功能
            // e.g.) exitProcess(0)
        }
    }
})

API 參考: com.hive.AuthV4.showSignIn

// Hive SDK AuthV4 authentication UI request
AuthV4.showSignIn(new AuthV4.AuthV4SignInListener() {
    @Override
    public void onAuthV4SignIn(ResultAPI result, AuthV4.PlayerInfo playerInfo) {

        if (result.isSuccess()) {
            // 認證成功
            // playerInfo: 已認證的用戶信息

            // 獲取電子郵件信息的示例
            if(playerInfo != null) {
                for (Map.Entry<AuthV4.ProviderType, AuthV4.ProviderInfo> entry : playerInfo.getProviderInfoData().entrySet()) {
                    AuthV4.ProviderInfo providerInfo = entry.getValue();
                    if (providerInfo.getProviderEmail() != "") {
                        String email = providerInfo.getProviderEmail();
                        break;
                    }
                }
            }
        }
        else if (result.needExit()) {
            // TODO: 實現應用程序退出功能
            // e.g. System.exit(0);
        }
    }
});

API 參考: HIVEAuthV4:showSignIn

var email = String()

// Hive SDK AuthV4 認證 UI 請求
AuthV4Interface.showSignIn { (result, playerInfo) in

    if result.isSuccess() {
        // 認證成功
        // playerInfo: 已認證的用戶信息

        // 獲取電子郵件信息的示例
        if let playerInfo = playerInfo {
            // 搜索 providerInfo,其中 providerEmail 存在(當前登錄的提供者)
            for key in playerInfo.providerInfoData.keys {
                if let providerInfo = playerInfo.providerInfoData[key],
                    providerInfo.providerEmail.count > 0 {
                    // providerEmail != ""
                    email = providerInfo.providerEmail
                    break
                }
            }
        }
    } else if result.needExit() {
        // TODO: 實現應用程序退出功能
        // 例如:exit(0)
    }
}

API 參考: HIVEAuthV4:showSignIn

__block NSString* email = @"";

// Hive SDK AuthV4 認證 UI 請求
[HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {

    if([result isSuccess]){
        // 認證成功
        // playerInfo: 已認證的用戶信息

        // 獲取電子郵件信息的示例
        if(playerInfo != nil) {
            // 搜索具有現有 providerEmail(當前登錄的提供者)的 providerInfo
            for (NSString* key in playerInfo.providerInfoData.allKeys) {
                HIVEProviderInfo* providerInfo = playerInfo.providerInfoData[key];
                if (providerInfo != nil && providerInfo.providerEmail.length > 0) {
                    // providerEmail != ""
                    email = providerInfo.providerEmail;
                    break;
                }
            }
        }
    } else if ([result needExit]) {
        // TODO: 實現應用退出功能
        // 例如:exit(0);
    }
}];


當沒有現有的登錄會話(例如,當應用程序首次安裝並運行時),在 Android 移動環境中的顯式 Google 登錄根據情況的不同而表現出不同的行為,如下所示。

  1. 在 Android 操作系統設備的帳戶設定中存在一個 Google 帳戶登錄到應用程序的情況(Google 帳戶登錄到 Android 操作系統設備的情況)
    • 使用相應的 Google 帳戶登錄
  2. 在 Android 操作系統設備的帳戶設定中存在兩個或更多 Google 帳戶登錄到應用程序的情況(特定 Google 帳戶登錄到 Android 操作系統設備的情況)
    • 顯示一個 UI 以選擇已登錄的 Google 帳戶之一
    • 從 UI 中選擇帳戶後登錄
    • 如果用戶在未選擇任何 Google 帳戶的情況下關閉 UI,則顯示一個 UI,列出 Android 操作系統設備帳戶設定中所有 Google 帳戶
    • 當用戶從所有 Google 帳戶的列表 UI 中選擇所需的 Google 帳戶時,使用該帳戶登錄
  3. 沒有 Google 帳戶登錄到應用程序的情況
    • 顯示一個 UI,列出 Android 操作系統設備帳戶設定中所有 Google 帳戶
    • 當用戶從所有 Google 帳戶的列表 UI 中選擇所需的 Google 帳戶時,使用該帳戶登錄


下圖是上述三種情況的用戶界面示例。從左側開始,分別對應情況1、2和3。

Note

有關 Google 認證的更多信息,請參閱 Google Credential Manager

明確的登錄自定義

可自訂的明確登錄用戶界面可以使用 providerTypeList 實現。當調用 AuthV4.setup() 方法以初始化 Hive SDK,或在初始化後調用 AuthV4.Helper.getIDPList() 方法時,providerTypeList 是返回的響應回調處理程序。當您希望根據遊戲用戶界面顯示登錄屏幕或主要暴露與特定身份提供者的集成時,將使用此功能。在實現可自訂的用戶界面後,根據用戶的操作調用 signIn() 方法,並使用所需的 ProviderType 來實現登錄。

Note
  • UI範例截圖顯示登錄屏幕上的Facebook集成按鈕

以下是一段示例源代码,假设用户在自定义的显式登录用户界面中选择了 Google 登录。

API 參考: hive.AuthV4.signIn

using hive;

AuthV4.signIn(AuthV4.ProviderType.GOOGLE, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => {
    if (result.isSuccess()) {
        // 呼叫成功
        // playerInfo : 認證用戶信息。
        // 取得ProviderType.GOOGLE的電子郵件信息的範例
        Dictionary<AuthV4.ProviderType, AuthV4.ProviderInfo> providerInfoData = playerInfo.providerInfoData;
        AuthV4.ProviderInfo providerInfo = providerInfoData[AuthV4.ProviderType.GOOGLE];
        string email = providerInfo.providerEmail;
    }
});
#include "HiveAuthV4.h"

FHiveAuthV4::SignIn(EHiveProviderType::GOOGLE,
                    FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {

    if (Result.IsSuccess()) {
        // 呼叫成功 (PlayerInfo: 已驗證的用戶信息) 

        // 取得 EHiveProviderType::GOOGLE 的電子郵件資訊範例
        TMap<EHiveProviderType, FHiveProviderInfo> ProviderInfoData = PlayerInfo.ProviderInfoData;
        if (const FHiveProviderInfo* ProviderInfo = ProviderInfoData.Find(EHiveProviderType::GOOGLE)) {
                FString Email = ProviderInfo->ProviderEmail;
        }
    }
}));

API 參考: Auth4::signIn

#include <HIVE_SDK_Plugin/HIVE_CPP.h>

AuthV4::signIn(ProviderType::GOOGLE, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {
    if (result.isSuccess()) {
        // 呼叫成功
        // playerInfo : 已驗證的用戶信息。

        // 取得 ProviderType::GOOGLE 的電子郵件資訊範例
        map<ProviderType, ProviderInfo> providerInfoData = playerInfo.providerInfoData;
        ProviderInfo providerInfo = providerInfoData[ProviderType::GOOGLE];
        string email = providerInfo.providerEmail;
    }
});

API 參考: AuthV4.signIn

import com.hive.AuthV4
import com.hive.ResultAPI

AuthV4.signIn(AuthV4.ProviderType.GOOGLE, object : AuthV4.AuthV4SignInListener {
    override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // 呼叫成功
            // playerInfo: 已認證的用戶信息
            // 獲取ProviderType.GOOGLE的電子郵件信息的示例
            if (playerInfo != null) {
                val providerInfoData = playerInfo.providerInfoData
                val providerInfo = providerInfoData[AuthV4.ProviderType.GOOGLE]
                if (providerInfo != null) {
                    val email = providerInfo.providerEmail
                }
            }
        }
    }
})

API 參考: com.hive.Auth4.signIn

import com.hive.AuthV4;
import com.hive.ResultAPI;

AuthV4.signIn(AuthV4.ProviderType.GOOGLE, (result, playerInfo) -> {
    if (result.isSuccess()) {
        // 呼叫成功
        // playerInfo: 認證用戶信息
        // 獲取ProviderType.GOOGLE的電子郵件信息示例
        if (playerInfo != null) {
            HashMap<AuthV4.ProviderType, AuthV4.ProviderInfo> providerInfoData = playerInfo.getProviderInfoData();
            AuthV4.ProviderInfo providerInfo = providerInfoData.get(AuthV4.ProviderType.GOOGLE);
            if (providerInfo != null) {
                String email = providerInfo.getProviderEmail();
            }
        }
    }
});

API 參考: AuthV4Interface.signIn

import HIVEService

AuthV4Interface.signIn(.Google) { result, playerInfo in    
    if result.isSuccess() {
        // 呼叫成功
        // playerInfo: 已驗證的用戶信息。

        // 獲取 Google 的電子郵件資訊的範例
        if 
            let playerInfo = playerInfo,  
            let providerInfo = playerInfo.providerInfoData["GOOGLE"] {
                let email = providerInfo.providerEmail
        }
    }
}

API 參考: HIVEAuth4:signIn

#import <HIVEService/HIVEService-Swift.h>

[HIVEAuthV4 signIn:HIVEProviderTypeGoogle handler:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
    if ([result isSuccess]){
        // 呼叫成功
        // playerInfo: 已驗證的用戶信息。

        // 獲取 HIVEProviderTypeGoogle 的電子郵件信息示例
        if(playerInfo != nil) {
            HIVEProviderInfo *providerInfo = playerInfo.providerInfoData[@"GOOGLE"];
            if(providerInfo != nil){
                NSString *email = providerInfo.providerEmail;
            }
        }
    }
}];

檢查設備上的 IdP 帳戶登錄

自動登錄使用已保存的 PlayerID 的身份驗證令牌密鑰進行登錄,而顯式登錄則登錄到與多個 IdP 相關聯的帳戶。在這兩種情況下,登錄的 PlayerID 的 IdP 帳戶可能與實際設備 (DevicePlayer) 上登錄的 IdP 帳戶不同。將提供指導以統一這兩個帳戶,以便為未來的成就或排行榜使用做好準備。

  • 檢查 SDK 提供的 DevicePlayer 的 UI

以下是一段示例代码,用于检查 IdP 信息。

API 參考: AuthV4.Helper.syncAccount

using hive;

AuthV4.ProviderType providerType = AuthV4.ProviderType.GOOGLE;
AuthV4.Helper.syncAccount (providerType, delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {

    switch (result.code) {
        case ResultAPI.Code.Success:
            // 正常
            break;   
        case ResultAPI.Code.AuthV4ConflictPlayer:
            // 帳號衝突
            // 例如) 當使用 Hive UI 時
            // AuthV4.Helper.showConflict(...);
            // 或
            // 例如) 當實作 GameUI 時
            // AuthV4.Helper.resolverConflict(...);// 當選擇當前用戶
            // AuthV4.Helper.switchAccount(...);// 當選擇用戶切換 
            break;
        default:  
            // 其他例外
            break;
    }
});
#include "HiveAuthV4.h"

FHiveAuthV4::Helper::SyncAccount(ProviderType, 
                                 FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, 
                                                                                const TOptional<FHivePlayerInfo>& PlayerInfo) {

    switch (Result.Code) {
        case FHiveResultAPI::ECode::Success:
            // 正常响应
            break;
        case FHiveResultAPI::ECode::AuthV4ConflictPlayer:
            // 账户冲突
            // 例如) 当使用 Hive UI 时
            // FHiveAuthV4::Helper::ShowConflict()
            // 例如) 当实现游戏 UI 时
            // FHiveAuthV4::Helper::ResolveConflict() // 当前用户选择
            // FHiveAuthV4::Helper::SwitchAccount() // 用户切换选择
            break;
        default:
            // 其他异常情况
            break;
    }
}));

API 參考: AuthV4::Helper::syncAccount

#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;
using namespace hive;

ProviderType providerType = ProviderType::GOOGLE;
AuthV4::Helper::syncAccount(providerType, [=](ResultAPI const & result, shared_ptr<PlayerInfo> playerInfo) {

    switch (result.code) {
        case ResultAPI::Success:
            // 正常
            break;   
        case ResultAPI::AuthV4ConflictPlayer:
            // 帳戶衝突
            // 例如) 當使用 Hive UI 時
            // AuthV4::Helper::showConflict(...);
            // 或
            // 例如) 當實現 GameUI 時
            // AuthV4::Helper::resolverConflict(...);// 當選擇當前用戶
            // AuthV4::Helper::switchAccount(...);// 當選擇切換用戶 
            break;
        default:  
            // 其他異常情況
            break;
    }
});

API 參考: AuthV4.Helper.syncAccount

import com.hive.AuthV4
import com.hive.ResultAPI

val providerType = AuthV4.ProviderType.GOOGLE
AuthV4.Helper.syncAccount(providerType, object : AuthV4.Helper.AuthV4HelperListener {
    override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {    
        when (result.code) {
            ResultAPI.Code.Success -> {
                // 正常
            }
            ResultAPI.Code.AuthV4ConflictPlayer -> {
                // 帳戶衝突
                // 例如) 使用 Hive UI 時
                // AuthV4.Helper.showConflict(...);
                // 或
                // 例如) 實現 GameUI 時
                // AuthV4.Helper.resolverConflict(...);// 選擇當前用戶時
                // AuthV4.Helper.switchAccount(...);// 選擇用戶切換時
            }
            else -> {
                // 其他異常情況
            }
        }
    }
})

API 參考: AuthV4.Helper.syncAccount

import com.hive.AuthV4;
import com.hive.ResultAPI;

AuthV4.ProviderType providerType = AuthV4.ProviderType.GOOGLE;
AuthV4.Helper.syncAccount(providerType, (result, playerInfo) -> {
    switch (result.getCode()) {
        case Success:
            // 正常  
        case AuthV4ConflictPlayer:    
            break;   
            // 帳戶衝突
            // 例如) 使用 Hive UI 時
            // AuthV4.Helper.showConflict(...);
            // 或
            // 例如) 實現 GameUI 時
            // AuthV4.Helper.resolverConflict(...);// 當選擇當前用戶
            // AuthV4.Helper.switchAccount(...);// 當選擇用戶切換 
            break;
        default:  
            // 其他異常
            break;
    }
});

API 參考: AuthV4Interface.helper().syncAccount

import HIVEService
let providerType: ProviderType = .Google

AuthV4Interface.helper().syncAccount(providerType) { result, playerInfo in
    switch result.getCode() {
        case .success:
        // 正常
        case .authV4ConflictPlayer:
        // 帳戶衝突
        // 例如) 使用 Hive UI 時
        // AuthV4Interface.helper().showConflict(...);
        // 或
        // 例如) 實作 GameUI 時
        // AuthV4Interface.helper().resolverConflict(...);// 當選擇當前用戶時
        // AuthV4Interface.helper().switchAccount(...);// 當選擇用戶切換時 
        default:
        // 其他例外情況
        break
    }
}

API 參考: [HIVEAuthV4 helper] syncAccount

#import <HIVEService/HIVEService-Swift.h>

HIVEProviderType providerType = HIVEProviderTypeGoogle
[[HIVEAuthV4 helper] syncAccount: providerType handler: ^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
    switch ([result getCode]) {
        case HIVEResultAPICodeSuccess:
            // 正常
            break;    
        case HIVEResultAPICodeAuthV4ConflictPlayer:
            // 帳戶衝突
            // 例如) 當使用 Hive UI 時
            // [[HIVEAuthV4 helper] showConflict: ...];
            // 或
            // 例如) 當實現 GameUI 時
            // [[HIVEAuthV4 helper] resolverConflict:...];// 當選擇當前用戶時
            // [[HIVEAuthV4 helper] switchAccount:...];// 當選擇用戶切換時  
            break;
        default:  
            // 其他異常
            break;
    }
}];

來賓登入

來賓登入功能允許用戶在不選擇 IdP 的情況下以來賓模式玩遊戲。您可以從 Hive SDK 提供的明確登入 UI 中選擇來賓登入,或者如果您在遊戲中自定義它,則可以直接實現來賓登入。Windows 環境不支持來賓登入。

作為訪客登錄時,您必須遵守以下政策。

客戶登入政策

  • 实现游戏,使得 IdP 认证用户和访客用户可以以相同的方式使用它。 即使以访客身份登录,Hive 平台的大多数功能也可以使用。因此,请实现您的游戏,以便以访客身份登录的用户可以以与 IdP 关联用户相同的方式使用游戏。例如,访客用户也应该能够在游戏中购买物品和进行支付。
    • 不为访客用户提供注销功能。 如果用户在以访客身份登录后注销,他们将无法使用相同的 PlayerID 重新登录。因此,请不要提供注销按钮,以便用户在以访客身份登录时无法注销。
    • 中国访客登录禁止政策 如果使用中国 IP,只有经过实名认证的用户才能充值和消费资源(自 2017 年 5 月 1 日起生效),因此访客登录不包括在可以使用中国 IP 登录的 IdP 列表中。

要執行訪客登錄,請調用 signIn() 方法,並將 ProviderType.GUEST 作為參數。 這裡是一個執行訪客登錄的示例代碼。

Note

在未進行任何 IdP 認證的來賓狀態下,playerInfo 中的 PlayerID 沒有 providerInfoData。

API 參考: hive.AuthV4.signIn

using hive;

AuthV4.signIn(AuthV4.ProviderType.GUEST, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => {
    if (result.isSuccess()) {
        // 認證成功
        // playerInfo: 已認證的用戶信息
    }
});
#include "HiveAuthV4.h"

FHiveAuthV4::SignIn(EHiveProviderType::GUEST, 
                    FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {

    if (Result.IsSuccess()) {
            // 呼叫成功 (PlayerInfo: 已驗證的用戶信息)
    }
}));

API 參考: Auth4::signIn

#include <HIVE_SDK_Plugin/HIVE_CPP.h> 

using namespace std;
using namespace hive;
AuthV4::signIn(ProviderType::GUEST, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {
    if (result.isSuccess()) {
        // 認證成功
        // playerInfo: 已認證的用戶信息
    }
});

API 參考: AuthV4.signIn

import com.hive.AuthV4
import com.hive.ResultAPI

AuthV4.signIn(AuthV4.ProviderType.GUEST, object : AuthV4.AuthV4SignInListener {
    override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // 認證成功
            // playerInfo: 已認證的用戶信息
        }
    }
})

API 參考: com.hive.Auth4.signIn

import com.hive.AuthV4;
import com.hive.ResultAPI;

AuthV4.signIn(AuthV4.ProviderType.GUEST, (result, playerInfo) -> {
    if (result.isSuccess()) {
        // 認證成功
        // playerInfo: 已認證的用戶信息
    }
});

API 參考: AuthV4Interface.signIn

import HIVEService

AuthV4Interface.signIn(.Guest) { result, playerInfo in
    if result.isSuccess() {
        // Authentication successful
        // playerInfo: Authenticated user information
    }
}

API 參考: HIVEAuth4:signIn

#import <HIVEService/HIVEService-Swift.h>

[HIVEAuthV4 登入: HIVEProviderTypeGuest 處理程序: ^(ResultAPI *result, HIVEPlayerInfo *playerInfo) {
    if ([result isSuccess]) {
        // 認證成功
        // playerInfo: 已認證的用戶信息
    }
}];

自訂登入

自訂登入是一個自訂登入的功能,允許您通過與遊戲本身集成的身份提供者(IdP)實現登入,除了Hive提供的IdP之外。請嘗試生成一個身份驗證密鑰(authKey),以便在根據Authenticate v4 Custom Authentication調用自訂登入API時使用。

在调用自定义登录 API 后,您可以通过作为回调接收到的 PlayerInfo 类实例访问 customProviderInfoData 数据,以检查自定义登录用户的信息。customProviderInfoDataProviderType (枚举) 统一设置为 CUSTOM,并且可以通过 ProviderName (字符串) 进行详细区分。

在遊戲中實現自定義登錄的IdP的信息不包括在AuthV4類的setup()showSignIn()方法調用的結果中。

如果您在第一次执行自定义登录后收到了 playerId 和 playerToken,当自定义登录 API 被重新调用时,authV4SessionExist(code) 的结果 API 将作为回调返回。在这种情况下,您应该使用 ProviderType.Auto 作为参数调用 signIn(),以便使用已经登录的帐户进行自动登录。请参阅下面的示例代码。

AuthV4類的connect()disconnect()方法不支持自定義登錄IdP的額外集成和斷開連接。connectWithAuthKey()disconnectWithName()方法支持自定義登錄IdP的額外集成和斷開連接。

這是一個實現自定義登錄的示例代碼。

API 參考: hive.AuthV4.signIn

// 在遊戲中直接實現Twitter登錄
Game.Login("CUSTOM_TWITTER", (string authKey) => {
    AuthV4.signInWithAuthKey(authKey, (ResultAPI result, PlayerInfo playerInfo) => {
        if (result.isSuccess()) {
            Dictionary<string, ProviderInfo> customProviderInfoData = playerInfo.customProviderInfoData;
            ProviderInfo providerInfo = customProviderInfoData["CUSTOM_TWITTER"];
            // 檢查以下用戶鏈接信息
            providerInfo.providerType;     // ProviderType.CUSTOM,自定義類型是固定的,因此需要通過providerName區分
            providerInfo.providerName;   // "CUSTOM_TWITTER"
            providerInfo.providerUserId;  // 用於自定義Twitter登錄的用戶ID
            return;
        }
        else if (result.code == ResultAPI.Code.AuthV4SessionExist) {
            // 如果playerId和playerToken已經發放並且需要自動登錄
            // TODO: AuthV4.signIn(ProviderType.AUTO, (ResultAPI _result, PlayerInfo playerInfo) => {});
        }
        else if (result.code == ResultAPI.Code.AuthV4NotInitialized) {
            // TODO: 需要SDK初始化
        }
        else if (result.code == ResultAPI.Code.AuthV4InvalidParam) {
            // TODO: 檢查提供的authKey的值是否為NULL或空
        }
        else if (result.needExit()) {
            // TODO: 實現應用退出功能
            // 例如) Application.Quit();
        }
    });  
});
#include "HiveAuthV4.h"

// 直接在遊戲中實現了 "CUSTOM_TWITTER" 類型的 Twitter 登錄
void GameLogin(const FString& AuthKey)
{
    FHiveAuthV4::SignInWithAuthKey(AuthKey, FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {

        if (Result.IsSuccess()) {
            TMap<FString, FHiveProviderInfo> CustomProviderInfoData = PlayerInfo.CustomProviderInfoData;
            if (const FHiveProviderInfo* ProviderInfo = CustomProviderInfoData.Find(TEXT("CUSTOM_TWITTER"))) {
                    EHiveProviderType ProviderType = ProviderInfo->ProviderType; // EHiveProviderType::CUSTOM, custom types are fixed
                    FString ProviderName = ProviderInfo->ProviderName; // Need to distinguish by ProviderName
                    FString ProviderUserId = ProviderInfo->ProviderUserId; // User id used in the custom Twitter login
            }
        } else if (Result.NeedExit()) {
            // TODO: Implement app exit functionality
            // e.g.) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        } else if (Result.Code == FHiveResultAPI::ECode::AuthV4SessionExist) {
            // If playerId and playerToken have already been issued and automatic login is needed
            // TODO: FHiveAuthV4.SignIn(EHiveProviderType::GUEST, Delegate);
        } else if (Result.Code == FHiveResultAPI::ECode::AuthV4NotInitialized) {
            // TODO: SDK initialization needed
        } else if (Result.Code == FHiveResultAPI::ECode::AuthV4InvalidParam) {
            // TODO: Check if the value of the provided authKey is empty
        }
    }));
}

API 參考: Auth4::signIn

using namespace std;
using namespace hive;

// Twitter 登入直接在遊戲中實現
Game::Login("CUSTOM_TWITTER", [=](string authKey) {
    AuthV4::signInWithAuthKey(authKey, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {
        if (result.isSuccess()) {
            map<string, ProviderInfo> customProviderInfoData = playerInfo.customProviderInfoData;
            ProviderInfo providerInfo = customProviderInfoData["CUSTOM_TWITTER"];
            // 檢查以下用戶連結信息
            providerInfo.providerType; // ProviderType::CUSTOM,因為自定義類型是固定的,需要通過 providerName 區分
            providerInfo.providerName; // "CUSTOM_TWITTER"
            providerInfo.providerUserId; // 用於自定義 Twitter 登入的用戶 ID
            return;
        }
        else if (result.code == ResultAPI::Code::AuthV4SessionExist) {
            // 如果 playerId 和 playerToken 已經被發放並且需要自動登入
            // TODO: AuthV4.signIn(ProviderType::AUTO, [=](ResultAPI const & _result, PlayerInfo const & playerInfo) {});
        }
        else if (result.code == ResultAPI::Code::AuthV4NotInitialized) {
            // TODO: 需要 SDK 初始化
        }
        else if (result.code == ResultAPI::Code::AuthV4InvalidParam) {
            // TODO: 檢查提供的 authKey 的值是否為 NULL 或空
        }
        else if (result.needExit()) {
            // TODO: 實現應用退出功能
            // 對於 Cocos2d-x 引擎用戶
            // 例) exit(0);
            // 對於 Unreal 引擎用戶
            // 例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        }
    });  
});

API 參考: com.hive.Auth4.signIn

// Twitter 登入直接在遊戲中實現
Game.Login("CUSTOM_TWITTER") { authKey: String ->

    AuthV4.signInWithAuthKey(authKey, object : AuthV4.AuthV4SignInListener {
        override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {

            if (result.isSuccess && playerInfo != null) {
                playerInfo.customProviderInfoData["CUSTOM_TWITTER"]?.let { providerInfo ->
                    providerInfo.providerType   // ProviderType.CUSTOM, custom types are fixed, so need to distinguish by providerName
                    providerInfo.providerName   // "CUSTOM_TWITTER"
                    providerInfo.providerUserId // User id used for the custom Twitter login
                }
            }
            else if (result.needExit()) {
                // TODO: Implement app exit functionality
                // e.g.) exitProcess(0)
            }
            else if (result.code == ResultAPI.Code.AuthV4SessionExist) {
                // If playerId and playerToken have already been issued and automatic login is needed
                // TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener)
            }
            else if (result.code == ResultAPI.Code.AuthV4NotInitialized) {
                // TODO: SDK initialization needed
            }
            else if (result.code == ResultAPI.Code.AuthV4InvalidParam) {
                // TODO: Check if the value of the provided authKey is NULL or empty
            }
        }
    })
}

API 參考: com.hive.Auth4.signIn

// Twitter 登入直接在遊戲中實現
Game.Login("CUSTOM_TWITTER") { authKey: String ->
    AuthV4.signInWithAuthKey(authKey, new AuthV4.AuthV4SignInListener() {
        @Override
        public void onAuthV4SignIn(@NonNull ResultAPI result, @Nullable AuthV4.PlayerInfo playerInfo) {

            if(result.isSuccess() && playerInfo != null) {
                HashMap<String, AuthV4.ProviderInfo> customProviderInfoData = playerInfo.getCustomProviderInfoData();
                AuthV4.ProviderInfo providerInfo = customProviderInfoData.get("CUSTOM_TWITTER");
                // 檢查以下用戶鏈接信息
                if (providerInfo != null){
                    providerInfo.getProviderType(); // AuthV4.ProviderType.CUSTOM,因為自定義類型是固定的,需要通過providerName來區分
                    providerInfo.getProviderName(); // "CUSTOM_TWITTER"
                    providerInfo.getProviderUserId(); // 用於直接實現的自定義Twitter登錄的用戶ID
                }
            } else if (result.needExit()) {
                // TODO: 實現應用退出功能
                // 例如) System.exit(0);
            } else if (result.getCode() == ResultAPI.Code.AuthV4SessionExist) {
                // 如果playerId和playerToken已經發放並且需要自動登錄
                // TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener)
            } else if (result.getCode() == ResultAPI.Code.AuthV4NotInitialized) {
                // TODO: 需要SDK初始化
            } else if (result.getCode() == ResultAPI.Code.AuthV4InvalidParam) {
                // TODO: 檢查提供的authKey的值是否為NULL或空
            }
        }
    });
}

API 參考: HIVEAuth4:signIn

// Twitter 登入直接在遊戲中實現
Game.login("CUSTOM_TWITTER") { (authKey) in
    AuthV4Interface.signInWithAuthKey(authKey) { (result, playerInfo) in
        if result.isSuccess() {
            let customProviderInfoData = playerInfo?.customProviderInfoData;
            let providerInfo = customProviderInfoData?["CUSTOM_TWITTER"]
            // 檢查以下用戶連結資訊
            providerInfo?.providerType;     // AuthProviderType,自定義類型是固定的,因此需要通過 providerName 區分
            providerInfo?.providerName;     // "CUSTOM_TWITTER"
            providerInfo?.providerUserId;   // 用於自定義 Twitter 登入的用戶 ID
            return
        }
        else if result.getCode() == .authV4SessionExist {
            // 如果 playerId 和 playerToken 已經發放並且需要自動登入
            // TODO: AuthV4Interface.signIn(.auto) { (result, playerInfo) in }
        }
        else if result.getCode() == .authV4NotInitialized {
            // TODO: 需要 SDK 初始化
        }
        else if result.getCode() == .authV4invalidParam {
            // TODO: 檢查提供的 authKey 的值是否為 nil 或空
        }
        else if result.needExit() {
            // TODO: 實現應用退出功能。
            // 例如:exit(0)
        }
    }
}

API 參考: HIVEAuth4:signIn

// Twitter 登入直接在遊戲中實現
[Game login:@"CUSTOM_TWITTER" handler:^(NSString* authKey) {

    [HIVEAuthV4 signInWithAuthKey:authKey handler:^(HIVEResultAPI* result, HIVEPlayerInfo* playerInfo) {
        if (result.isSuccess) {
            NSDictionary<NSString*, HIVEProviderInfo*>* customProviderInfoData = playerInfo.customProviderInfoData;
            ProviderInfo* providerInfo = [customProviderInfoData objectForKey:@"CUSTOM_TWITTER"];
            // 检查以下用户链接信息
            providerInfo.providerType;     // HIVEProviderTypeCustom,自定义类型是固定的,因此需要通过providerName区分
            providerInfo.providerName;   // "CUSTOM_TWITTER"
            providerInfo.providerUserId;  // 在自定义Twitter登录中使用的用户ID
            return;
        }
        else if (result.getCode == HIVEResultAPICodeAuthV4SessionExist) {
            // 如果playerId和playerToken已经被发放并且需要自动登录
            // TODO: [HIVEAuthV4 signIn:HIVEProviderTypeAuto, handler:^(HIVEResultAPI* _result, HIVEPlayerInfo* playerInfo) {}];
        }
        else if (result.getCode == HIVEResultAPICodeAuthV4NotInitialized) {
            // TODO: 需要SDK初始化
        }
        else if (result.getCode == HIVEResultAPICodeAuthV4InvalidParam) {
            // TODO: 检查提供的authKey的值是否为NULL或空
        }
        else if (result.needExit) {
            // TODO: 实现应用退出功能。
            // 例如) exit(0);
        }
    }];   
}];

使用者名稱

由於美國的COPPA等問題,當用戶從美國及其領土作為身份提供者(IdP)訪問和登錄時,必須輸入用戶名以便進行額外的用戶身份驗證處理。作為參考,美國領土包括美屬薩摩亞(AS)、關島(GU)、北馬里亞納群島(MP)、波多黎各(PR)、美國小離島(UM)和美國維爾京群島(VI)。用於輸入用戶身份的用戶名的屏幕如下。

  • 用戶名輸入畫面僅用於用戶識別目的,因此僅在初始 IdP 集成期間顯示一次,之後不會再顯示。
  • 在訪客登錄期間不會顯示用戶名輸入畫面。

驗證身份驗證令牌密鑰

遊戲伺服器可以使用成功登錄後返回的令牌、playerId 和 DID 資訊來驗證令牌密鑰的真實性。Hive 身份驗證允許多設備登錄和同時訪問。

如果不允許使用相同帳戶重複訪問,遊戲伺服器將在首次連接的設備上顯示通知消息,然後退出遊戲,允許遊戲在後來連接的設備上繼續進行。如果您在未退出的情況下再次嘗試訪問遊戲,您的遊玩記錄可能無法正確反映。要實現此功能,您需要管理經過驗證的令牌密鑰或遊戲本身的會話密鑰。

透過參考身份驗證令牌金鑰驗證伺服器API來實現此功能。

在背景中檢測 IdP 帳戶變更

用戶可以在遊戲過程中導航到設備設置,以更改他們的 Apple Game Center 或 Google Play Games 帳戶。如果您需要檢查遊戲過程中的 IdP 帳戶是否與當前 PlayerID 的 IdP 帳戶不同,請在初始化 SDK 後調用 setProviderChangedListener()。通過調用此 API,您可以在遊戲恢復時接收一個事件,指示設備上設置的 IdP 帳戶已更改。

iOS 與 Apple Game Center 一起工作,Android 則與 Google Play 遊戲一起工作,當帳戶更改時,只有當當前登錄的 PlayerID 與相應的 IdP 相關聯時,才會發送響應。當接收到 IdP 帳戶更改事件時,UI 被配置為允許用戶選擇是否使用登錄到設備的 IdP 帳戶。如果用戶選擇登錄到設備的 IdP 帳戶,則調用 signOut 以登出,然後執行隱式登錄。

Warning

安裝了 2021 年 7 月後發布的 Google Play 遊戲的設備,由於 Google Play 遊戲的操作問題,無法在背景中更改 IdP 帳戶。

Note

此功能可能會導致遊戲暫停並要求更改帳戶,並且只能在需要帳戶同步的時候限制性使用,例如進入大廳或商店時。

以下是一段示例代码,用于在用户重新启动游戏并且设备上设置的 IdP 账户发生更改时接收事件。

API 參考: hive.AuthV4.setProviderChangedListener

using hive;

AuthV4.setProviderChangedListener((ResultAPI result, AuthV4.ProviderInfo providerInfo) => {
    if (!result.isSuccess()) {
        return;
    }

    if (providerInfo != null && providerInfo.providerType == AuthV4.ProviderType.APPLE) {
        // 更改 GameCenter 用户信息
    }
});
#include "HiveAuthV4.h"

FHiveAuthV4::SetProviderChangedListener(FHiveAuthV4OnCheckProviderDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHiveProviderInfo& ProviderInfo) {
    if (Result.IsSuccess()) {
            // 调用成功。通过 ProviderInfo 对象检查更改的用户信息
    }
}));

API 參考: AuthV4::setProviderChangedListener

#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;
using namespace hive;

AuthV4::setProviderChangedListener([=](ResultAPI const & result, ProviderInfo const & providerInfo) {
    if (!result.isSuccess()) {
        return;
    }

    if (providerInfo != null && providerInfo.providerType == ProviderType::GOOGLE) {
        // 更改 Google Play 游戏服务帐户
    }
});

API 參考: AuthV4.setProviderChangedListener

import com.hive.AuthV4
import com.hive.ResultAPI

AuthV4.setProviderChangedListener(object : AuthV4.AuthV4CheckProviderListener {
    override fun onDeviceProviderInfo(result: ResultAPI, providerInfo: AuthV4.ProviderInfo?) {
        if (!result.isSuccess) {
            return
        }

        if (providerInfo != null && providerInfo.providerType == AuthV4.ProviderType.GOOGLE) {
            // 更改 Google Play 游戏服务帐户
        }
    }
})

API 參考: com.hive.AuthV4.setProviderChangedListener

import com.hive.AuthV4;
import com.hive.ResultAPI;

AuthV4.setProviderChangedListener((result, providerInfo) -> {
    if (!result.isSuccess()) {
        return;
    }

    if (providerInfo != null && providerInfo.getProviderType() == AuthV4.ProviderType.GOOGLE) {
        // 更改 Google Play 遊戲服務帳戶
    }
});

API 參考: AuthV4Interface.setProviderChangedListener

import HIVEService

AuthV4Interface.setProviderChangedListener() { result, providerInfo in 
    if !result.isSuccess() {
        return
    }

    if let providerInfo = providerInfo, providerInfo.providerType == .Apple {
        // 更改 GameCenter 用户信息
    }
}

API 參考: HIVEAuthV4:setProviderChangedListener

#import <HIVEService/HIVEService-Swift.h> 

[HIVEAuthV4 setProviderChangedListener: ^(HIVEResultAPI *result, ProviderInfo *providerInfo) {
    if (![result isSuccess]) {
        return;
    }

    if (providerInfo != nil && providerInfo.providerType == HIVEProviderTypeApple) {
        // GameCenter 用戶信息變更
    }
}];

遊戲數據初始化

在初始化遊戲數據時請勿調用登出。由於 PlayerID 不會被刪除,可能會發生帳戶之間的衝突。您應該實現讓用戶能夠繼續使用當前登錄的帳戶進行遊玩,並且在用戶明確要求之前不要調用登出。

登出

Warning
  • 在登出操作中,身份验证信息 PlayerId 和会话信息 PlayerToken,以及所有 IDP 的会话信息,将被删除。
  • 所有以 set 开头的 API 设置的值将不会被初始化或删除。
    • Configuration、Auth、Auth v4、Promotion 和 Push 类中所有以 set 开头的方法
    • 以下是代表性的示例。 ex> Configuration.setServer, Configuration.setUseLog, Configuration.setGameLanguage, Configuration.setHiveCertificationKey, Auth.setEmergencyMode, AuthV4.setProviderChangedListener, Promotion.setUserEngagementReady, Promotion.setAddtionalInfo, Push.setRemotePush, Push.setForegroundPush 等等。所有以 set 开头的方法均属于此类别。
    • 从 Hive SDK v4 24.3.0 开始,当游客用户登出时,将返回错误代码。之后,客户端和服务器会话将保持。
  • 通过 SDK 中以 set 开头的方法设置的值的有效范围在应用程序的生命周期内保持,无论登录或登出状态如何。

如果您已經登入Hive,則已發出PlayerID和身份驗證令牌密鑰。登出執行初始化PlayerID和身份驗證令牌密鑰的功能。當您調用signOut()方法以完成登出時,您將被重定向到遊戲標題,當您點擊標題時將執行明確的登入。

Note
  • 在訪客登錄狀態下登出時,無法再找到相同的 PlayerID,因此請實現使訪客狀態下不提供登出的功能。
  • PlayerID 的 IdP 連結狀態在登出後不會改變。
  • 登出完成後,將移動到遊戲標題,並在點擊標題時進行明確登錄。
  • 登出後,如果應用程序重新啟動,將首先執行隱式登錄。

這是一個執行登出的範例代碼。

API 參考: hive.AuthV4.signOut

using hive;    

AuthV4.Helper.signOut (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {    
    switch(result.code) {    
        case ResultAPI.Code.Success:    
            // 登出成功    
            break;    
        default:    
            // 其他异常    
            break;    
    }    
});
#include "HiveAuthV4.h"

FHiveAuthV4::Helper::SignOut(FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& PlayerInfo) {
    AHIVESDKV4TesterGameMode::getGameModeInstance()->appendLogString(ELogType::AuthV4Helper ,TEXT("Helper::SignOut Result = %s"), *(Result.ToString()));
    switch (Result.Code) {
        case FHiveResultAPI::ECode::Success:
            // 登出成功
            break;
        default:
            // 其他异常
            break;
    }
}));

API 參考: AuthV4::signOut

#include <HIVE_SDK_Plugin/HIVE_CPP.h>    
using namespace std;    
using namespace hive;    

AuthV4::Helper::signOut([=](ResultAPI const & result, shared_ptr playerInfo) {    
    switch (result.code) {    
        case ResultAPI::Success:    
            // 登出成功    
            break;    
        default:    
            // 其他异常    
            break;    
    }    
});

API 參考: AuthV4.Helper.signOut

import com.hive.AuthV4
import com.hive.ResultAPI

AuthV4.Helper.signOut(object : AuthV4.Helper.AuthV4HelperListener {
    override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        when (result.code) {
            ResultAPI.Code.Success -> {
                // 登出成功
            }
            else -> {
                // 其他异常情况
            }
        }
    }
})

API 參考: AuthV4.Helper.signOut

import com.hive.AuthV4;
import com.hive.ResultAPI;

AuthV4.Helper.signOut((result, playerInfo) -> {
    switch (result.getCode()) {
        case Success:
            // 登出成功
            break;
        default:
            // 其他异常
            break;
    }
});

API 參考: AuthV4Interface.helper().signOut()

import HIVEService

AuthV4Interface.helper().signOut() { result, playerInfo in
    switch result.getCode() {
        case .success:
            // 登出成功
        default:
            // 其他异常
            break
    }}

API 參考: [HIVEAuthV4 helper] 登出

#import <HIVEService/HIVEService-Swift.h>

[[HIVEAuthV4 helper] signOut: ^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
    switch ([result getCode]) {
        case HIVEResultAPICodeSuccess:
            // 登录成功
            break;
        default:
            // 其他异常
            break;
    }
}];

遊戲中心取消通知文本

語言 短語
Korean Apple Game Center 的登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與您的遊戲中心帳戶同步並重試。
English 您的遊戲中心登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與遊戲中心帳戶同步並重試。
Japanese Apple Game Center 的登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以在與您的遊戲中心帳戶同步後重試。
Simplified Chinese Apple Game Center 已登出。
如果您想與遊戲中心帳戶同步,請在 [設定 > 遊戲中心] 再次登錄並重試。
Traditional Chinese Apple Game Center 的登錄已被取消。
如果您想連接到遊戲中心帳戶,請在 [設定 > 遊戲中心] 登錄並重試。
French 您與遊戲中心的連接已被取消。
請在 [設定 > 遊戲中心] 登錄以同步您的遊戲中心帳戶並重試。
German Apple Game Center 的登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與遊戲中心帳戶同步並重試。
Russian 您的遊戲中心登錄已被取消。
請通過 [設定 > 遊戲中心] 登錄遊戲中心並重試。
Spanish 您的遊戲中心登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與遊戲中心帳戶同步並重試。
Portuguese 您的遊戲中心登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與遊戲中心帳戶同步並重試。
Indonesian Apple Game Center 的登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以連接您的遊戲中心帳戶並重試。
Malaysian 您的遊戲中心登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與遊戲中心帳戶同步並重試。
Vietnamese Apple Game Center 的登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與您的遊戲中心帳戶同步並重試。
Thai 您的遊戲中心登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以連接到您的遊戲中心帳戶並重試。
Italian 您對 Apple Game Center 的訪問已被取消。
請在 [設定 > 遊戲中心] 登錄以與遊戲中心同步您的帳戶並重試。
Turkish 您的 Apple Game Center 登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以訪問遊戲中心帳戶並重試。
Arabic 您的遊戲中心登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與您的遊戲中心帳戶同步並重試。