mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-15 09:48:14 +08:00
🌱 验证码登录请求草创 #118
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
/**
|
||||
* @file plugins/Mys/index.ts
|
||||
* @description Mys plugin index
|
||||
* @since Beta v0.4.5
|
||||
* @since Beta v0.5.1
|
||||
*/
|
||||
|
||||
import MysApi from "./api/index.js";
|
||||
import { getCaptcha, doCaptchaLogin } from "./request/doCaptchaLogin.js";
|
||||
import { getLoginQr, getLoginStatus } from "./request/doGameLogin.js";
|
||||
import { getCollectionData, getCollectionPosts } from "./request/getCollectionData.js";
|
||||
import getForumList from "./request/getForumList.js";
|
||||
@@ -50,6 +51,8 @@ const Mys = {
|
||||
User: {
|
||||
getQr: getLoginQr,
|
||||
getData: getLoginStatus,
|
||||
getCaptcha,
|
||||
login: doCaptchaLogin,
|
||||
},
|
||||
Vote: {
|
||||
get: getVoteInfo,
|
||||
|
||||
112
src/plugins/Mys/request/doCaptchaLogin.ts
Normal file
112
src/plugins/Mys/request/doCaptchaLogin.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @file plugins/Mys/request/doCaptchaLogin.ts
|
||||
* @description 通过短信验证码登录账号获取 stoken
|
||||
* @since Beta v0.5.1
|
||||
*/
|
||||
|
||||
import { publicEncrypt } from "node:crypto";
|
||||
|
||||
import TGHttp from "../../../utils/TGHttp.js";
|
||||
import { getDeviceInfo } from "../../../utils/toolFunc.js";
|
||||
import TGConstant from "../../../web/constant/TGConstant.js";
|
||||
|
||||
const PUB_KEY = `-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7cI5DcsNK
|
||||
qdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs9ExXCdvqrn51qELb
|
||||
qj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+QCgGs52bFoYMtyi+xEQIDAQAB
|
||||
-----END PUBLIC KEY-----`;
|
||||
const EncryptAreaCode = rsaEncrypt("+86");
|
||||
|
||||
/**
|
||||
* @description rsa 加密
|
||||
* @since Beta v0.5.1
|
||||
* @param {string} data - 待加密数据
|
||||
* @returns {string} 加密后数据
|
||||
*/
|
||||
function rsaEncrypt(data: string): string {
|
||||
const buffer = Buffer.from(data);
|
||||
return publicEncrypt(PUB_KEY, buffer).toString("base64");
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取短信验证码
|
||||
* @since Beta v0.5.1
|
||||
* @todo retcode 为-3101时,表示需要进行验证,需要从resp.headers["x-rpc-aigis"]中获取相关数据
|
||||
* @param {string} phone - 手机号
|
||||
* @returns {Promise<TGApp.Plugins.Mys.CaptchaLogin.CaptchaData | TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function getCaptcha(
|
||||
phone: string,
|
||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.CaptchaData | TGApp.BBS.Response.Base> {
|
||||
const url = "https://passport-api.mihoyo.com/account/ma-cn-verifier/verifier/createLoginCaptcha";
|
||||
const device_fp = getDeviceInfo("device_fp");
|
||||
const device_name = getDeviceInfo("device_name");
|
||||
const device_id = getDeviceInfo("device_id");
|
||||
const device_model = getDeviceInfo("product");
|
||||
const body = { area: EncryptAreaCode, phone: rsaEncrypt(phone) };
|
||||
const header = {
|
||||
"x-rpc-aigis": "",
|
||||
"x-rpc-app_version": TGConstant.BBS.VERSION,
|
||||
"x-rpc-client_type": "2",
|
||||
"x-rpc-app_id": TGConstant.BBS.APP_ID,
|
||||
"x-rpc-device_fp": device_fp,
|
||||
"x-rpc-device_name": device_name,
|
||||
"x-rpc-device_id": device_id,
|
||||
"x-rpc-device_model": device_model,
|
||||
};
|
||||
const resp = await TGHttp<
|
||||
TGApp.Plugins.Mys.CaptchaLogin.CaptchaResponse | TGApp.BBS.Response.Base
|
||||
>(url, {
|
||||
method: "POST",
|
||||
headers: header,
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 通过短信验证码登录
|
||||
* @since Beta v0.5.1
|
||||
* @param {string} phone - 手机号
|
||||
* @param {string} action_type - 操作类型
|
||||
* @param {string} captcha - 验证码
|
||||
* @returns {Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base>}
|
||||
*/
|
||||
export async function doCaptchaLogin(
|
||||
phone: string,
|
||||
action_type: string,
|
||||
captcha: string,
|
||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | TGApp.BBS.Response.Base> {
|
||||
const url = "https://passport-api.mihoyo.com/account/ma-cn-passport/app/loginByMobileCaptcha";
|
||||
const device_fp = getDeviceInfo("device_fp");
|
||||
const device_name = getDeviceInfo("device_name");
|
||||
const device_id = getDeviceInfo("device_id");
|
||||
const device_model = getDeviceInfo("product");
|
||||
const body = {
|
||||
area: EncryptAreaCode,
|
||||
phone: rsaEncrypt(phone),
|
||||
action_type,
|
||||
captcha,
|
||||
};
|
||||
const header = {
|
||||
"x-rpc-aigis": "",
|
||||
"x-rpc-app_version": TGConstant.BBS.VERSION,
|
||||
"x-rpc-client_type": "2",
|
||||
"x-rpc-app_id": TGConstant.BBS.APP_ID,
|
||||
"x-rpc-device_fp": device_fp,
|
||||
"x-rpc-device_name": device_name,
|
||||
"x-rpc-device_id": device_id,
|
||||
"x-rpc-device_model": device_model,
|
||||
};
|
||||
const resp = await TGHttp<TGApp.Plugins.Mys.CaptchaLogin.LoginResponse | TGApp.BBS.Response.Base>(
|
||||
url,
|
||||
{
|
||||
method: "POST",
|
||||
headers: header,
|
||||
body: JSON.stringify(body),
|
||||
},
|
||||
);
|
||||
if (resp.retcode !== 0) return <TGApp.BBS.Response.Base>resp;
|
||||
return resp.data;
|
||||
}
|
||||
163
src/plugins/Mys/types/CaptchaLogin.d.ts
vendored
Normal file
163
src/plugins/Mys/types/CaptchaLogin.d.ts
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @file plugins/Mys/types/CaptchaLogin.d.ts
|
||||
* @description Mys 插件 Captcha 登录类型定义文件
|
||||
* @since Beta v0.5.1
|
||||
*/
|
||||
|
||||
/**
|
||||
* @description Mys 插件 Captcha 登录类型
|
||||
* @since Beta v0.5.1
|
||||
* @namespace TGApp.Plugins.Mys.CaptchaLogin
|
||||
* @memberof TGApp.Plugins.Mys
|
||||
*/
|
||||
declare namespace TGApp.Plugins.Mys.CaptchaLogin {
|
||||
/**
|
||||
* @description 获取短信验证码返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface CaptchaResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {CaptchaData} data 数据
|
||||
* @return GetCaptchaResponse
|
||||
*/
|
||||
interface CaptchaResponse extends TGApp.BBS.Response.BaseWithData {
|
||||
data: CaptchaData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取短信验证码返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface CaptchaData
|
||||
* @property {string} sent_new 是否发送新验证码
|
||||
* @property {string} countdown 倒计时
|
||||
* @property {string} action_type 操作类型
|
||||
* @return CaptchaData
|
||||
*/
|
||||
interface CaptchaData {
|
||||
sent_new: string;
|
||||
countdown: string;
|
||||
action_type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 短信验证码登录返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface LoginResponse
|
||||
* @extends TGApp.BBS.Response.BaseWithData
|
||||
* @property {LoginData} data 数据
|
||||
* @return LoginResponse
|
||||
*/
|
||||
interface LoginResponse extends TGApp.BBS.Response.BaseWithData {
|
||||
data: LoginData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 短信验证码登录返回数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface LoginData
|
||||
* @property {Token} token token数据
|
||||
* @property {UserInfo} user_info 用户信息
|
||||
* @property {ReactivateInfo} reactivate_info 重新激活信息
|
||||
* @property {string} login_ticket 登录 ticket
|
||||
* @property {boolean} new_user 是否新用户
|
||||
* @property {RealnameInfo} realname_info 实名信息
|
||||
* @property {boolean} need_realperson 是否需要实名认证
|
||||
* @property {string} oauth_hw_open_id 华为 open id
|
||||
* @return LoginData
|
||||
*/
|
||||
interface LoginData {
|
||||
token: Token;
|
||||
user_info: UserInfo;
|
||||
reactivate_info: ReactivateInfo;
|
||||
login_ticket: string;
|
||||
new_user: boolean;
|
||||
realname_info: RealnameInfo;
|
||||
need_realperson: boolean;
|
||||
oauth_hw_open_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description token 数据
|
||||
* @since Beta v0.5.1
|
||||
* @interface Token
|
||||
* @property {number} token_type token 类型
|
||||
* @property {string} token token
|
||||
* @return Token
|
||||
*/
|
||||
interface Token {
|
||||
token_type: number;
|
||||
token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用户信息
|
||||
* @since Beta v0.5.1
|
||||
* @interface UserInfo
|
||||
* @property {string} aid 账号 id
|
||||
* @property {string} mid mid
|
||||
* @property {string} account_name 账号名称
|
||||
* @property {string} email 邮箱
|
||||
* @property {number} is_email_verify 是否验证邮箱
|
||||
* @property {string} area_code 手机区号
|
||||
* @property {string} mobile 手机号
|
||||
* @property {string} safe_area_code 安全手机区号
|
||||
* @property {string} safe_mobile 安全手机号
|
||||
* @property {string} realname 真实姓名
|
||||
* @property {string} identity_code 身份证号
|
||||
* @property {string} rebind_area_code 重新绑定手机区号
|
||||
* @property {string} rebind_mobile 重新绑定手机号
|
||||
* @property {string} rebind_mobile_time 重新绑定手机时间
|
||||
* @property {string[]} links 账号绑定信息
|
||||
* @property {string} country 国家
|
||||
* @property {string} unmasked_email 邮箱
|
||||
* @property {number} unmasked_email_type 邮箱类型
|
||||
* @return UserInfo
|
||||
*/
|
||||
interface UserInfo {
|
||||
aid: string;
|
||||
mid: string;
|
||||
account_name: string;
|
||||
email: string;
|
||||
is_email_verify: number;
|
||||
area_code: string;
|
||||
mobile: string;
|
||||
safe_area_code: string;
|
||||
safe_mobile: string;
|
||||
realname: string;
|
||||
identity_code: string;
|
||||
rebind_area_code: string;
|
||||
rebind_mobile: string;
|
||||
rebind_mobile_time: string;
|
||||
links: string[];
|
||||
country: string;
|
||||
unmasked_email: string;
|
||||
unmasked_email_type: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 重新激活信息
|
||||
* @since Beta v0.5.1
|
||||
* @interface ReactivateInfo
|
||||
* @property {boolean} required 是否需要重新激活
|
||||
* @property {string} ticket 重新激活 ticket
|
||||
* @return ReactivateInfo
|
||||
*/
|
||||
interface ReactivateInfo {
|
||||
required: boolean;
|
||||
ticket: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 实名信息
|
||||
* @since Beta v0.5.1
|
||||
* @interface RealnameInfo
|
||||
* @property {boolean} required 是否需要实名认证
|
||||
* @property {string} action_type 操作类型
|
||||
* @property {string} action_ticket 操作 ticket
|
||||
* @return RealnameInfo
|
||||
*/
|
||||
interface RealnameInfo {
|
||||
required: boolean;
|
||||
action_type: string;
|
||||
action_ticket: string;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user