跳轉至

多帳號登入管理

**多帳戶登錄管理**是一項在登錄或登出時保存帳戶信息的功能,允許用戶重新加載保存的帳戶信息以便未來登錄。這通過利用先前驗證的帳戶信息提供了更快、更方便的登錄體驗。


操作流程和限制

在實施多帳戶登錄管理功能之前,讓我們解釋一下操作流程和限制。

以下每個功能的操作流程是實現多帳號登錄管理時的示例場景供參考。根據您的開發環境,流程的順序或保存帳號信息的方法可能與這些場景有所不同。

在登錄狀態下保存帳戶信息

此場景描述在用戶完成明確登錄後,保存帳戶信息。

因此,您可以稍後使用已保存的帳戶資訊實現重新登錄或帳戶刪除

※ 儲存和處理帳戶資訊的方法可能因遊戲客戶端的實現而異。


登出時保存帳戶資訊

此情境描述了當已登入的用戶登出時保存帳戶資訊。

因此,在這種情況下,您可以稍後實現使用保存的帳戶信息重新登錄或刪除帳戶

※ 儲存和處理帳戶資訊的方法可能會根據遊戲客戶端的實現而有所不同。


使用已保存的帳戶資訊重新登入或刪除

這是一個使用已保存的帳戶資訊重新登入或從檢索的列表中刪除特定帳戶資訊的流程,這是多帳戶登入管理的實際實現場景。

在用户从游戏中实现的 PlayerID 列表 UI 中选择帐户的步骤中,行为取决于用户当前是否已登录。

※ 遊戲客戶端中實現的 PlayerID 列表的 UI 配置方法可能會根據遊戲開發環境而有所不同。

操作限制

實施多帳戶登錄管理之前,請考慮以下操作限制。

  • 帳戶資訊**僅在登錄時**才能保存。
  • 使用已保存的帳戶資訊查看 PlayerID 列表或刪除已保存的帳戶資訊無論登錄狀態如何均可進行。
  • 在查看 PlayerID 列表後,使用已保存的帳戶資訊重新登錄**僅在登出時**可能。

實施指南

本指南說明如何使用 SDK 實現多帳戶登錄管理功能。

按照以下順序逐步實現該功能,通過調用 SDK 提供的 API:

  1. 登入完成後,保存當前已登入的帳戶資訊
  2. 要使用已保存的帳戶登入或刪除已保存的帳戶資訊,檢索已保存的帳戶資訊(PlayerID 列表)
  3. 使用檢索到的已保存帳戶資訊,實現當用戶點擊**多帳戶登入管理**時顯示 PlayerID 列表 UI 的功能
  4. 在 PlayerID 列表 UI 中,實現使用已保存的帳戶登入(PlayerID)刪除已保存的帳戶(PlayerID)

1. 保存當前登錄的帳戶信息

保存當前登錄的帳戶信息。通過使用已保存的帳戶信息,您可以**在隨後的登錄中更快地登錄,而無需單獨的身份驗證過程。**

在遊戲客戶端,如果用戶已登錄,請在帳戶設置菜單中提供一個UI元素,以允許用戶隨時保存當前登錄的帳戶,並在用戶啟用帳戶保存功能時調用帳戶保存API。 有關相關流程,請參考上面的登錄時保存帳戶信息場景。

當前登錄帳戶保存的 UI 實現示例如下。

圖 1. 實現當前登錄帳戶保存的示例

此外,當登出時,您可以實現一個流程,即如果用戶已登錄並選擇登出,則顯示一個彈出窗口,詢問是否保存帳戶。如果用戶點擊**保存並登出**,則調用帳戶保存 API 以保存當前登錄的帳戶信息,然後登出。有關相關流程,請參考上面的登出時保存帳戶信息場景。

圖 2. 登出時保存當前登錄帳戶的實現示例

呼叫 API 以保存當前登錄帳戶的示例代碼如下。

