跳轉至

登录注销

登入驗證包括以下步驟。

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 登录,而他们的设备没有登录 Apple ID,则在调用 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 Game Center帳戶以及在Android上連結他們的Google Play Games帳戶,自動登錄,而無需選擇登錄方法。它實現了自動登錄,並在自動登錄失敗的情況下執行隱式登錄。

要在 iOS 環境中使用自動登錄,您需要添加 Game Center 權限,如果您在 Unity 中勾選了「Apple GameCenter」依賴項,則它會通過 Unity PostProcess 自動添加相應的權限。在 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 产品设置

在 Windows 環境中的自動登錄

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

  • 在移動設備上,登錄狀態在登錄後始終自動保持,但在 Windows 上,只有當用戶啟用“保持我登錄”復選框(在登錄 UI 的 IdP 列表底部顯示)時,才會保持登錄狀態。在其他情況下,登錄狀態不會保持。
  • 當執行 AuthV4Helper.Connect 時,在移動設備上,如果切換到新帳戶,則新帳戶也會保持自動登錄狀態,但在 Windows 上,切換到新帳戶時,新帳戶不會保持自動登錄狀態。

隱式登入

  • 隱式登錄流程

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

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: 实现应用退出功能
        // e.g.) Application.Quit();
    } else {
        switch (result.code) {
            case ResultAPI.Code.AuthV4ConflictPlayer:
                // 账户冲突
                break;
            case ResultAPI.Code.AuthV4HelperImplifiedLoginFail:
                // 隐式登录失败
                // ex) AuthV4.showSignIn(...);
                break;
            default:
                // 其他异常
                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 登錄 (signIn)
AuthV4.Helper.signIn(object : AuthV4.Helper.AuthV4HelperListener {
    override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // 登錄成功
        } else if (result.needExit()) {
            // TODO: 實現應用程序退出功能
            // 例如) exitProcess(0)
        } else {
            when (result.code) {
                ResultAPI.Code.AuthV4ConflictPlayer -> {
                    // 帳戶衝突
                }
                ResultAPI.Code.AuthV4HelperImplifiedLoginFail -> {
                    // 隱式登錄失敗
                    // 例如) 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) 在使用不同账户进行登录时,如果出现账户冲突,会提示用户一个对话框,询问是否使用上次登录的账户进行登录。

隱式登錄行為:PC

在PC上隐式登录(例如Hive SDK Unity for Windows和其他Windows平台)(AuthV4.Helper.signIn)在首次登录后使用不同帐户登录时会自动使用上次登录的帐户进行登录。不会发生帐户冲突。

明確登錄

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

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

身份提供者列表由Hive平台根據各國的政策進行控制和提供。例如,在中國,Google Play遊戲和Facebook對於訪客不可用。

明確的登錄截圖

由SDK提供的IdP選擇UI

當使用 SDK 提供的 UI 進行實作時

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

Note

如果用户通过按下“X”按钮关闭SDK提供的身份提供者选择UI,则必须提供再次登录的方式。用户仍然未登录。

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 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 認證 UI 請求
AuthV4::showSignIn([=](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);
    }
});

API 參考: com.hive.AuthV4.showSignIn

// Hive SDK AuthV4 authentication UI request
AuthV4.showSignIn(object : AuthV4.AuthV4SignInListener {
    override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // Authentication successful
            // playerInfo: Authenticated user information

            // 獲取電子郵件信息的示例
            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: 實現應用程序退出功能
        // e.g.) 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);
    }
}];

明確的登錄自定義

可自定义的显式登录用户界面可以使用 providerTypeList 实现。providerTypeList 是在调用 AuthV4.setup() 方法初始化 Hive SDK 时返回的响应回调处理程序,或者在初始化后调用 AuthV4.Helper.getIDPList() 方法时返回的。此功能用于当您希望根据游戏用户界面显示登录屏幕或主要暴露与特定身份提供者的集成时。在实现可自定义的用户界面后,通过根据用户的操作调用 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 帳戶不同。我們提供指導以統一這兩個帳戶,以便為未來的成就或排行榜使用做好準備。

  • 檢查 UI 以使用 SDK 提供的 DevicePlayer

以下是一個檢查 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 認證的訪客狀態下,PlayerID 的 playerInfo 中沒有 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 signIn: HIVEProviderTypeGuest handler: ^(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: 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 by Type, 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 整合期間顯示一次;之後將不再顯示。
  • 在訪客登錄期間不會顯示用戶名輸入畫面。

認證令牌密鑰驗證

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

如果不允許使用相同帳戶的重複訪問,遊戲伺服器將在首次連接的設備上顯示通知消息,然後終止遊戲,允許遊戲在後來連接的設備上維持。在這種情況下,如果您嘗試在不終止遊戲的情況下再次訪問遊戲,您的遊戲記錄可能無法正確反映。要實現此功能,您需要管理一個有效的令牌密鑰或使用它來管理遊戲本身的會話密鑰。

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

在背景中檢測 IdP 帳戶變更

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

當Apple Game Center帳戶更改時,iOS會運作,而當Google Play Games帳戶更改時,Android會運作,並且只有當當前登錄的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 開始,當訪客用戶登出時會返回錯誤代碼。之後,客戶端和服務器會話將保持。
  • 通過以 set 開頭的方法在 SDK 中設置的值的有效範圍在應用程序的生命週期內保持,無論登錄或登出狀態。

如果您已經登錄到 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 您的遊戲中心登錄已被取消。
請在 [設定 > 遊戲中心] 登錄以與您的遊戲中心帳戶同步,然後重試。