一克泥在线服务
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using IchniOnline.Online.Models;
|
||||
using IchniOnline.Online.Network;
|
||||
using IchniOnline.Online.Network.Models;
|
||||
using TapSDK.Login;
|
||||
@@ -30,11 +32,24 @@ namespace IchniOnline.Online.Logic
|
||||
/// </summary>
|
||||
public static event Action OnLoginCanceled;
|
||||
|
||||
/// <summary>
|
||||
/// TapTap 未绑定账号时触发,参数为 pendingBindOauthId 和浏览器绑定页面 URL
|
||||
/// </summary>
|
||||
public static event Action<string, string> OnTapTapUnbound;
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在进行登录流程,用于防止并发登录请求
|
||||
/// </summary>
|
||||
public static bool IsLoggingIn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前未绑定的 TapTap oauthId
|
||||
/// </summary>
|
||||
private static string _pendingBindOauthId;
|
||||
private static CancellationTokenSource _pollingCts;
|
||||
|
||||
private const string WebBaseUrl = "https://ichni.hoshino.fan";
|
||||
|
||||
#region TapTap Login
|
||||
|
||||
/// <summary>
|
||||
@@ -108,9 +123,23 @@ namespace IchniOnline.Online.Logic
|
||||
|
||||
if (result.IsSuccess && result.Data != null)
|
||||
{
|
||||
LoginCacheManager.SaveAuthSession(result.Data.token, result.Data);
|
||||
IchniOnlineApiClient.Instance.JwtToken = result.Data.token;
|
||||
OnLoginSuccess?.Invoke(result.Data);
|
||||
if (!string.IsNullOrEmpty(result.Data.pendingBindOauthId))
|
||||
{
|
||||
_pendingBindOauthId = result.Data.pendingBindOauthId;
|
||||
var bindUrl = $"{WebBaseUrl}/bind?method=0&id={_pendingBindOauthId}";
|
||||
OnTapTapUnbound?.Invoke(_pendingBindOauthId, bindUrl);
|
||||
OpenBrowserBindPage(bindUrl);
|
||||
|
||||
_pollingCts?.Cancel();
|
||||
_pollingCts = new CancellationTokenSource();
|
||||
PollBindStatusAsync(_pendingBindOauthId, _pollingCts.Token).Forget();
|
||||
}
|
||||
else
|
||||
{
|
||||
LoginCacheManager.SaveAuthSession(result.Data.token, result.Data);
|
||||
IchniOnlineApiClient.Instance.JwtToken = result.Data.token;
|
||||
OnLoginSuccess?.Invoke(result.Data);
|
||||
}
|
||||
}
|
||||
else if (result.IsSuccess && result.Data == null)
|
||||
{
|
||||
@@ -132,6 +161,94 @@ namespace IchniOnline.Online.Logic
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenBrowserBindPage(string url)
|
||||
{
|
||||
Application.OpenURL(url);
|
||||
}
|
||||
|
||||
private static async UniTaskVoid PollBindStatusAsync(string oauthId, CancellationToken cancellationToken)
|
||||
{
|
||||
var startTime = DateTime.UtcNow;
|
||||
var timeout = TimeSpan.FromMinutes(5);
|
||||
var pollInterval = TimeSpan.FromSeconds(2);
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (DateTime.UtcNow - startTime > timeout)
|
||||
{
|
||||
IsLoggingIn = false;
|
||||
OnLoginFailed?.Invoke("绑定超时");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await IchniOnlineApiClient.Instance.GetAsync<BindStatusDto>(
|
||||
$"/api/auth/third-party/bind-status?oauthId={oauthId}",
|
||||
cancellationToken);
|
||||
|
||||
if (result.IsSuccess && result.Data != null)
|
||||
{
|
||||
if (result.Data.status == "bound" && !string.IsNullOrEmpty(result.Data.token))
|
||||
{
|
||||
var loginResponse = new LoginResponseDto
|
||||
{
|
||||
token = result.Data.token,
|
||||
user = result.Data.user
|
||||
};
|
||||
|
||||
LoginCacheManager.SaveAuthSession(result.Data.token, loginResponse);
|
||||
IchniOnlineApiClient.Instance.JwtToken = result.Data.token;
|
||||
IsLoggingIn = false;
|
||||
OnLoginSuccess?.Invoke(loginResponse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[IchniOnlineAuthService] Polling error: {ex.Message}");
|
||||
}
|
||||
|
||||
await UniTask.Delay(pollInterval,DelayType.Realtime,PlayerLoopTiming.Update,cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleIchniProtocolCallback(string token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
{
|
||||
OnLoginFailed?.Invoke("浏览器回调 token 为空");
|
||||
return;
|
||||
}
|
||||
|
||||
_pollingCts?.Cancel();
|
||||
_pollingCts = null;
|
||||
_pendingBindOauthId = null;
|
||||
|
||||
IchniOnlineApiClient.Instance.JwtToken = token;
|
||||
|
||||
LoginCacheData cachedData = LoginCacheManager.CachedData;
|
||||
if (cachedData != null)
|
||||
{
|
||||
cachedData.jwtToken = token;
|
||||
cachedData.hasServerSession = true;
|
||||
}
|
||||
|
||||
OnLoginSuccess?.Invoke(new LoginResponseDto
|
||||
{
|
||||
token = token,
|
||||
user = cachedData != null ? new UserResponseDto
|
||||
{
|
||||
userId = cachedData.userId,
|
||||
username = cachedData.name,
|
||||
displayName = cachedData.displayName,
|
||||
avatarUrl = cachedData.avatarUrl,
|
||||
permission = cachedData.permission
|
||||
} : null
|
||||
});
|
||||
}
|
||||
|
||||
private static void UnsubscribeTapTapEvents(
|
||||
Action<TapTapAccount> onSuccess,
|
||||
Action onCanceled,
|
||||
|
||||
Reference in New Issue
Block a user