跳转至

登录注销

在认证中,登录由以下步骤组成。

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。

Note
Note
  • 由于中国无法使用 Google Play 游戏,因此无法在 Android 上使用隐式登录。
  • 由于中国无法使用 Facebook,因此 IdP 列表中不包括 Facebook。
  • 由于中国 IP 仅允许实名认证的用户充值或消费服务(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 登录提示弹窗会自动显示,因此游戏工作室无需单独显示提示 弹窗

自动登录和隐式登录

自动登录

隐式登录是一种用户不选择登录方式,而是自动登录iOS上的Apple Game Center账户或Android上的Google Play Games账户的方法。在自动登录失败后执行隐式登录。

在iOS环境中使用自动登录,您需要添加Game Center权限。在Unity中,如果您勾选了“Apple GameCenter”依赖项,它将通过Unity PostProcess自动添加权限。对于iOS Native,Xcode将自动添加Game Center权限。

离线模式

Hive SDK v4 23.1.0及更高版本提供自动登录功能(AuthV4.signIn使用ProviderType.AUTO,或AuthV4.Helper.signIn),即使用户的设备未连接到网络。要使用离线模式,请按照以下说明进行操作:

  1. 应用程序必须至少在在线模式下运行一次, resulting in a successful explicit, implicit, guest, or custom login, 并且随后发放了 playerIdplayerToken
    从应用程序开发者的角度来看,必须至少成功执行过一次 AuthV4.Helper.signInAuthV4.showSignInAuthV4.signInWithAuthKey,并在在线状态下通过回调接收 playerIdplayerToken。从用户的角度来看,他们必须在设备连接到网络时至少成功登录过一次应用程序。然而,如果用户的账户在他们上次在线登录尝试时被暂停或限制,他们将无法在离线模式下登录。

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

Windows 环境中的自动登录

Windows 环境也支持自动登录,可以在 Hive 控制台应用中心 中启用/禁用。 但是,Windows 的自动登录与移动设备的行为不同。 Windows 中的自动登录有以下不同之处。

  • 在移动设备上,登录后会自动保持登录状态,但在Windows上,只有当用户启用登录保持复选框(在登录UI中IdP列表下方显示)时,才会保持登录状态。在其他情况下不会保持登录状态。
  • 当执行 AuthV4Helper.Connect 时,在移动设备上如果切换到新账户,新账户也会保持自动登录状态,但在Windows上切换到新账户时,新账户不会保持自动登录状态。

隐式登录

  • 隐式登录的登录流程

AuthV4.Helper.signIn 尝试通过使用 PlayerID 的认证令牌密钥进行自动登录。如果之前登录生成的令牌密钥不存在,游戏将自动在 iOS 上登录 Apple Game Center,在 Android 上登录 Google Play Games。如果登录失败,它会根据响应显示适当的登录页面。

AuthV4.Helper.signIn尝试使用PlayerID的认证令牌密钥进行自动登录。如果没有之前登录的认证令牌密钥,iOS的情况下会自动登录到Apple Game Center,Android的情况下会自动登录到Google Play游戏。如果登录失败,将根据响应值构建适当的登录界面。

Note

要使用自动登录,必须添加Game Center Entitlement。如果勾选了'Apple GameCenter' Dependency,Unity PostProcess会自动添加该Entitlement。

Note

您必须添加游戏中心权限才能使用自动登录。如果您已检查“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:
// 其他异常
break;
}
}
});
#include "HiveAuthV4.h"

// 尝试 Hive SDK 登录 (signIn)
FHiveAuthV4::Helper::SignIn(FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& 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 FHiveResultAPI::ECode::AuthV4ConflictPlayer:
                                // 账户冲突
                                break;
                        case FHiveResultAPI::ECode::AuthV4HelperImplifiedLoginFail:
                                // 隐式登录失败
                                // 例如) AuthV4.showSignIn(...);)
                                break;
                        default:
                                // 其他异常
                                break;
                }
        }
}));

API 参考: Auth4::signIn

