mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
♻️ 重构 http req,捕获aigis
This commit is contained in:
@@ -84,6 +84,7 @@
|
|||||||
"geetest": "^4.1.2",
|
"geetest": "^4.1.2",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"js-md5": "^0.8.3",
|
"js-md5": "^0.8.3",
|
||||||
|
"jsencrypt": "^3.3.2",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
"qrcode.vue": "^3.4.1",
|
"qrcode.vue": "^3.4.1",
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -65,6 +65,9 @@ importers:
|
|||||||
js-md5:
|
js-md5:
|
||||||
specifier: ^0.8.3
|
specifier: ^0.8.3
|
||||||
version: 0.8.3
|
version: 0.8.3
|
||||||
|
jsencrypt:
|
||||||
|
specifier: ^3.3.2
|
||||||
|
version: 3.3.2
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^2.1.7
|
specifier: ^2.1.7
|
||||||
version: 2.1.7(typescript@5.5.3)(vue@3.4.32(typescript@5.5.3))
|
version: 2.1.7(typescript@5.5.3)(vue@3.4.32(typescript@5.5.3))
|
||||||
@@ -2202,6 +2205,9 @@ packages:
|
|||||||
jsbn@0.1.1:
|
jsbn@0.1.1:
|
||||||
resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
|
resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
|
||||||
|
|
||||||
|
jsencrypt@3.3.2:
|
||||||
|
resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==}
|
||||||
|
|
||||||
jsesc@2.5.2:
|
jsesc@2.5.2:
|
||||||
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
|
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -5497,6 +5503,8 @@ snapshots:
|
|||||||
|
|
||||||
jsbn@0.1.1: {}
|
jsbn@0.1.1: {}
|
||||||
|
|
||||||
|
jsencrypt@3.3.2: {}
|
||||||
|
|
||||||
jsesc@2.5.2: {}
|
jsesc@2.5.2: {}
|
||||||
|
|
||||||
json-buffer@3.0.1: {}
|
json-buffer@3.0.1: {}
|
||||||
|
|||||||
@@ -4,17 +4,20 @@
|
|||||||
* @since Beta v0.5.1
|
* @since Beta v0.5.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { publicEncrypt } from "node:crypto";
|
import { JSEncrypt } from "jsencrypt";
|
||||||
|
|
||||||
|
import showSnackbar from "../../../components/func/snackbar.js";
|
||||||
import TGHttp from "../../../utils/TGHttp.js";
|
import TGHttp from "../../../utils/TGHttp.js";
|
||||||
import { getDeviceInfo } from "../../../utils/toolFunc.js";
|
import { getDeviceInfo } from "../../../utils/toolFunc.js";
|
||||||
import TGConstant from "../../../web/constant/TGConstant.js";
|
import TGConstant from "../../../web/constant/TGConstant.js";
|
||||||
|
|
||||||
const PUB_KEY = `-----BEGIN PUBLIC KEY-----
|
const PUB_KEY_STR = `-----BEGIN PUBLIC KEY-----
|
||||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7cI5DcsNKqdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs
|
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7cI5DcsNKqdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs
|
||||||
9ExXCdvqrn51qELbqj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+Q
|
9ExXCdvqrn51qELbqj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+Q
|
||||||
CgGs52bFoYMtyi+xEQIDAQAB
|
CgGs52bFoYMtyi+xEQIDAQAB
|
||||||
-----END PUBLIC KEY-----`;
|
-----END PUBLIC KEY-----`;
|
||||||
|
const encrypt = new JSEncrypt();
|
||||||
|
encrypt.setPublicKey(PUB_KEY_STR);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description rsa 加密
|
* @description rsa 加密
|
||||||
@@ -23,8 +26,15 @@ CgGs52bFoYMtyi+xEQIDAQAB
|
|||||||
* @returns {string} 加密后数据
|
* @returns {string} 加密后数据
|
||||||
*/
|
*/
|
||||||
function rsaEncrypt(data: string): string {
|
function rsaEncrypt(data: string): string {
|
||||||
const buffer = Buffer.from(data);
|
const res = encrypt.encrypt(data.toString());
|
||||||
return publicEncrypt(PUB_KEY, buffer).toString("base64");
|
if (res === false) {
|
||||||
|
showSnackbar({
|
||||||
|
text: "RSA 加密失败",
|
||||||
|
color: "error",
|
||||||
|
});
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,14 +46,14 @@ function rsaEncrypt(data: string): string {
|
|||||||
*/
|
*/
|
||||||
export async function getCaptcha(
|
export async function getCaptcha(
|
||||||
phone: string,
|
phone: string,
|
||||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.CaptchaData | TGApp.BBS.Response.Base> {
|
): Promise<TGApp.Plugins.Mys.CaptchaLogin.CaptchaData | TGApp.BBS.Response.BaseWithData> {
|
||||||
const url = "https://passport-api.mihoyo.com/account/ma-cn-verifier/verifier/createLoginCaptcha";
|
const url = "https://passport-api.mihoyo.com/account/ma-cn-verifier/verifier/createLoginCaptcha";
|
||||||
const device_fp = getDeviceInfo("device_fp");
|
const device_fp = getDeviceInfo("device_fp");
|
||||||
const device_name = getDeviceInfo("device_name");
|
const device_name = getDeviceInfo("device_name");
|
||||||
const device_id = getDeviceInfo("device_id");
|
const device_id = getDeviceInfo("device_id");
|
||||||
const device_model = getDeviceInfo("product");
|
const device_model = getDeviceInfo("product");
|
||||||
const body = { area_code: rsaEncrypt("+86"), mobile: rsaEncrypt(phone) };
|
const body = { area_code: rsaEncrypt("+86"), mobile: rsaEncrypt(phone) };
|
||||||
const header = {
|
const header: Record<string, string> = {
|
||||||
"x-rpc-aigis": "",
|
"x-rpc-aigis": "",
|
||||||
"x-rpc-app_version": TGConstant.BBS.VERSION,
|
"x-rpc-app_version": TGConstant.BBS.VERSION,
|
||||||
"x-rpc-client_type": "2",
|
"x-rpc-client_type": "2",
|
||||||
@@ -61,13 +71,24 @@ export async function getCaptcha(
|
|||||||
console.log("getCaptcha body: ", body);
|
console.log("getCaptcha body: ", body);
|
||||||
const resp = await TGHttp<
|
const resp = await TGHttp<
|
||||||
TGApp.Plugins.Mys.CaptchaLogin.CaptchaResponse | TGApp.BBS.Response.Base
|
TGApp.Plugins.Mys.CaptchaLogin.CaptchaResponse | TGApp.BBS.Response.Base
|
||||||
>(url, {
|
>(
|
||||||
|
url,
|
||||||
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: header,
|
headers: header,
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
});
|
},
|
||||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
true,
|
||||||
return resp.data;
|
);
|
||||||
|
const data = await resp.data;
|
||||||
|
if (data.retcode !== 0) {
|
||||||
|
return <TGApp.BBS.Response.BaseWithData>{
|
||||||
|
retcode: data.retcode,
|
||||||
|
message: data.message,
|
||||||
|
data: resp.resp.headers.get("x-rpc-aigis"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return <TGApp.Plugins.Mys.CaptchaLogin.CaptchaData>data.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,12 +97,14 @@ export async function getCaptcha(
|
|||||||
* @param {string} phone - 手机号
|
* @param {string} phone - 手机号
|
||||||
* @param {string} captcha - 验证码
|
* @param {string} captcha - 验证码
|
||||||
* @param {string} action_type - 操作类型
|
* @param {string} action_type - 操作类型
|
||||||
|
* @param {string} [aigis] - 验证数据
|
||||||
* @returns {Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base>}
|
* @returns {Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base>}
|
||||||
*/
|
*/
|
||||||
export async function doCaptchaLogin(
|
export async function doCaptchaLogin(
|
||||||
phone: string,
|
phone: string,
|
||||||
captcha: string,
|
captcha: string,
|
||||||
action_type: string,
|
action_type: string,
|
||||||
|
aigis?: string,
|
||||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base> {
|
): Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base> {
|
||||||
const url = "https://passport-api.mihoyo.com/account/ma-cn-passport/app/loginByMobileCaptcha";
|
const url = "https://passport-api.mihoyo.com/account/ma-cn-passport/app/loginByMobileCaptcha";
|
||||||
const device_fp = getDeviceInfo("device_fp");
|
const device_fp = getDeviceInfo("device_fp");
|
||||||
@@ -95,7 +118,7 @@ export async function doCaptchaLogin(
|
|||||||
captcha,
|
captcha,
|
||||||
};
|
};
|
||||||
const header = {
|
const header = {
|
||||||
"x-rpc-aigis": "",
|
"x-rpc-aigis": aigis || "",
|
||||||
"x-rpc-app_version": TGConstant.BBS.VERSION,
|
"x-rpc-app_version": TGConstant.BBS.VERSION,
|
||||||
"x-rpc-client_type": "2",
|
"x-rpc-client_type": "2",
|
||||||
"x-rpc-app_id": TGConstant.BBS.APP_ID,
|
"x-rpc-app_id": TGConstant.BBS.APP_ID,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* @file utils/TGHttp.ts
|
* @file utils/TGHttp.ts
|
||||||
* @description 封装HTTP请求
|
* @description 封装HTTP请求
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { fetch } from "@tauri-apps/plugin-http";
|
import { fetch } from "@tauri-apps/plugin-http";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 请求参数
|
* @description 请求参数
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.1
|
||||||
* @property {"GET"|"POST"} method 请求方法
|
* @property {"GET"|"POST"} method 请求方法
|
||||||
* @property {Record<string,string>} headers 请求头
|
* @property {Record<string,string>} headers 请求头
|
||||||
* @property {Record<string,string>} query 请求参数
|
* @property {Record<string,string>} query 请求参数
|
||||||
@@ -26,13 +26,23 @@ type TGHttpParams = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 发送请求
|
* @description 发送请求
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.1
|
||||||
* @template T
|
* @template T
|
||||||
* @param {string} url 请求地址
|
* @param {string} url 请求地址
|
||||||
* @param {TGHttpParams} options 请求参数
|
* @param {TGHttpParams} options 请求参数
|
||||||
* @returns {Promise<T>}
|
* @returns {Promise<T>} 请求结果
|
||||||
*/
|
*/
|
||||||
async function TGHttp<T>(url: string, options: TGHttpParams): Promise<T> {
|
async function TGHttp<T>(url: string, options: TGHttpParams): Promise<T>;
|
||||||
|
async function TGHttp<T>(
|
||||||
|
url: string,
|
||||||
|
options: TGHttpParams,
|
||||||
|
fullResponse: true,
|
||||||
|
): Promise<{ data: Promise<T>; resp: Response }>;
|
||||||
|
async function TGHttp<T>(
|
||||||
|
url: string,
|
||||||
|
options: TGHttpParams,
|
||||||
|
fullResponse?: true,
|
||||||
|
): Promise<T | { data: Promise<T>; resp: Response }> {
|
||||||
const httpHeaders = new Headers();
|
const httpHeaders = new Headers();
|
||||||
if (options.headers) {
|
if (options.headers) {
|
||||||
for (const key in options.headers) {
|
for (const key in options.headers) {
|
||||||
@@ -55,8 +65,11 @@ async function TGHttp<T>(url: string, options: TGHttpParams): Promise<T> {
|
|||||||
return await fetch(url, fetchOptions)
|
return await fetch(url, fetchOptions)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
if (options.isBlob) return res.arrayBuffer();
|
const data = options.isBlob ? res.blob() : res.json();
|
||||||
return res.json();
|
if (fullResponse) {
|
||||||
|
return { data, resp: res };
|
||||||
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
throw new Error(`HTTP error! status: ${res.status}`);
|
throw new Error(`HTTP error! status: ${res.status}`);
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user