跳轉至

登录注销

登入驗證包括以下步驟。

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
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 ID 登录的设备上使用 Apple 登录,则在调用 AuthV4Helper 类的 connect()signIn() 方法 的过程中会发生 AuthV4SignInAppleUnknown 错误。Apple ID 登录指导弹出窗口会自动显示,因此游戏工作室无需显示单独的 弹出窗口 进行指导。

Note

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

Hive SDK Windows 注意事項

在所有 Windows 目標的 Hive SDK 構建中,當調用 AuthV4.Helper.signInAuthV4.showSignInAuthV4.signIn 方法時,可能會出現如下所示的 IdP 登錄待機窗口。即使此待機窗口關閉,登錄仍未完成。<

登入僅在收到方法調用的結果回調後才算完成,回調的傳遞可能會根據網絡環境而延遲。因此,建議通過文本顯示或遊戲畫面中的加載指示器來告知用戶登入進度狀態。

自動登入和隱式登入

自動登入

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

要在 iOS 環境中使用自動登錄,您需要添加 Game Center 權限,Unity 會通過 Unity PostProcess 自動添加該權限,如果您勾選了「Apple GameCenter」依賴項。在 iOS Native 中,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: 實現應用程式退出功能
            // e.g.) System.exit(0);
        } else {
            switch (result.code) {
                case ResultAPI.Code.AuthV4ConflictPlayer:
                    // 帳號衝突
                    break;
                case ResultAPI.Code.AuthV4HelperImplifiedLoginFail:
                    // 隱式登入失敗
                    // ex) 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: 實現應用程式退出功能
        // 例如) exit(0)
    } else {
        switch result.getCode() {
            case .authV4ConflictPlayer:
                // 帳戶衝突
                break
            case .authV4HelperImplifiedLoginFail:
                // 隱式登錄失敗
                // 例如) 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,請參考 明確登錄自定義 部分。

IdP 列表由 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: 實現應用程序退出功能
        // 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 {
            // 搜尋存在 providerEmail 的 providerInfo(當前登錄的提供者)
            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,則顯示一個包含所有 Google 帳戶的 UI,這些帳戶存在於 Android 操作系統設備的帳戶設置中
    • 當用戶從所有 Google 帳戶的列表 UI 中選擇所需的 Google 帳戶時,使用該帳戶登錄
  3. 沒有 Google 帳戶登錄到應用程序的情況
    • 顯示一個包含所有 Google 帳戶的 UI,這些帳戶存在於 Android 操作系統設備的帳戶設置中
    • 當用戶從所有 Google 帳戶的列表 UI 中選擇所需的 Google 帳戶時,使用該帳戶登錄


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

Note

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

明確的登錄自定義

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

Note
  • UI範例截圖顯示登錄畫面上的Facebook整合按鈕

以下是一個範例源代碼,假設用戶在自定義的明確登錄 UI 中選擇 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 提供的明確登入用戶界面中選擇來賓登入,或者如果您在遊戲中自定義它,可以直接實現來賓登入。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()) {
            // Call succeeded (PlayerInfo: Authenticated user information)
    }
}));

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() {
        // 認證成功
        // playerInfo: 已認證的用戶信息
    }
}

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 (enum) 統一設置為 CUSTOM,並且可以通過 ProviderName (String) 詳細區分。

在遊戲中實現自定義登錄的 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: 實現應用退出功能
            // e.g.) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        } else if (Result.Code == FHiveResultAPI::ECode::AuthV4SessionExist) {
            // 如果 playerId 和 playerToken 已經發放並且需要自動登錄
            // TODO: FHiveAuthV4.SignIn(EHiveProviderType::GUEST, Delegate);
        } else if (Result.Code == FHiveResultAPI::ECode::AuthV4NotInitialized) {
            // TODO: 需要 SDK 初始化
        } else if (Result.Code == FHiveResultAPI::ECode::AuthV4InvalidParam) {
            // TODO: 檢查提供的 authKey 的值是否為空
        }
    }));
}

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: 實現應用退出功能。
            // e.g. 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: 实现应用退出功能。
            // e.g) exit(0);
        }
    }];   
}];

自動登錄持久性選項

**自動登錄持久性選項**是一個功能,允許遊戲啟用或禁用自動登錄功能。


基本實現序列