// 尝试 Hive SDK 登录 (signIn)
AuthV4::Helper::signIn([=](ResultAPI const & result, std::shared\_ptr playerInfo) {

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

API 参考: com.hive.Auth4.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.Auth4.signIn

// 尝试 Hive SDK 登录 (signIn)
AuthV4.Helper.signIn(new AuthV4.Helper.AuthV4HelperListener() {
    @Override
    public void onAuthV4Helper(ResultAPI result, AuthV4.PlayerInfo playerInfo) {

        if (result.isSuccess()) {
            // 登录成功
        } else if (result.needExit()) {
            // TODO: 实现应用退出功能
            // ex) System.exit(0);
        } else {
            switch(result.code) {
                case AuthV4ConflictPlayer:
                    // 账户冲突
                    break;
                case AuthV4HelperImplifiedLoginFail:
                    // 隐式登录失败
                    // ex) AuthV4.showSignIn(...);
                    break;
                default:
                    // 其他异常
                    break;
            }
        }
    }
});

API 参考: AuthV4Interface.signIn

// 尝试 Hive SDK 登录 (signIn)
AuthV4Interface.helper().signIn() { (result, playerInfo) in

    if result.isSuccess() {
        // 登录成功
    }
    else if result.needExit() {
        // TODO: 实现应用退出功能
        // ex) exit(0)
    }
    else {
        switch result.getCode() {
        case .authV4ConflictPlayer:
            // 账户冲突
        case .authV4HelperImplifiedLoginFail:
            // 隐式登录失败
            // ex) AuthV4Interface.showSignIn() { (result, playerInfo)
            // // 做一些事情...
            // }
        default:
            // 其他异常
            break
        }
    }
}

API 参考: HIVEAuth4:signIn

// 尝试 Hive SDK 登录 (signIn)
[[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 Windows等,Windows)上,隐式登录(AuthV4.Helper.signIn)在初始登录后会自动使用上次登录的账户进行登录,而不会导致任何账户冲突。

显式登录

显式登录是指用户选择身份提供者(IdP)进行身份验证的过程。如果玩家未能执行自动登录和隐式登录,则应实现游戏,使玩家在点击标题时转到游戏标题屏幕并执行显式登录。

显式登录由Hive SDK提供的用户界面或在使用身份提供者(IdP)列表初始化Hive SDK后在游戏中自定义的用户界面组成。如果您自定义用户界面,请参阅自定义显式登录用户界面

Hive 平台根据各国的政策控制并提供 IdP 列表。例如,Google Play 游戏、Facebook 和游客登录在中国不可用。

显式登录的示例屏幕

由Hive SDK提供的IdP选择用户界面


在使用 Hive SDK 提供的 UI 实现功能时

要使用 Hive SDK 提供的 UI 实现显式登录,您可以通过调用 showSignIn() 方法来显示 IdP 列表 UI。

Note

确保在用户点击SDK提供的IdP选择UI中的X按钮关闭后,提供再次登录的方法。因为用户尚未登录。

Note

如果您想自定义显式登录,请参见这里

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:    
                // 其他异常情况    
                break;    
        }    
    }    
});
#include "HiveAuthV4.h"

// Hive SDK 登录(signIn) 尝试
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::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:    
                // 隐式登录失败    
                // ex) AuthV4.showSignIn(...);    
                break;    
            default:    
                break;    
        }    
    }    
});

API 参考: hive.AuthV4.showSignIn

// 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.showSignIn

// Hive SDK AuthV4 认证 UI 请求    
    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: 实现应用程序退出功能    
            // 例如) System.exit(0);    
        }    
    }    
});

API 参考: HIVEAuthV4:signIn

