From 0be84a25853edde65a1470be535bb3c12122ac09 Mon Sep 17 00:00:00 2001
From: DismissedLight <1686188646@qq.com>
Date: Mon, 14 Nov 2022 16:37:17 +0800
Subject: [PATCH] support PROD salt for #207
---
.../Snap.Hutao/Core/Convert/Md5Convert.cs | 5 ++
.../Snap.Hutao/Core/CoreEnvironment.cs | 28 +------
.../Snap.Hutao/Web/Hoyolab/ApiEndpoints.cs | 35 ++++++++-
.../Web/Hoyolab/App/Account/AccountClient.cs | 77 +++++++++++++++++++
.../Web/Hoyolab/App/Account/LtokenWrapper.cs | 26 +++++++
.../Web/Hoyolab/Passport/PassportClient.cs | 2 +-
...ountInfo.cs => ActionTicketAccountInfo.cs} | 2 +-
.../Takumi/Auth/ActionTicketWrapper.cs | 2 +-
.../Hoyolab/Takumi/Binding/BindingClient.cs | 17 ++++
.../Hoyolab/Takumi/Binding/BindingClient2.cs | 6 +-
.../Hoyolab/Takumi/Binding/GenAuthKeyData.cs | 2 +
.../Web/Response/KnownReturnCode.cs | 5 ++
12 files changed, 173 insertions(+), 34 deletions(-)
create mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/AccountClient.cs
create mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/LtokenWrapper.cs
rename src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/{AccountInfo.cs => ActionTicketAccountInfo.cs} (98%)
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Convert/Md5Convert.cs b/src/Snap.Hutao/Snap.Hutao/Core/Convert/Md5Convert.cs
index f52ee927..001b5802 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Convert/Md5Convert.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Convert/Md5Convert.cs
@@ -22,3 +22,8 @@ internal abstract class Md5Convert
return System.Convert.ToHexString(hash);
}
}
+
+internal class RSAConvert
+{
+
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs
index 6f4ed18c..da63244c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs
@@ -16,33 +16,6 @@ namespace Snap.Hutao.Core;
///
internal static class CoreEnvironment
{
- // 计算过程:https://github.com/UIGF-org/Hoyolab.Salt
-
- ///
- /// 动态密钥1的K2盐
- ///
- public const string DynamicSecretK2Salt = "fdv0fY9My9eA7MR0NpjGP9RjueFvjUSQ";
-
- ///
- /// 动态密钥1的LK2盐
- ///
- public const string DynamicSecretLK2Salt = "jEpJb9rRARU2rXDA9qYbZ3selxkuct9a";
-
- ///
- /// 动态密钥2的X4盐
- ///
- public const string DynamicSecretX4Salt = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs";
-
- ///
- /// 动态密钥2的X6盐
- ///
- public const string DynamicSecretX6Salt = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v";
-
- ///
- /// LoginApi的盐
- ///
- public const string DynamicSecretPRODSalt = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS";
-
///
/// 米游社请求UA
///
@@ -55,6 +28,7 @@ internal static class CoreEnvironment
///
/// 动态密钥
+ /// https://github.com/UIGF-org/Hoyolab.Salt
///
public static readonly ImmutableDictionary DynamicSecrets = new Dictionary()
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/ApiEndpoints.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/ApiEndpoints.cs
index d4aba5ca..a39a503c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/ApiEndpoints.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/ApiEndpoints.cs
@@ -129,10 +129,15 @@ internal static class ApiEndpoints
///
public const string UserGameRolesByCookie = $"{ApiTaKumiBindingApi}/getUserGameRolesByCookie?game_biz=hk4e_cn";
+ ///
+ /// 用户游戏角色
+ ///
+ public const string UserGameRolesByStoken = $"{ApiTaKumiBindingApi}/getUserGameRolesByStoken";
+
///
/// AuthKey
///
- public const string GenAuthKey = $"{ApiTaKumiBindingApi}/genAuthKey";
+ public const string BindingGenAuthKey = $"{ApiTaKumiBindingApi}/genAuthKey";
#endregion
#region Auth
@@ -179,7 +184,7 @@ internal static class ApiEndpoints
// https://sdk-static.mihoyo.com/hk4e_cn/mdk/launcher/api/content?key=eYd89JmJ&language=zh-cn&launcher_id=18
#endregion
- #region ma-cn-session
+ #region LoginApi
///
/// 获取 CookieToken
@@ -192,8 +197,30 @@ internal static class ApiEndpoints
public const string AccountVerifyLtoken = $"{PassportApiV4}/account/ma-cn-session/web/verifyLtoken";
#endregion
+ #region WebAccountApi
+
+ ///
+ /// 通过通行证Cookie登录
+ ///
+ /// 通行证Cookie登录
+ public static string AccountLoginByCookie()
+ {
+ return $"{WebApiAccountApi}/login_by_cookie?t={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
+ }
+ #endregion
+
#region App
+ ///
+ /// 另一个AuthKey
+ ///
+ public const string AppAccountGenAuthKey = $"{AppAuthApi}/genAuthKey";
+
+ ///
+ /// 通过 Stoken 获取 Ltoken
+ ///
+ public const string AppAccountGetLTokenBySToken = $"{AppAuthApi}/getLTokenBySToken";
+
///
/// 小组件数据
///
@@ -209,6 +236,7 @@ internal static class ApiEndpoints
private const string ApiTakumiRecordApi = $"{ApiTakumiRecord}/game_record/app/genshin/api";
private const string App = "https://app.mihoyo.com";
+ private const string AppAuthApi = $"{App}/account/auth/api";
private const string AppCardApi = $"{App}/game_record/app/card/api";
private const string BbsApi = "https://bbs-api.mihoyo.com";
@@ -224,5 +252,8 @@ internal static class ApiEndpoints
private const string SdkStatic = "https://sdk-static.mihoyo.com";
private const string SdkStaticLauncherApi = $"{SdkStatic}/hk4e_cn/mdk/launcher/api";
+ private const string WebApiAccount = "https://webapi.account.mihoyo.com";
+ private const string WebApiAccountApi = $"{WebApiAccount}/Api";
+
private const string AnnouncementQuery = "game=hk4e&game_biz=hk4e_cn&lang=zh-cn&bundle_id=hk4e_cn&platform=pc®ion=cn_gf01&level=55&uid=100000000";
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/AccountClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/AccountClient.cs
new file mode 100644
index 00000000..cada6339
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/AccountClient.cs
@@ -0,0 +1,77 @@
+using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
+using Snap.Hutao.Model.Entity;
+using Snap.Hutao.Web.Hoyolab.Annotation;
+using Snap.Hutao.Web.Hoyolab.DynamicSecret;
+using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
+using Snap.Hutao.Web.Response;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Snap.Hutao.Web.Hoyolab.App.Account;
+
+///
+/// 账户客户端
+///
+[HttpClient(HttpClientConfigration.XRpc)]
+internal class AccountClient
+{
+ private readonly HttpClient httpClient;
+ private readonly JsonSerializerOptions options;
+ private readonly ILogger logger;
+
+ ///
+ /// 构造一个新的账户客户端
+ ///
+ /// http客户端
+ /// 选项
+ /// 日志器
+ public AccountClient(HttpClient httpClient, JsonSerializerOptions options, ILogger logger)
+ {
+ this.httpClient = httpClient;
+ this.options = options;
+ this.logger = logger;
+ }
+
+ ///
+ /// 异步生成祈愿验证密钥
+ /// 需要stoken
+ ///
+ /// 用户
+ /// 提交数据
+ /// 取消令牌
+ /// 用户角色信息
+ [ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.K2)]
+ public async Task GenerateAuthenticationKeyAsync(User user, GenAuthKeyData data, CancellationToken token = default)
+ {
+ Response? resp = await httpClient
+ .SetUser(user, CookieType.Stoken)
+ .SetReferer("https://app.mihoyo.com")
+ .UsingDynamicSecret1(SaltType.K2)
+ .TryCatchPostAsJsonAsync>(ApiEndpoints.AppAccountGenAuthKey, data, options, logger, token)
+ .ConfigureAwait(false);
+
+ return resp?.Data;
+ }
+
+ ///
+ /// 异步获取 Ltoken
+ ///
+ /// 用户
+ /// 取消令牌
+ /// Ltoken
+ [ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.PROD)]
+ public async Task GetLTokenBySTokenAsync(User user, CancellationToken token)
+ {
+ Response? resp = await httpClient
+ .SetUser(user, CookieType.Stoken)
+ .UsingDynamicSecret2(SaltType.PROD, options, ApiEndpoints.AppAccountGetLTokenBySToken)
+ .TryCatchGetFromJsonAsync>(token)
+ .ConfigureAwait(false);
+
+ return resp?.Data?.Ltoken;
+ }
+}
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/LtokenWrapper.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/LtokenWrapper.cs
new file mode 100644
index 00000000..7706f37f
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/App/Account/LtokenWrapper.cs
@@ -0,0 +1,26 @@
+using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
+using Snap.Hutao.Model.Entity;
+using Snap.Hutao.Web.Hoyolab.Annotation;
+using Snap.Hutao.Web.Hoyolab.DynamicSecret;
+using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
+using Snap.Hutao.Web.Response;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Snap.Hutao.Web.Hoyolab.App.Account;
+
+///
+/// Ltoken 包装器
+///
+public class LtokenWrapper
+{
+ ///
+ /// Ltoken
+ ///
+ [JsonPropertyName("ltoken")]
+ public string Ltoken { get; set; } = default!;
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient.cs
index e0930f32..bdfc225d 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient.cs
@@ -39,7 +39,7 @@ internal class PassportClient
/// 用户
/// 取消令牌
/// 验证信息
- [ApiInformation(Cookie = CookieType.Ltoken)]
+ [ApiInformation(Cookie = CookieType.All)]
public async Task VerifyLtokenAsync(User user, CancellationToken token)
{
Response? response = await httpClient
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/AccountInfo.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/ActionTicketAccountInfo.cs
similarity index 98%
rename from src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/AccountInfo.cs
rename to src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/ActionTicketAccountInfo.cs
index 44757483..e76f8940 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/AccountInfo.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/ActionTicketAccountInfo.cs
@@ -12,7 +12,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Auth;
/// 账户信息
///
[SuppressMessage("", "SA1600")]
-public class AccountInfo
+public class ActionTicketAccountInfo
{
[JsonPropertyName("is_realname")]
public bool IsRealname { get; set; }
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/ActionTicketWrapper.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/ActionTicketWrapper.cs
index 5492510e..9ac5e9b6 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/ActionTicketWrapper.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Auth/ActionTicketWrapper.cs
@@ -29,5 +29,5 @@ public class ActionTicketWrapper
/// 账户信息
///
[JsonPropertyName("account_info")]
- public AccountInfo AccountInfo { get; set; } = default!;
+ public ActionTicketAccountInfo AccountInfo { get; set; } = default!;
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs
index 10fb4a13..b526b3c0 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs
@@ -69,4 +69,21 @@ internal class BindingClient
return EnumerableExtension.EmptyIfNull(resp?.Data?.List);
}
+
+ ///
+ /// 获取用户角色信息
+ ///
+ /// 用户
+ /// 取消令牌
+ /// 用户角色信息
+ [ApiInformation(Cookie = CookieType.Stoken)]
+ public async Task> GetUserGameRolesByStokenAsync(User user, CancellationToken token = default)
+ {
+ Response>? resp = await httpClient
+ .SetUser(user, CookieType.Stoken)
+ .TryCatchGetFromJsonAsync>>(ApiEndpoints.UserGameRolesByStoken, options, logger, token)
+ .ConfigureAwait(false);
+
+ return EnumerableExtension.EmptyIfNull(resp?.Data?.List);
+ }
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient2.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient2.cs
index 3d81b1a5..4852d08c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient2.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient2.cs
@@ -3,6 +3,7 @@
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Model.Entity;
+using Snap.Hutao.Web.Hoyolab.Annotation;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using Snap.Hutao.Web.Response;
using System.Net.Http;
@@ -40,13 +41,14 @@ internal class BindingClient2
/// 提交数据
/// 取消令牌
/// 用户角色信息
+ [ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.K2)]
public async Task GenerateAuthenticationKeyAsync(User user, GenAuthKeyData data, CancellationToken token = default)
{
Response? resp = await httpClient
.SetUser(user, CookieType.Stoken)
.SetReferer("https://app.mihoyo.com")
- .UsingDynamicSecret1(SaltType.LK2)
- .TryCatchPostAsJsonAsync>(ApiEndpoints.GenAuthKey, data, options, logger, token)
+ .UsingDynamicSecret1(SaltType.K2)
+ .TryCatchPostAsJsonAsync>(ApiEndpoints.BindingGenAuthKey, data, options, logger, token)
.ConfigureAwait(false);
return resp?.Data;
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/GenAuthKeyData.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/GenAuthKeyData.cs
index 4de9c2ef..9f7f42c1 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/GenAuthKeyData.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/GenAuthKeyData.cs
@@ -5,6 +5,8 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Binding;
///
/// 验证密钥提交数据
+/// im_css?
+/// {"auth_appid":"im_ccs","game_biz":"bbs_cn","game_uid":0,"region":""}
///
public sealed class GenAuthKeyData
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs b/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs
index 3e72c6ed..d8fa9116 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs
@@ -43,6 +43,11 @@ public enum KnownReturnCode : int
///
RET_NEED_AIGIS = -3101,
+ ///
+ /// 登录信息已失效,请重新登录
+ ///
+ LoginDataOutdated = -262,
+
///
/// 访问过于频繁
///