在 Hive SDK 中應用自動登錄持久性選項的順序如下:

  1. 呼叫 SDK 初始化函數
  2. 呼叫 AuthV4.setAutoLoginEnabled API。在呼叫時,傳遞以下配置值以設置「自動登錄持久選項」:
    • true:啟用自動登錄。此配置值應用於隨後呼叫的登錄函數(AuthV4.signIn、AuthV4.showSignIn 等),以保存登錄信息並在重新登錄時啟用自動登錄。
    • false:禁用自動登錄。即使成功登錄,也不會保存登錄信息,因此在重新登錄時,用戶必須選擇登錄方法並按照現有登錄流程進行。
  3. 呼叫登錄函數並成功登錄
    • 成功登錄後,如果在第 2 步中呼叫 AuthV4.setAutoLoginEnabled API 時傳遞的配置值為 true,則保存登錄信息。
  4. 用戶強制終止遊戲應用而未登出(假設)
  5. 執行應用並呼叫 SDK 初始化函數以重新登錄
    • 如果在第 2 步中呼叫 AuthV4.setAutoLoginEnabled API 時傳遞的配置值為 true,則「登錄自動類型」作為 SDK 初始化函數的回調值返回。
    • 當呼叫涉及後續重新登錄操作的 AuthV4.signIn API 或 AuthV4.showSignIn API 時,應用「登錄自動類型」。但是,在 PC 登錄環境中,呼叫 AuthV4.showSignIn API 時不應用此選項,因為自動登錄選項作為單獨的復選框提供。
  6. 在重新登錄期間,可以直接使用 AuthV4.signin AUTO 類型或 AuthV4.Helper.SignIn 進行自動登錄,而無需呼叫 AuthV4.setAutoLoginEnabled API

  7. 如果用戶在未經過登出過程的情況下終止並重新執行遊戲應用程式,則可以使用 AuthV4.signin AUTO 類型或作為初始化函數回調返回的 AuthV4.Helper.SignIn 進行自動登錄。

當遊戲應用程式重新執行或登出時,調用AuthV4.setAutoLoginEnabled API時傳遞的配置值會根據以下每個遊戲應用程式設備環境重置為默認值。

- **手機**: `true` (自動登入已啟用,Android 和 iOS 的預設值)
- **電腦**: `false` (自動登入已禁用)
Warning

當調用 AuthV4.setAutoLoginEnabled 時傳遞的配置值將應用於隨後調用的與登錄相關的 API(AuthV4.signInAuthV4.showSignIn 等)。因此,AuthV4.setAutoLoginEnabled API 必須在 SDK 初始化後 ~ 登錄前 被調用。


操作特性和限制

當調用 AuthV4.setAutoLoginEnabled API 時,必須確認並應用以下自動登錄持久性選項的操作特性:

  • 自動登錄持久性選項只能在**登錄之前**設置,並且在登錄時無法調用AuthV4.setAutoLoginEnabled API。可以從回調信息中確認設置值的成功與失敗。
  • 如果已經存在自動登錄會話,並且在AuthV4.setup回調信息中'isAutoSignIn=true',則應用用戶處於應用自動登錄持久性選項的情況下,可以使用登錄自動類型登錄,因此可以直接調用'AuthV4.signIn'而無需調用AuthV4.setAutoLoginEnabled。此外,如果在可以進行自動類型登錄時調用AuthV4.setAutoLoginEnabled,則會作為回調傳遞RESPONSE_FAIL失敗響應,並返回true作為自動登錄設置值。
  • 對於訪客登錄,請小心不要使用AuthV4.setAutoLoginEnabled=false。當調用false時,登錄後不會保存會話信息,這可能導致訪客帳戶信息丟失。
  • 在遊戲應用設備環境中調用的一些API不受AuthV4.setAutoLoginEnabled的影響。
    • 在PC環境中調用AuthV4.showSignIn:自動登錄持久性選項根據暴露的UI中包含的'自動登錄持久性選項'復選框值運行,因此在調用AuthV4.setAutoLoginEnabled時傳遞的配置值將被忽略。復選框中設置的值在應用重新執行或登出之前有效,就像AuthV4.setAutoLoginEnabled一樣,因此即使發生帳戶切換,當前設置也會保持。
      在PC環境中,如果通過調用AuthV4.showSignIn成功登錄,則根據復選框值保存登錄信息,並可以應用自動登錄。
    • 在PC和移動環境中調用AuthV4.signInWithStoredPlayerId:自動登錄持久性選項通過單獨的useAutoSignIn參數檢查應用程序狀態,因此在調用AuthV4.setAutoLoginEnabled時傳遞的配置值將被忽略。useAutoSignIn配置值在應用重新執行或登出之前有效,就像AuthV4.setAutoLoginEnabled一樣,因此即使發生帳戶切換,當前設置也會保持。
      在PC和移動環境中,如果通過調用AuthV4.signInWithStoredPlayerId成功登錄,則根據useAutoSignIn配置值保存登錄信息,並可以應用自動登錄。
  • 如果調用AuthV4.setAutoLoginEnabled API時的配置值未用作'根據遊戲應用設備環境的默認值',則操作可能會受到限制。
    • 在移動環境中,通過離線模式登錄時,使用AuthV4.setAutoLoginEnabled=true是強制性的。(或者不調用'AuthV4.setAutoLoginEnabled'以便使用默認值設置)如果用戶之前在離線模式下使用了AuthV4.setAutoLoginEnabled=false,則不會記錄登錄會話信息,因此在下一次應用執行期間無法進行離線模式登錄。
Info

