diff --git a/package-lock.json b/package-lock.json
index 2e6c0cf..cce0eb4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,13 +11,12 @@
"@nuxtjs/tailwindcss": "^6.12.2",
"ant-design-vue": "^4.2.6",
"clipboard": "^2.0.11",
- "crypto-js": "^4.2.0",
+ "crypto-es": "^2.1.0",
"nuxt": "^3.14.1592",
"vue": "latest",
"vue-router": "latest"
},
"devDependencies": {
- "@types/crypto-js": "^4.2.2",
"nitropack": "^2.10.4",
"sass-embedded": "^1.82.0"
}
@@ -2514,12 +2513,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/@types/crypto-js": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
- "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==",
- "dev": true
- },
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@@ -3900,10 +3893,10 @@
"uncrypto": "^0.1.3"
}
},
- "node_modules/crypto-js": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
- "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
+ "node_modules/crypto-es": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/crypto-es/-/crypto-es-2.1.0.tgz",
+ "integrity": "sha512-C5Dbuv4QTPGuloy5c5Vv/FZHtmK+lobLAypFfuRaBbwCsk3qbCWWESCH3MUcBsrgXloRNMrzwUAiPg4U6+IaKA=="
},
"node_modules/css-declaration-sorter": {
"version": "7.2.0",
diff --git a/package.json b/package.json
index 42d80c0..53054a1 100644
--- a/package.json
+++ b/package.json
@@ -7,20 +7,20 @@
"dev": "nuxt dev",
"start": "nuxt start",
"generate": "nuxt generate",
- "postinstall": "nuxt prepare"
+ "postinstall": "nuxt prepare",
+ "cf-dev": "npx nuxi build --preset=cloudflare_pages && npx wrangler pages dev dist/"
},
"dependencies": {
"@ant-design-vue/nuxt": "^1.4.6",
"@nuxtjs/tailwindcss": "^6.12.2",
"ant-design-vue": "^4.2.6",
"clipboard": "^2.0.11",
- "crypto-js": "^4.2.0",
+ "crypto-es": "^2.1.0",
"nuxt": "^3.14.1592",
"vue": "latest",
"vue-router": "latest"
},
"devDependencies": {
- "@types/crypto-js": "^4.2.2",
"nitropack": "^2.10.4",
"sass-embedded": "^1.82.0"
}
diff --git a/pages/index.vue b/pages/index.vue
index 566e196..c2886ca 100644
--- a/pages/index.vue
+++ b/pages/index.vue
@@ -4,13 +4,11 @@
@@ -18,25 +16,17 @@
-
-
@@ -44,25 +34,17 @@
-
-
@@ -73,18 +55,15 @@
正在获取授权链接...
-
+
-
-
-
+
+
+
{{ authorizing ? '授权中...' : '授权登录' }}
@@ -94,14 +73,8 @@
-
+
本工具能帮助你一键获取「阿里云盘TV版」的刷新令牌,完全免费。TV接口能绕过三方应用权益包的速率限制,但前提你得是SVIP。
我知道了
@@ -110,7 +83,7 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/server/routes/check_status/[sid].ts b/server/routes/check_status/[sid].ts
index 484297c..bac6342 100644
--- a/server/routes/check_status/[sid].ts
+++ b/server/routes/check_status/[sid].ts
@@ -1,46 +1,47 @@
import { decrypt, getParams } from '@/utils/decode';
import { defineEventHandler, getRouterParams } from 'h3'
+import type { QrCodeStatus, TokenResponseEncrypt, TokenRequest } from '~/types/api'
export const runtime = 'edge'
export default defineEventHandler(async (event) => {
try {
const { sid } = getRouterParams(event);
- const response = await fetch(`https://openapi.alipan.com/oauth/qrcode/${sid}/status`);
- const statusData:any = await response.json();
-
- if (statusData.status === 'LoginSuccess') {
+ const statusData = await $fetch(`https://openapi.alipan.com/oauth/qrcode/${sid}/status`);
+ if (statusData.status === 'LoginSuccess' && statusData.authCode) {
try {
- const authCode = statusData.authCode;
const t = Math.floor(Date.now() / 1000);
- const sendData = { ...getParams(t), code: authCode, "Content-Type": "application/json"};
+ const sendData = {
+ ...getParams(t),
+ code: statusData.authCode,
+ "Content-Type": "application/json"
+ } as TokenRequest;
+
const headers = Object.fromEntries(
Object.entries(sendData).map(([k, v]) => [k, String(v)])
);
- const tokenResponse = await fetch('http://api.extscreen.com/aliyundrive/v3/token', {
+ const tokenResponse = await $fetch('http://api.extscreen.com/aliyundrive/v3/token', {
method: 'POST',
headers: headers,
body: JSON.stringify(sendData)
});
-
- const tokenData:any = await tokenResponse.json();
- const jsonp = tokenData.data;
- const plainData = decrypt(jsonp.ciphertext, jsonp.iv, t);
+ const plainData = decrypt(tokenResponse.data.ciphertext, tokenResponse.data.iv, t);
const tokenInfo = JSON.parse(plainData);
- return {
+ return {
status: 'LoginSuccess',
refresh_token: tokenInfo.refresh_token,
- access_token: tokenInfo.access_token
+ access_token: tokenInfo.access_token
};
+
} catch (error) {
- return { status: 'LoginFailed' };
+ return { status: 'LoginFailed' } as QrCodeStatus;
}
- } else {
- return { status: statusData.status };
}
- } catch (error:any) {
+
+ return statusData;
+ } catch (error: any) {
throw createError({
statusCode: 500,
message: error.message
diff --git a/server/routes/generate_qr.ts b/server/routes/generate_qr.ts
index 732c92d..bef07c7 100644
--- a/server/routes/generate_qr.ts
+++ b/server/routes/generate_qr.ts
@@ -1,20 +1,19 @@
import { defineEventHandler } from 'h3'
-
+import type { ApiResponse, QrCodeData } from '~/types/api'
export default defineEventHandler(async (event) => {
try {
- const response = await fetch('http://api.extscreen.com/aliyundrive/qrcode', {
+ const response = await $fetch>('http://api.extscreen.com/aliyundrive/qrcode', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
+ body: JSON.stringify({
scopes: ["user:base", "file:all:read", "file:all:write"].join(','),
width: 500,
height: 500,
})
})
- const data:any = await response.json()
- return {
- qr_link: data.data.qrCodeUrl,
- sid: data.data.sid
+ return {
+ qr_link: response.data.qrCodeUrl,
+ sid: response.data.sid
}
} catch (error: any) {
throw createError({
diff --git a/server/routes/refresh.ts b/server/routes/refresh.ts
index 05ef30f..2ef8cb9 100644
--- a/server/routes/refresh.ts
+++ b/server/routes/refresh.ts
@@ -1,5 +1,6 @@
import { decrypt, getParams } from "@/utils/decode";
import { defineEventHandler } from 'h3'
+import type { ApiResponse, TokenResponseEncrypt } from '~/types/api'
export const runtime = 'edge'
@@ -17,15 +18,12 @@ export default defineEventHandler(async (event) => {
Object.entries(sendData).map(([k, v]) => [k, String(v)])
);
- const response = await fetch('http://api.extscreen.com/aliyundrive/v3/token', {
+ const tokenData = await $fetch('http://api.extscreen.com/aliyundrive/v3/token', {
method: 'POST',
headers: headers,
body: JSON.stringify(sendData)
});
-
- const tokenData :any = await response.json();
- const jsonp = tokenData.data;
- const plainData = decrypt(jsonp.ciphertext, jsonp.iv, t);
+ const plainData = decrypt(tokenData.data.ciphertext, tokenData.data.iv, t);
const tokenInfo = JSON.parse(plainData);
return {
@@ -34,10 +32,14 @@ export default defineEventHandler(async (event) => {
refresh_token: tokenInfo.refresh_token,
expires_in: tokenInfo.expires_in
};
+ // 直接返回响应数据
+ return tokenData;
+
} catch (error:any) {
return {
- error: error.message,
- statusCode: 500
- }
+ code: 500,
+ message: error.message,
+ data: null
+ } as ApiResponse
}
})
diff --git a/types/api.ts b/types/api.ts
new file mode 100644
index 0000000..63f6e6d
--- /dev/null
+++ b/types/api.ts
@@ -0,0 +1,45 @@
+export interface ApiResponse {
+ code: number;
+ message: string;
+ data: T;
+}
+
+export interface QrCodeData {
+ qrCodeUrl: string;
+ sid: string;
+}
+
+export interface TokenInfo {
+ token_type: string;
+ access_token: string;
+ refresh_token: string;
+ expires_in: number;
+}
+
+export interface TokenResponseEncrypt extends ApiResponse<{
+ ciphertext: string;
+ iv: string;
+}> {}
+
+export interface QrCodeStatus {
+ status: 'WaitLogin' | 'LoginSuccess' | 'LoginFailed';
+ authCode?: string;
+}
+
+export interface DeviceInfo {
+ akv: string;
+ apv: string;
+ b: string;
+ d: string;
+ m: string;
+ mac: string;
+ n: string;
+ t: number;
+ wifiMac: string;
+}
+
+export interface TokenRequest extends DeviceInfo {
+ refresh_token?: string;
+ code?: string;
+ 'Content-Type': string;
+}
\ No newline at end of file
diff --git a/utils/decode.ts b/utils/decode.ts
index 3def5fd..31534a7 100644
--- a/utils/decode.ts
+++ b/utils/decode.ts
@@ -1,18 +1,16 @@
-import pkg from 'crypto-js';
-const { AES, enc, mode, pad, MD5 } = pkg;
+import CryptoES from 'crypto-es';
const decrypt = function (ciphertext: string, iv: string, t: number): string {
try {
const key = generateKey(t);
- const decrypted = AES.decrypt(ciphertext, enc.Utf8.parse(key), {
- iv: enc.Hex.parse(iv),
- mode:mode.CBC,
- padding: pad.Pkcs7
+ const decrypted = CryptoES.AES.decrypt(ciphertext, CryptoES.enc.Utf8.parse(key), {
+ iv: CryptoES.enc.Hex.parse(iv),
+ mode: CryptoES.mode.CBC,
+ padding: CryptoES.pad.Pkcs7
});
- const dec = enc.Utf8.stringify(decrypted).toString();
+ const dec = CryptoES.enc.Utf8.stringify(decrypted).toString();
return dec;
} catch (error) {
- console.error("Decryption failed", error);
console.error("Decryption failed", error);
throw error;
}
@@ -60,7 +58,7 @@ const generateKey = function (t: number): string {
const keyArray = concatenatedParams.split("");
const hashedKey = h(keyArray, t);
- return MD5(hashedKey).toString(enc.Hex);
+ return CryptoES.MD5(hashedKey).toString(CryptoES.enc.Hex);
};
export { decrypt, getParams };