Skip to main content

Login Integration

Client Login Access

Proceed with the following steps immediately after Step Five

Step Six: Add Callback Handling

You need to add the AuthResultObserver and LIEventObserver callbacks to handle login events.

The callback data structure is FINTLAuthResult, which includes login and account information, such as OpenID, account binding details, and account logout status.

// Add callbacks
AuthResultObserver = UINTLSDKAPI::GetAuthResultObserver().AddUObject(this, &ULevelInfiniteWindow::OnAuthResult_Callback);
// Handle AuthResultObserver callback result
void ULevelInfiniteWindow::OnAuthResult_Callback(FINTLAuthResult AuthResult)
{
if(AuthResult.MethodId == (int32)LIEnterGameMethodId::kLILoginEnterGame)
{
// LI Login succeeded, enter the game here.
}
else if (AuthResult.MethodId == (int32)LIEnterGameMethodId::kLIBindEnterGame)
{
// Social account binding succeeded inside the game
}
}

// Add callbacks
FDelegateHandle LIEventObserver;
LIEventObserver = ULevelInfiniteAPI::GetEventDelegate().AddUObject(this, &ULevelInfiniteWindow::OnLIEvent_Callback);

// Handle LIEventObserver callback result
void ULevelInfiniteWindow::OnLIEvent_Callback(FLIBaseEvent Event)
{
FString logStr;
switch(Event.EventType){
case ELIEventType::GN_READY:
{
break;
}
}
}

Step Seven: Complete the Login Process

Call the LoginChannelWithLIPass interface to open the LI PASS login component and specify the login channel for the player.

If the current account is not yet linked with LI PASS and the player is entering the game for the first time, the login component will display the interface for linking LI PASS.

ULevelInfiniteAPI::LoginChannelWithLIPass(EINTLLoginChannel::kChannelPlayStation);

Step Eight: Configure Third-Party Channel Information

LI Pass supports multiple console-end third-party channels:

PlayStation

Nintendo Switch

XSX and WinGDK

Backend Login Access

Please refer to Backend Integration in the Integration Overview.

In-Game Binding API Instructions

(1) The in-game binding process must only be initiated after login is complete. Please ensure the login process is finished first.

(2) In-Game Binding Process

  1. Call the query binding status API. If the query shows that the current account is not bound to an LI (Level Infinite) account, open the in-game binding UI.
  • Query binding status API: UINTLSDKAPI::QueryBindInfo()
  • Open in-game binding UI API: ULevelInfiniteAPI::OpenBindAccount()
  • Callback handling:
//Add callback listener
AuthResultObserver = UINTLSDKAPI::GetAuthResultObserver().AddUObject(this, &UFloatingSidebar::OnAuthResult_Callback);

//Remove callback listener
UINTLSDKAPI::GetAuthResultObserver().Remove(AuthResultObserver);

//Query the binding status when the in-game bind button is clicked
void UFloatingSidebar::OnConsoleBindAccountButtonClicked()
{
UE_LOG(LogTemp, Log, TEXT("OnConsoleBindAccountButtonClicked"));
FINTLAuthResult AuthResult;
if (UINTLSDKAPI::GetAuthResult(AuthResult))
{
// Query account binding status
UINTLSDKAPI::QueryBindInfo();
} else {
UE_LOG(LogTemp, Log, TEXT("Need login first!"));
}
}

//Handle query binding status callback
void UFloatingSidebar::OnAuthResult_Callback(FINTLAuthResult AuthResult)
{
if(AuthResult.MethodId == (int32)LIMethodId::kLIQueryBindInfo) {
if(AuthResult.RetCode == INTL_NAMESPACE::ErrorCode::SUCCESS)
{
UE_LOG(LogTemp, Verbose, TEXT("LI query bind info success bindlist = %s"), *AuthResult.BindList);
TArray <TSharedPtr<FJsonValue>> bindInfoArray;
TSharedRef<TJsonReader<TCHAR>>jsonReader = TJsonReaderFactory<TCHAR>::Create(AuthResult.BindList);
bool isSucess = FJsonSerializer::Deserialize(jsonReader, bindInfoArray);
if (isSucess)
{
UE_LOG(LogTemp, Verbose, TEXT("LI query bind info format JsonObject success"));
bool haveBindLI = false;
FString liEmail;
for(int i = 0; i < bindInfoArray.Num(); i++) // Iterate through the array to find the LI channel binding relationship
{
int32 channelId = bindInfoArray[i]->AsObject()->GetIntegerField("channelid");
FString email = bindInfoArray[i]->AsObject()->GetStringField("email");
if(channelId == (int32)EINTLLoginChannel::kChannelLevelInfinite) {
haveBindLI = true;
liEmail = email;
break;
}
}
if(!haveBindLI) {
// The current account is not bound to an LI account, open the in-game binding UI
UE_LOG(LogTemp, Verbose, TEXT("UFloatingSidebar::OpenBindAccount"));
ULevelInfiniteAPI::OpenBindAccount();
} else {
UE_LOG(LogTemp, Verbose, TEXT("Account have bind LI!"));
}
} else {
UE_LOG(LogTemp, Warning, TEXT("LI query bind info format JsonObject failed"));
}
}else if (AuthResult.RetCode == INTL_NAMESPACE::ErrorCode::NETWORK_ERROR || AuthResult.RetCode == INTL_NAMESPACE::ErrorCode::TIMEOUT) {
// Network issue, you can attempt to retry if necessary
UE_LOG(LogTemp, Warning, TEXT("LI query bind info failed, network error, ret_code = %d, ret_msg = %s"), AuthResult.RetCode, *AuthResult.RetMsg);
}else if (AuthResult.ThirdCode == (int32)LIThirdCode::kLITokenDisable || AuthResult.ThirdCode == (int32)LIThirdCode::kLITokenUnavailable || AuthResult.ThirdCode == (int32)LIThirdCode::kLITokenTimeOut) {
UE_LOG(LogTemp, Warning, TEXT("LI query bind info failed, token unavailable, ret_code = %d, ret_msg = %s"), AuthResult.RetCode, *AuthResult.RetMsg);
// If the user token becomes invalid during the in-game QueryBindInfo, a re-login is required
}else {
UE_LOG(LogTemp, Warning, TEXT("LI query bind info failed, ret_code = %d, ret_msg = %s, third_code = %d, third_msg = %s"), AuthResult.RetCode, *AuthResult.RetMsg, AuthResult.ThirdCode, *AuthResult.ThirdMsg);
}
}
}
  1. After the user successfully binds an LI account via the LI interface, you can handle the subsequent logic by listening to the ELIEventType::CONSOLE_INGAME_BIND_COMPLETE event.
//Add LIPass event listener
LIEventObserver = ULevelInfiniteAPI::GetEventDelegate().AddUObject(this, &UGameScreen::OnLIEvent_Callback);

//Remove LIPass event listener
ULevelInfiniteAPI::GetEventDelegate().Remove(LIEventObserver);

//In-game binding completion event callback
void UGameScreen::OnLIEvent_Callback(FLIBaseEvent Event)
{
switch (Event.EventType) {
case ELIEventType::CONSOLE_INGAME_BIND_COMPLETE:
{
UE_LOG(LogTemp, Display, TEXT("LIPass console in game bind complete!"));
// Todo: Navigate focus to the game UI
break;
}
case ELIEventType::RESET_GAME_UI_FOCUS:
{
// Todo: Navigate focus to the game UI
break;
}
}
}