當帳戶衝突發生時,決定自動登錄持久性選項的標準 基本上遵循 AuthV4.setAutoLoginEnabled 配置值。
然而,在特定遊戲應用設備環境中調用登錄相關的 API 時,如下所示,將應用該 API 使用的單獨自動登錄標誌值,而不是 AuthV4.setAutoLoginEnabled 配置值,並在帳戶衝突後切換帳戶時保持相同的標準。

  • 基於在 PC 環境中調用 AuthV4.showSignIn 時在登錄 UI 中顯示的自動登錄持久性選項復選框的值
  • 基於在 PC 和移動環境中調用 AuthV4.signInWithStoredPlayerId 時的內部自動登錄使用標誌 useAutoSignIn 的值


實作範例代碼

實現自動登錄持久性選項的示例代碼如下:

AuthV4.setAutoLoginEnabled(true, (ResultAPI result, bool isEnabled) =>
{
    if (result.isSuccess())
    {
        // API call successful
        // isEnabled : Set auto login usage status
    }
});
FHiveAuthV4::SetAutoLoginEnabled(true, FHiveAuthV4OnAutoLoginEnabledDelegate::CreateLambda([this](const FHiveResultAPI& Result, bool isEnabled) {
    if (Result.IsSuccess()) {
        // API call successful
        // isEnabled : Set auto login usage status
    }
}));
AuthV4::setAutoLoginEnabled(true, [=](const ResultAPI& result, bool isEnabled) {
    if (result.isSuccess()) {
        // API call successful
        // isEnabled : Set auto login usage status
    }
});
AuthV4.setAutoLoginEnabled(true) { result: ResultAPI, enabled: Boolean ->
    if (result.isSuccess()) {
        // API 呼叫成功
        // enabled : 設定自動登入使用狀態
    } else {
        // 錯誤處理
    }
}
AuthV4.setAutoLoginEnabled(true, new AuthV4.AuthV4SetAutoLoginEnabledListener() {
    @Override
    public void onAuthV4SetAutoLoginEnabled(ResultAPI result, boolean enabled) {
        if (result.isSuccess()) {
            // API 呼叫成功
            // enabled : 設定自動登錄使用狀態
        } else {
            // 錯誤處理
        }
    }
});
AuthV4Interface.setAutoLoginEnabled(enabled: true) { result, isEnabled in
    if (result.isSuccess()) {
        // API call successful
        // isEnabled : Set auto login usage status
    }
}

使用者名稱

由於美國的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

因為 Google Play 遊戲的操作問題,2021 年 7 月之後發布的安裝了 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() 方法以完成登出時,您將被重定向到遊戲標題,當您點擊標題時將執行明確的登錄。

當呼叫 AuthV4.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;
    }
}];

遊戲中心取消通知文本

語言 短語
韓文 Apple Game Center 登入已被取消。
請在 [設定 > Game Center] 登入以同步您的 Game Center 帳戶並重試。
英文 您的 Game Center 登入已被取消。
在 [設定 > Game Center] 登入以同步到 Game Center 帳戶並重試。
日文 Apple Game Center 登入已被取消。
請在 [設定 > Game Center] 登入以在與您的 Game Center 帳戶同步後重試。
簡體中文 Apple Game Center 已登出。
如果您想與 Game Center 帳戶同步,請在 [設定 > Game Center] 再次登入並重試。
繁體中文 Apple Game Center 登入已被取消。
如果您想連結到 Game Center 帳戶,請在 [設定 > Game Center] 登入並重試。
法文 您與 Game Center 的連接已被取消。
在 [設定 > Game Center] 登入以同步您的 Game Center 帳戶並重試。
德文 Apple Game Center 的登入已被取消。
通過在 [設定 > Game Center] 登入來與 Game Center 帳戶同步並重試。
俄文 您的 Game Center 登入已被取消。
通過 [設定 > Game Center] 登入 Game Center 並重試。
西班牙文 您的 Game Center 登入已被取消。
在 [設定 > Game Center] 登入以與 Game Center 帳戶同步並重試。
葡萄牙文 您的 Game Center 登入已被取消。
在 [設定 > Game Center] 登入以與 Game Center 帳戶同步並重試。
印尼文 Apple Game Center 登入已被取消。
通過在 [設定 > Game Center] 登入來連接您的 Game Center 帳戶並重試。
馬來文 您的 Game Center 登入已被取消。
在 [設定 > Game Center] 登入以與 Game Center 帳戶同步並重試。
越南文 Apple Game Center 登入已被取消。
在 [設定 > Game Center] 登入以與您的 Game Center 帳戶同步並重試。
泰文 您的 Game Center 登入已被取消。
在 [設定 > Game Center] 登入以連接到您的 Game Center 帳戶並重試。
意大利文 您對 Apple Game Center 的訪問已被取消。
在 [設定 > Game Center] 登入以與 Game Center 同步您的帳戶並重試。
土耳其文 您的 Apple Game Center 登入已被取消。
在 [設定 > Game Center] 登入以訪問 Game Center 帳戶並重試。
阿拉伯文 您的 Game Center 登入已被取消。
在 [設定 > Game Center] 登入以與您的 Game Center 帳戶同步並重試。