var email = String()    
    // Hive SDK AuthV4 认证 UI 请求    
    AuthV4Interface.showSignIn { (result, playerInfo) in    

    if result.isSuccess() {    
        // 认证成功    
        // playerInfo: 认证的用户信息    
        // 邮箱信息查询示例    
        if let playerInfo = playerInfo {    
            // 查找存在providerEmail的providerInfo(当前登录的provider)    
            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:signIn

// Hive SDK 登录(signIn) 尝试    
[[HIVEAuthV4 helper] signIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {

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

隐式登录操作:移动

移动端(Hive SDK Unity Android等Android/iOS平台)隐式登录(AuthV4.Helper.signIn)在首次登录后,如果使用其他账户登录,将会出现账户冲突情况,并弹出窗口询问用户是否使用最后登录的账户进行登录。

隐式登录操作: 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: 实现应用程序退出功能
        // 例如) 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 认证 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: 实现应用退出功能
                // 例如) exitProcess(0)
        }
}
})

API 参考: com.hive.AuthV4.showSignIn

// Hive SDK AuthV4 认证 UI 请求
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: 实现应用退出功能
                // 例如) 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(当前登录的provider)
                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(当前登录的provider)
                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);
}
}];

显式登录自定义

显式登录的自定义 UI 可以通过 providerTypeList 来实现。providerTypeList 是在初始化 Hive SDK 时调用 AuthV4.setup() 方法,或者在初始化后调用 AuthV4.Helper.getIDPList() 方法时返回的响应回调处理程序。当需要根据游戏 UI 显示登录界面或主要显示与特定 IdP 的集成时,可以使用此功能。在实现自定义 UI 后,请根据用户的操作调用所需的 ProviderType 的 signIn() 方法来实现登录。

Note
  • 仅在登录界面显示Facebook联动按钮的UI示例截图

以下是一个假设用户在自定义的显式登录 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.INSTANCE.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 账户和实际设备上登录的 IdP 账户(DevicePlayer)可能不同。为了将来使用成就或排行榜,我们提供指导信息以统一这两个账户。

  • 确认是否使用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:    
                // 账户冲突    
                // ex) 使用 Hive UI 时     
                // AuthV4.Helper.showConflict(...);    
                // or    
                // ex) 实现 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()
                        // 例如) 实现 Game 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:    
            // 账户冲突    
            // ex) 使用 Hive UI 时     
            // AuthV4::Helper::showConflict(...);    
            // or    
            // ex) 实现 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 -> {    
                    // 账户冲突    
                    // ex) 使用 Hive UI 时    
                    // AuthV4.Helper.showConflict(...);    
                    // 或者    
                    // ex) 实现 GameUI 时    
                    // AuthV4.Helper.resolverConflict(...);// 当前用户选择时    
                    // AuthV4.Helper.switchAccount(...);// 用户切换选择时    
                }    
                else -> {    
                    // 其他异常情况    
                }    
            }    
        }    
})

API 参考: AuthV4.Helper.INSTANCE.syncAccount

import com.hive.AuthV4;    
    import com.hive.ResultAPI;    
    AuthV4.ProviderType providerType = AuthV4.ProviderType.GOOGLE;    
    AuthV4.Helper.INSTANCE.syncAccount(providerType, (result, playerInfo) -> {    
        switch (result.getCode()) {    
            case Success:    
                // 正常    
                break;    
            case AuthV4ConflictPlayer:    
                // 账户冲突    
                // ex) 使用 Hive UI 时    
                // AuthV4.Helper.INSTANCE.showConflict(...);    
                // 或者    
                // ex) 实现 GameUI 时    
                // AuthV4.Helper.INSTANCE.resolverConflict(...);// 当前用户选择时    
                // AuthV4.Helper.INSTANCE.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:    
            // 账户冲突    
            // ex) 使用 Hive UI 时     
            // AuthV4Interface.helper().showConflict(...);    
            // 或者    
            // ex) 实现 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:    
                // 账户冲突    
                // ex) 使用 Hive UI 时     
                // [[HIVEAuthV4 helper] showConflict: ...];    
                // or    
                // ex) 实现 GameUI 时    
                // [[HIVEAuthV4 helper] resolverConflict:...];// 当前用户选择时    
                // [[HIVEAuthV4 helper] switchAccount:...];// 用户切换选择时     
                break;    
            default:    
                // 其他异常情况    
                break;    
        }    
}];

游客登录

支持用户在未选择 IdP 的情况下以游客身份使用游戏的游客登录功能。可以在 Hive SDK 提供的显式登录 UI 中选择游客,也可以在游戏中进行自定义实现游客登录。Windows 环境不支持游客登录。