AuthV4.storeCurrentPlayerId((ResultAPI result)=>{
    if (result.isSuccess()) {
        // API call succeeded
    }
});
FHiveAuthV4::StoreCurrentPlayerId(FHiveAuthV4OnStoreCurrentPlayerIdDelegate::CreateLambda([this](const FHiveResultAPI& Result) {
    if (Result.IsSuccess()) {
        // API call succeeded
    } 
}));
AuthV4::storeCurrentPlayerId([=](ResultAPI const & result) {
    if (result.isSuccess()) {
        // API call succeeded
    }
});
AuthV4.storeCurrentPlayerId(object : AuthV4.AuthV4StorePlayerIdListener {
    override fun onAuthV4StorePlayerId(result: ResultAPI) {
        if (result.isSuccess) {
            // API call succeeded
        }
    }
})
AuthV4.storeCurrentPlayerId(new AuthV4.AuthV4StorePlayerIdListener() {
    @Override
    public void onAuthV4StorePlayerId(ResultAPI result) {
        if (result.isSuccess()) {
            // API call succeeded
        }
    }
});
AuthV4Interface.storeCurrentPlayerId { (result) in
    if result.isSuccess() {
        // API call succeeded
    }
}
[HIVEAuthV4 storeCurrentPlayerId: ^(HIVEResultAPI * result) {
    if([result isSuccess]){
        // API call succeeded
    }
}];


2. 檢索已保存的帳戶資訊 (PlayerID 列表)

從SDK和身份驗證伺服器檢索已保存的帳戶資訊(PlayerID列表)。遊戲客戶端可以使用檢索到的PlayerID列表來實現單獨的PlayerID列表UI。

呼叫 API 以檢索已保存的帳戶資訊(PlayerID 列表)的示例代碼如下。

AuthV4.getStoredPlayerIdList((ResultAPI result, List<long> playerIdList) =>
{
    if (result.isSuccess())
    {
        foreach (long playerId in playerIdList) {
            // API call succeeded
            // playerId: player ID
        }
    }
});
FHiveAuthV4::GetStoredPlayerIdList(FHiveAuthV4OnGetStoredPlayerIdListDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TArray<int64>& PlayerIdList) {
    if (Result.IsSuccess()) {
        for (int64 PlayerId : PlayerIdList) {
            // API 呼叫成功
            // playerId: 玩家 ID
        }
    }
}));
AuthV4::getStoredPlayerIdList([=](ResultAPI const & result, std::vector<PlayerID> const& playerIdList) {
    if (result.isSuccess()) {
        for (auto playerId : playerIdList) {
            // API call succeeded
            // playerId: player ID
        }
    }
});
AuthV4.getStoredPlayerIdList(object : AuthV4.AuthV4PlayerIdListListener {
    override fun onAuthV4GetPlayerIdList(result: ResultAPI, playerIdList: ArrayList<Long>?) {
        if (result.isSuccess) {
            playerIdList?.let {
                for (playerId in it) {
                    // API call succeeded
                            // playerId: player ID
                }
            }
        }
    }
})
AuthV4.getStoredPlayerIdList(new AuthV4.AuthV4PlayerIdListListener() {
    @Override
    public void onAuthV4GetPlayerIdList(ResultAPI result, ArrayList<Long> playerIdList) {
        if (result.isSuccess()) {
            if(playerIdList != null) {
                for(Long playerId : playerIdList) {
                    // API call succeeded
                            // playerId: player ID
                }
            }
        }
    }
});
AuthV4Interface.getStoredPlayerIdList { (result, playerIdList) in
    if result.isSuccess() {
        for playerId in playerIdList {
                            // API 呼叫成功
                            // playerId: 玩家 ID
        }
    }
}
[HIVEAuthV4 getStoredPlayerIdList: ^(HIVEResultAPI * result, NSArray<NSNumber *> * playerIdList) {
    if([result isSuccess]){
        for (NSNumber* playerId in playerIdList) {
            // API call succeeded
            // playerId: player ID
        }
    }
}];


3. 使用已保存的帳戶登入 (PlayerID)

快速使用已保存的帳戶(PlayerID)通過多帳戶登錄管理功能登錄,當時已登出。

