118 lines
3.2 KiB
JavaScript
118 lines
3.2 KiB
JavaScript
const STORAGE_KEY = "taiyi1224";
|
|
const MACHINE_KEY = "xhsp_machine_code";
|
|
|
|
export function getStoredAuth() {
|
|
try {
|
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
return raw ? JSON.parse(raw) : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function saveStoredAuth(data) {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
|
window.dispatchEvent(new CustomEvent("license-auth-changed", { detail: data }));
|
|
}
|
|
|
|
export function clearStoredAuth() {
|
|
localStorage.removeItem(STORAGE_KEY);
|
|
window.dispatchEvent(new CustomEvent("license-auth-changed", { detail: null }));
|
|
}
|
|
|
|
export function getAccessToken() {
|
|
return getStoredAuth()?.token || "";
|
|
}
|
|
|
|
async function sha256Hex(input) {
|
|
const bytes = new TextEncoder().encode(input);
|
|
const buffer = await crypto.subtle.digest("SHA-256", bytes);
|
|
return Array.from(new Uint8Array(buffer)).map((item) => item.toString(16).padStart(2, "0")).join("");
|
|
}
|
|
|
|
export async function getMachineCode() {
|
|
const cached = localStorage.getItem(MACHINE_KEY);
|
|
if (cached) return cached;
|
|
|
|
const fingerprint = [
|
|
navigator.userAgent,
|
|
navigator.language,
|
|
navigator.platform,
|
|
screen.width,
|
|
screen.height,
|
|
new Date().getTimezoneOffset(),
|
|
].join("|");
|
|
|
|
const code = (await sha256Hex(fingerprint)).slice(0, 32).toUpperCase();
|
|
localStorage.setItem(MACHINE_KEY, code);
|
|
return code;
|
|
}
|
|
|
|
export async function verifyLicenseKey(licenseKey) {
|
|
const machineCode = await getMachineCode();
|
|
const response = await fetch("/api/license/verify", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ licenseKey, machineCode }),
|
|
});
|
|
|
|
const data = await response.json().catch(() => ({ success: false, message: "授权服务返回异常" }));
|
|
if (!response.ok || data.success === false) {
|
|
throw new Error(data.message || "卡密验证失败");
|
|
}
|
|
|
|
const auth = {
|
|
token: data.token,
|
|
auth: data.auth,
|
|
recheckIntervalMs: data.recheckIntervalMs,
|
|
};
|
|
saveStoredAuth(auth);
|
|
return auth;
|
|
}
|
|
|
|
export async function refreshLicenseStatus() {
|
|
const token = getAccessToken();
|
|
if (!token) return null;
|
|
|
|
const response = await fetch("/api/license/status", {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
});
|
|
|
|
const data = await response.json().catch(() => ({ success: false, message: "授权状态检查失败" }));
|
|
if (!response.ok || data.success === false) {
|
|
clearStoredAuth();
|
|
throw new Error(data.message || "授权已失效");
|
|
}
|
|
|
|
const auth = {
|
|
token: data.token || token,
|
|
auth: data.auth,
|
|
recheckIntervalMs: data.recheckIntervalMs,
|
|
};
|
|
saveStoredAuth(auth);
|
|
return auth;
|
|
}
|
|
|
|
export async function unbindCurrentLicense() {
|
|
const token = getAccessToken();
|
|
if (!token) {
|
|
throw new Error("当前没有有效授权");
|
|
}
|
|
|
|
const response = await fetch("/api/license/unbind", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
});
|
|
|
|
const data = await response.json().catch(() => ({ success: false, message: "解绑服务返回异常" }));
|
|
if (!response.ok || data.success === false) {
|
|
throw new Error(data.message || "解绑失败");
|
|
}
|
|
|
|
clearStoredAuth();
|
|
return data;
|
|
}
|