在访客登录时,必须遵守以下政策。

客户登录政策

  • 请实现IdP认证用户和访客用户都可以同样使用游戏的功能。 在访客登录时,几乎可以使用Hive平台的所有功能。因此,请确保在您的游戏中,作为访客登录的用户可以与IdP关联的用户一样使用游戏。例如,访客用户也应该能够在游戏中购买和支付物品。
    • 请不要为访客用户提供注销功能。 用户在以访客身份登录后,如果注销,将无法再以相同的PlayerID登录。因此,当用户以访客身份登录时,请不要提供注销按钮,以防止他们注销。
    • 中国访客登录禁止政策 由于使用中国IP的情况下,只有经过实名认证的用户才能进行充值和消费服务(自17年5月1日起实施),因此可以使用中国IP登录的IdP列表中不包括访客登录。

要执行访客登录,请将ProviderType.GUEST作为参数传递给signIn()方法。 以下是执行访客登录的示例代码。

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()) {
                // 调用成功 (PlayerInfo: 认证的用户信息)
        }
}));

API 参考: Auth4::signIn

#include <HIVE_SDK_Plugin/HIVE_CPP.h>    
    using namespace std;     
    using namespace hive;    
    AuthV4::signIn(ProviderType::GUEST, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {    
        if (result.isSuccess()) {    
            // 认证成功    
            // playerInfo: 认证的用户信息    
        }    
});

API 参考: AuthV4.signIn

import com.hive.AuthV4    
    import com.hive.ResultAPI    
    AuthV4.signIn(AuthV4.ProviderType.GUEST, object : AuthV4.AuthV4SignInListener {    
        override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {    
            if (result.isSuccess) {    
                // 认证成功    
                // playerInfo: 认证的用户信息    
            }    
        }    
})

API 参考: com.hive.Auth4.signIn

import com.hive.AuthV4;    
    import com.hive.ResultAPI;    
    AuthV4.INSTANCE.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: 认证的用户信息    
        }    
}];

自定义登录

自定义登录定制登录 功能,允许在 Hive 提供的 IdP 之外,通过游戏本身集成的 IdP 实现登录。请根据 认证 v4 自定义认证 创建在调用自定义登录 API 时使用的认证密钥(authKey)。

通过调用自定义登录 API 后,您可以通过回调传递的 PlayerInfo 类实例访问 customProviderInfoData 数据,以确认自定义登录的用户信息。 customProviderInfoDataProviderType(enum) 都设置为 CUSTOM,并可以通过 ProviderName(String) 进行详细区分。

游戏中实现自定义登录的 IdP 信息不包含在 AuthV4 类的 setup()showSignIn() 方法调用结果中。

如果在首次执行自定义登录后获得了 playerId 和 playerToken,则在重新调用自定义登录 API 时,authV4SessionExist(code) 的 Result 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" 类型直接实现的推特登录
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, 自定义类型是固定的
                                FString ProviderName = ProviderInfo->ProviderName; // 需要通过ProviderName区分
                                FString ProviderUserId = ProviderInfo->ProviderUserId; // 用于自定义实现的Twitter登录的用户id
                        }
                } else if (Result.NeedExit()) {
                        // TODO: 实现应用程序退出功能
                        // 例如) 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, 自定义类型固定,因此需要通过 providerName 区分
                                    providerInfo.providerName   // "CUSTOM_TWITTER"
                                    providerInfo.providerUserId // 用于自定义实现的 Twitter 登录的用户 id
                            }
                    }
                    else if (result.needExit()) {
                            // TODO: 实现应用程序退出功能
                            // 例如) exitProcess(0)
                    }
                    else if (result.code == ResultAPI.Code.AuthV4SessionExist) {
                            // 如果已经发放了 playerId 和 playerToken,需要自动登录
                            // TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener)
                    }
                    else if (result.code == ResultAPI.Code.AuthV4NotInitialized) {
                            // TODO: 需要初始化 SDK
                    }
                    else if (result.code == ResultAPI.Code.AuthV4InvalidParam) {
                            // TODO: 确认传递的 authKey 的值是否为 NULL 或空值
                    }
            }
    })

    }