使用已保存帳戶登錄的實施步驟如下。

  1. 在用户登出并尝试再次登录时,在登录屏幕上,点击 多账户登录管理 → 调用 API 以检索保存的账户信息(PlayerID 列表)
  2. 显示在上一步中实现的 PlayerID 列表 UI
    图 3. 通过 多账户登录管理 使用保存的账户登录的示例

  3. 用户从 PlayerID 列表 UI 中选择一个特定账户并登录 → 调用 API 使用 '保存的账户信息(PlayerID)' 登录
    '调用 API 使用保存的 PlayerID 登录的示例代码' 如下所示:

    AuthV4.signInWithStoredPlayerId(playerId, useAutoSignIn, (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 app exit functionality
            // e.g.) Application.Quit();
        }
    });
    
    FHiveAuthV4::SignInWithStoredPlayerId(playerId, useAutoSignIn, 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: 实现应用程序退出功能
            // e.g.) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        }
    }));
    
    AuthV4::signInWithStoredPlayerId(playerId, useAutoSignIn, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {
        if (result.isSuccess()) {
            // 認證成功
            // playerInfo: 已認證的用戶信息
    
            // 示例:检索电子邮件信息
            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);
        }
    });
    
        AuthV4.signInWithStoredPlayerId(playerId, useAutoSignInState, 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: 实现应用程序退出功能
                                // 例如)exitProcess(
    

4. 刪除已保存的帳戶 (PlayerID)

在登出狀態下,通過多帳戶登錄管理功能刪除已保存的帳戶 (PlayerID)。

在顯示的 PlayerID 列表 UI 中,用戶可以選擇刪除已保存的帳戶 (PlayerID),而不是登錄。

圖 4. 透過 多帳號登入管理 刪除已儲存帳戶的範例


<

呼叫 API 以刪除已儲存帳戶(PlayerID)的示例代碼如下。

AuthV4.deleteStoredPlayerId(playerId, (ResultAPI result)=>{
    if (result.isSuccess()) {
        // API call succeeded
    }
});
FHiveAuthV4::DeleteStoredPlayerId(playerId, FHiveAuthV4OnDeleteStoredPlayerIdDelegate::CreateLambda([this](const FHiveResultAPI& Result) {
    if (Result.IsSuccess()) {
        // API call succeeded
    } 
}));
AuthV4::deleteStoredPlayerId(playerId, [=](ResultAPI const & result) {
    if (result.isSuccess()) {
        // API call succeeded
    }
});
AuthV4.deleteStoredPlayerId(playerId, object : AuthV4.AuthV4DeletePlayerIdListener {
    override fun onAuthV4DeletePlayerId(result: ResultAPI) {
        if (result.isSuccess) {
            // API call succeeded
        }
    }
})
AuthV4.deleteStoredPlayerId(playerId, new AuthV4.AuthV4DeletePlayerIdListener() {
    @Override
    public void onAuthV4DeletePlayerId(ResultAPI result) {
        if (result.isSuccess()) {
            // API call succeeded
        }
    }
});
AuthV4Interface.deleteStoredPlayerId(playerId) { (result) in
    if result.isSuccess() {
        // API call succeeded
    }
}
[HIVEAuthV4 deleteStoredPlayerId: playerId handler:^(HIVEResultAPI *result) {
    if([result isSuccess]){
        // API call succeeded
    }
}];


錯誤代碼

本節解釋了在實施多帳戶登錄管理功能期間,SDK 發送的錯誤代碼。

錯誤代碼 訊息 描述
NEED_INITIALIZE AuthV4NotInitialized 如果SDK設置尚未完成(AuthV4.setup)
IN_PROGRESS AuthV4InProgress 如果在收到響應之前再次調用API
INVALID_SESSION AuthV4SessionNotExist 如果請求的PlayerID在列表中不存在
INVALID_SESSION AuthV4SessionProcessingFail 保存/刪除會話失敗

 


實施備註

實施多帳戶登錄管理功能時,請注意以下事項。

  • API 持續呼叫限制

    如果在接口调用后未收到响应之前反复调用API,您可能不会收到正常的响应。请确保在调用下一个API之前等待响应。

  • 注意登入會話儲存方法

    登入會話是根據登入的帳戶存儲的,而不是根據設備。因此,根據實現方法,登入信息可能會暴露給使用相同設備的其他用戶。在使用需要安全性的服務的登入會話存儲功能時要小心。

  • 禁止使用多帳戶登錄管理功能以符合 COPPA(ageGateU13 = true)

    多帳戶登錄管理功能允許通過保存帳戶信息來實現快速登錄。然而,對於受COPPA約束的用戶,應限制多帳戶登錄管理功能,以便不保存帳戶信息且不提供基於會話的登錄。

    SDK 不會自動限制多帳戶登錄管理功能的使用,因此需要單獨的應對。此外,COPPA 限制對 13 歲以下用戶的個人信息的收集、使用和共享,因此建議避免存儲相關數據,包括會話信息。