mirror of
https://github.com/iLay1678/i-tools.git
synced 2025-07-03 18:52:17 +08:00
修复cf pages无法使用
This commit is contained in:
parent
815a2542ef
commit
2b83ecd8dd
17
package-lock.json
generated
17
package-lock.json
generated
@ -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",
|
||||
|
@ -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"
|
||||
}
|
||||
|
108
pages/index.vue
108
pages/index.vue
@ -4,13 +4,11 @@
|
||||
<div class="mx-auto w-full max-w-3xl bg-white shadow-lg rounded-lg p-8">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-800">与「阿里云盘」连接</h1>
|
||||
<a href="https://ghcr.io/ilay1678/alipan-tv-token"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-gray-600 hover:text-blue-500 transition-colors"
|
||||
title="Docker Image">
|
||||
<a href="https://ghcr.io/ilay1678/alipan-tv-token" target="_blank" rel="noopener noreferrer"
|
||||
class="text-gray-600 hover:text-blue-500 transition-colors" title="Docker Image">
|
||||
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288z"/>
|
||||
<path
|
||||
d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
@ -18,25 +16,17 @@
|
||||
<div class="space-y-8">
|
||||
<div class="space-y-2">
|
||||
<div class="relative">
|
||||
<textarea
|
||||
id="accessToken"
|
||||
v-model="accessToken"
|
||||
<textarea id="accessToken" v-model="accessToken"
|
||||
class="w-full rounded font-mono text-sm leading-normal border-2 border-dashed border-gray-300 p-3 pr-10 bg-white resize-none focus:outline-none focus:border-blue-500 transition-colors min-h-[120px] whitespace-pre-wrap overflow-auto placeholder:text-gray-400"
|
||||
readonly
|
||||
spellcheck="false"
|
||||
placeholder="访问令牌"
|
||||
/>
|
||||
<button
|
||||
data-clipboard-target="#accessToken"
|
||||
:class="`absolute top-2 right-2 p-1 rounded transition-colors ${
|
||||
hasAccessToken
|
||||
? 'hover:bg-gray-100 text-gray-500 hover:text-blue-500'
|
||||
: 'text-gray-300 cursor-not-allowed'
|
||||
}`"
|
||||
:disabled="!hasAccessToken"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
||||
readonly spellcheck="false" placeholder="访问令牌" />
|
||||
<button data-clipboard-target="#accessToken" :class="`absolute top-2 right-2 p-1 rounded transition-colors ${hasAccessToken
|
||||
? 'hover:bg-gray-100 text-gray-500 hover:text-blue-500'
|
||||
: 'text-gray-300 cursor-not-allowed'
|
||||
}`" :disabled="!hasAccessToken">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@ -44,25 +34,17 @@
|
||||
|
||||
<div class="space-y-2">
|
||||
<div class="relative">
|
||||
<textarea
|
||||
id="refreshToken"
|
||||
v-model="refreshToken"
|
||||
<textarea id="refreshToken" v-model="refreshToken"
|
||||
class="w-full rounded font-mono text-sm leading-normal border-2 border-dashed border-gray-300 p-3 pr-10 bg-white resize-none focus:outline-none focus:border-blue-500 transition-colors min-h-[120px] whitespace-pre-wrap overflow-auto placeholder:text-gray-400"
|
||||
readonly
|
||||
spellcheck="false"
|
||||
placeholder="刷新令牌"
|
||||
/>
|
||||
<button
|
||||
data-clipboard-target="#refreshToken"
|
||||
:class="`absolute top-2 right-2 p-1 rounded transition-colors ${
|
||||
hasRefreshToken
|
||||
? 'hover:bg-gray-100 text-gray-500 hover:text-blue-500'
|
||||
: 'text-gray-300 cursor-not-allowed'
|
||||
}`"
|
||||
:disabled="!hasRefreshToken"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
||||
readonly spellcheck="false" placeholder="刷新令牌" />
|
||||
<button data-clipboard-target="#refreshToken" :class="`absolute top-2 right-2 p-1 rounded transition-colors ${hasRefreshToken
|
||||
? 'hover:bg-gray-100 text-gray-500 hover:text-blue-500'
|
||||
: 'text-gray-300 cursor-not-allowed'
|
||||
}`" :disabled="!hasRefreshToken">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@ -73,18 +55,15 @@
|
||||
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
|
||||
<span class="ml-3 text-gray-600">正在获取授权链接...</span>
|
||||
</div>
|
||||
<button
|
||||
v-else
|
||||
@click="handleAuth(authUrl)"
|
||||
:disabled="authorizing"
|
||||
:class="`block w-full bg-blue-500 text-white text-center py-3 px-4 rounded transition-colors relative ${
|
||||
authorizing ? 'bg-blue-400 cursor-not-allowed' : 'hover:bg-blue-600'
|
||||
}`"
|
||||
>
|
||||
<button v-else @click="handleAuth(authUrl)" :disabled="authorizing" :class="`block w-full bg-blue-500 text-white text-center py-3 px-4 rounded transition-colors relative ${authorizing ? 'bg-blue-400 cursor-not-allowed' : 'hover:bg-blue-600'
|
||||
}`">
|
||||
<div class="flex items-center justify-center">
|
||||
<div v-if="authorizing" class="animate-spin rounded-full h-5 w-5 border-2 border-white border-t-transparent mr-2"></div>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
|
||||
<div v-if="authorizing"
|
||||
class="animate-spin rounded-full h-5 w-5 border-2 border-white border-t-transparent mr-2"></div>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
|
||||
</svg>
|
||||
{{ authorizing ? '授权中...' : '授权登录' }}
|
||||
</div>
|
||||
@ -94,14 +73,8 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<a-modal
|
||||
v-model:open="isNoticeOpen"
|
||||
title="使用说明"
|
||||
@ok="closeNotice"
|
||||
:maskClosable="false"
|
||||
:closable="false"
|
||||
:keyboard="false"
|
||||
>
|
||||
<a-modal v-model:open="isNoticeOpen" title="使用说明" @ok="closeNotice" :maskClosable="false" :closable="false"
|
||||
:keyboard="false">
|
||||
<p>本工具能帮助你一键获取「阿里云盘TV版」的刷新令牌,完全免费。TV接口能绕过三方应用权益包的速率限制,但前提你得是SVIP。</p>
|
||||
<template #footer>
|
||||
<a-button type="primary" @click="closeNotice">我知道了</a-button>
|
||||
@ -110,7 +83,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import ClipboardJS from 'clipboard'
|
||||
|
||||
@ -127,8 +100,7 @@ const refreshToken = ref('')
|
||||
async function generateAuthUrl() {
|
||||
try {
|
||||
isLoading.value = true
|
||||
const response = await fetch("/generate_qr", { method: "POST" })
|
||||
const data = await response.json()
|
||||
const data = await $fetch("/generate_qr", { method: "POST" })
|
||||
authUrl.value = `https://www.alipan.com/o/oauth/authorize?sid=${data.sid}`
|
||||
checkStatus(data.sid)
|
||||
} finally {
|
||||
@ -142,8 +114,7 @@ function closeNotice() {
|
||||
|
||||
async function checkStatus(sid) {
|
||||
try {
|
||||
const response = await fetch("/check_status/" + sid)
|
||||
const data = await response.json()
|
||||
const data = await $fetch("/check_status/" + sid)
|
||||
if (data.status === "LoginSuccess") {
|
||||
accessToken.value = data.access_token
|
||||
refreshToken.value = data.refresh_token
|
||||
@ -191,6 +162,7 @@ const handleAuth = (url) => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 先显示弹框
|
||||
isNoticeOpen.value = true
|
||||
if (!hasGenerated.value) {
|
||||
generateAuthUrl()
|
||||
@ -200,6 +172,4 @@ onMounted(() => {
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
@ -1,32 +1,32 @@
|
||||
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<QrCodeStatus>(`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<TokenResponseEncrypt>('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 {
|
||||
@ -34,13 +34,14 @@ export default defineEventHandler(async (event) => {
|
||||
refresh_token: tokenInfo.refresh_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
|
||||
|
@ -1,8 +1,8 @@
|
||||
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<ApiResponse<QrCodeData>>('http://api.extscreen.com/aliyundrive/qrcode', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@ -11,10 +11,9 @@ export default defineEventHandler(async (event) => {
|
||||
height: 500,
|
||||
})
|
||||
})
|
||||
const data:any = await response.json()
|
||||
return {
|
||||
qr_link: data.data.qrCodeUrl,
|
||||
sid: data.data.sid
|
||||
qr_link: response.data.qrCodeUrl,
|
||||
sid: response.data.sid
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw createError({
|
||||
|
@ -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<TokenResponseEncrypt>('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
|
||||
}
|
||||
})
|
||||
|
45
types/api.ts
Normal file
45
types/api.ts
Normal file
@ -0,0 +1,45 @@
|
||||
export interface ApiResponse<T = any> {
|
||||
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;
|
||||
}
|
@ -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 };
|
||||
|
Loading…
x
Reference in New Issue
Block a user