API 参考: com.hive.Auth4.signIn

// 在游戏中实现的 Twitter 登录
    Game.Login("CUSTOM_TWITTER") { authKey: String ->
            AuthV4.INSTANCE.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(); // 用于自定义实现的推特登录的用户 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

// 游戏中直接实现的推特登录
    [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实现该功能。

获取 TalkPlus 登录令牌

通过认证 v4 接口,在完成 signIn() 后调用 AuthV4.getHiveTalkPlusLoginToken API 获取的登录令牌用于 Hive TalkPlus 登录。

Note

请参考相关指南 Hive TalkPlus 登录指南

AuthV4.getHiveTalkPlusLoginToken((ResultAPI result, String loginToken) =&gt; {
if (result.isSuccess()) {
    // SUCCESS
    // TODO: 传递的 loginToken 值确认后进行 HiveTalkPlus 登录
}
});
// Kotlin
AuthV4.getHiveTalkPlusLoginToken(object : AuthV4.AuthV4GetHiveTalkPlusLoginTokenListener {
        override fun onAuthV4GetHiveTalkPlusLoginToken(resultApi: ResultAPI, loginToken: String?) {
                if (resultApi.isSuccess) {
                        // SUCCESS
                }
        }
}
// Java
com.hive.AuthV4.INSTANCE.getHiveTalkPlusLoginToken(new com.hive.AuthV4.AuthV4GetHiveTalkPlusLoginTokenListener() {
        @Override
        public void onAuthV4GetHiveTalkPlusLoginToken(@NotNull ResultAPI result, @Nullable String loginToken) {
if (result.isSuccess()) {
// SUCCESS
}
        }
});
// Swift
AuthV4Interface.getHiveTalkPlusLoginToken { result, loginToken in
        if (result.isSuccess()) {
                // SUCCESS
        }
}
// Objective-c
[HIVEAuthV4 getHiveTalkplusLoginToken:^(HIVEResultAPI* result, NSString* loginToken) {
        if ([result isSuccess]) {
                // SUCCESS
        }
}];

在后台检测 IdP 账户更改

用户可以在游戏运行时通过设备设置更改 Apple Game Center 或 Google Play 游戏账户。如果需要在游戏运行时检查 IdP 账户是否与当前 PlayerID 的 IdP 账户不同,请在 SDK 初始化后调用 setProviderChangedListener()。调用该 API 后,您可以在游戏恢复时接收到设备上设置的 IdP 账户已更改的事件。

iOS在更改Apple Game Center,Android在更改Google Play游戏的账户时工作,并且只有在当前登录的PlayerID与该IdP关联时才会传递响应。当收到IdP账户更改事件时,将为用户构建UI,以便用户选择是否使用设备上登录的IdP账户。如果用户选择设备上登录的IdP账户,则调用signOut进行注销,然后进行隐式登录。

Warning

自2021年7月起安装了Google Play游戏的设备,由于Google Play游戏的运行问题,无法在后台更改IdP账户。

Note

此功能可能会导致游戏暂停并请求更改帐户,仅在需要帐户同步的时刻,如进入大厅或商店时有限制地使用。

以下是一个示例代码,用于设置在用户重新开始游戏时接收设备上设置的 IdP 账户已更改的事件。

API 参考: hive.AuthV4.setProviderChangedListener

using hive;

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

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

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

API 参考: AuthV4::setProviderChangedListener

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

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

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

API 参考: AuthV4.setProviderChangedListener

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

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

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

API 参考: com.hive.AuthV4.setProviderChangedListener

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

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

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

API 参考: AuthV4Interface.setProviderChangedListener

import HIVEService

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

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

API 参考: HIVEAuthV4:setProviderChangedListener

#import <HIVEService/HIVEService-Swift.h>

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

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

游戏数据初始化

在初始化游戏数据时,请勿调用注销。由于 PlayerID 不会被删除,因此可能会发生帐户间的冲突。为了确保用户能够继续使用当前登录的帐户进行游戏,请在用户明确请求之前避免调用注销。

登出

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

如果您已执行 Hive 登录,则 PlayerID 和认证令牌密钥已发放。注销是指初始化 PlayerID 和认证令牌密钥的功能。调用 signOut() 方法完成注销后,将转到游戏标题,并在点击标题时执行显式登录。

Note
  • 在访客登录状态下注销时,将无法再找到相同的 PlayerID,因此请在访客状态下实现不提供注销功能。
  • 即使注销,PlayerID 的 IdP 关联状态也不会改变。
  • 注销完成后,将转到游戏标题,点击标题时将执行显式登录。
  • 注销后重新启动应用程序时,将首先执行隐式登录。

以下是执行注销的示例代码。

API 参考: hive.AuthV4.signOut

using hive;    

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

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

API 参考: AuthV4::signOut

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

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

API 参考: AuthV4.Helper.signOut

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

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

API 参考: AuthV4.Helper.INSTANCE.signOut

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

AuthV4.Helper.INSTANCE.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]에서 로그인한 후 다시 시도해주세요.
英语 Your login to the Game Center has been canceled.
Log in at [Settings >; Game Center] to sync to the Game Center Account and try again.
日语 Apple Game Center ログインがキャンセルされました。
Game Center アカウントと連動するには [設定 >; Game Center] にログインした後、再度お試しください。
简体中文 Apple Game Center已退出登录。
若想与Game Center账号同步,请在设备[设置 >; Game Center]中重新登录后再试。
繁体中文 登入Apple Game Center已取消。
若想連動Game Center帳號,請至[設定 >; Game Center]登入後,再試一次。
法语 Ta connexion au Game Center a été annulée.
Connecte-toi dans [Réglages >; Game Center] pour synchroniser ton compte Game Center et essaie de nouveau.
德语 Das Einloggen ins Apple Game Center wurde abgebrochen.
Die Synchronisation mit dem Game Center-Konto läuft über [Einstellungen >; Game Center]. Logge dich ein und versuche es erneut.
俄语 Ваш авторизация в Game Center была отменена.
Авторизуйтесь в Game Center через [Настройки >; Game Center] и повторите попытку.
西班牙语 Tu Inicio de Sesión en Game Center ha sido cancelado.
Inicia Sesión en [Configuración >; Game Center] para sincronizar a la Cuenta de Game Center, e inténtalo de nuevo.
葡萄牙语 O seu login no Game Center foi cancelado.
Faça o login em [Configurações >; Game Center] para sincronizar com a Conta do Game Center e tente novamente.
印尼语 Login ke Apple Game Center telah dibatalkan.
Hubungkan akun Game Center dengan login di [Pengaturan >; Game Center] dan coba lagi.
马来语 Log masuk ke Game Center anda telah dibatalkan.
Log masuk di [Tetapan >; Game Center] untuk disegerakkan ke Akaun Game Center dan cuba lagi.
越南语 Đã hủy bỏ đăng nhập vào Apple Game Center.
Đăng nhập tại [Cài đặt >; Game Center] để đồng bộ với tài khoản Game Center và thử lại.
泰语 การล็อกอินเข้า Game Center ของคุณถูกยกเลิก
ล็อกอินที่ [การตั้งค่า >; Game Center] เพื่อเชื่อมต่อบัญชี Game Center และโปรดลองอีกครั้ง
意大利语 L'accesso all'Apple Game Center è stato annullato.
Fai log-in su [Impostazioni >; Game Center] per sincronizzare il tuo account con il Game Center e riprova.
土耳其语 Apple Oyun Merkezine girişiniz iptal edilmiştir.
Oyun Merkezi Hesabına ulaşmak için [Ayarlar >; Oyun Merkezi]'nden giriş yapın ve tekrar deneyin.
阿拉伯语 تم إلغاء تسجيل الدخول إلى مركز الألعاب.
سجل الدخول إلى [الإعدادات >; مركز الألعاب] للمزامنة مع حساب مركز الألعاب وحاول مرة أخرى。