first commit
This commit is contained in:
174
apps/miniprogram/utils/syncAuth.js
Normal file
174
apps/miniprogram/utils/syncAuth.js
Normal file
@@ -0,0 +1,174 @@
|
||||
/* global wx, console, require, module */
|
||||
|
||||
const { getOpsConfig } = require("./opsConfig");
|
||||
|
||||
const SYNC_AUTH_STORAGE_KEY = "remoteconn.sync.auth.v1";
|
||||
|
||||
function logSyncAuth(level, message, extra) {
|
||||
if (level === "info") return;
|
||||
const payload = extra && typeof extra === "object" ? extra : {};
|
||||
const writer = level === "warn" ? console.warn : level === "error" ? console.error : console.info;
|
||||
writer("[sync.auth]", message, payload);
|
||||
}
|
||||
|
||||
function readAuthCache() {
|
||||
try {
|
||||
const raw = wx.getStorageSync(SYNC_AUTH_STORAGE_KEY);
|
||||
return raw && typeof raw === "object" ? raw : {};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function writeAuthCache(value) {
|
||||
try {
|
||||
wx.setStorageSync(SYNC_AUTH_STORAGE_KEY, value && typeof value === "object" ? value : {});
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function resolveSyncBaseUrl() {
|
||||
const ops = getOpsConfig();
|
||||
const raw = String(ops.gatewayUrl || "").trim();
|
||||
if (!raw) {
|
||||
logSyncAuth("warn", "未配置 gatewayUrl,无法发起同步请求");
|
||||
return "";
|
||||
}
|
||||
let normalized = raw;
|
||||
if (normalized.startsWith("ws://")) normalized = `http://${normalized.slice(5)}`;
|
||||
if (normalized.startsWith("wss://")) normalized = `https://${normalized.slice(6)}`;
|
||||
if (!normalized.startsWith("http://") && !normalized.startsWith("https://")) {
|
||||
normalized = `https://${normalized}`;
|
||||
}
|
||||
normalized = normalized.replace(/[?#].*$/, "").replace(/\/+$/, "");
|
||||
const matched = normalized.match(/^(https?):\/\/([^/]+)(?:\/.*)?$/i);
|
||||
if (!matched) {
|
||||
logSyncAuth("warn", "gatewayUrl 非法,无法推导同步基地址", { raw });
|
||||
return "";
|
||||
}
|
||||
const baseUrl = `${matched[1].toLowerCase()}://${matched[2]}`;
|
||||
logSyncAuth("info", "同步基地址推导成功", { baseUrl });
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
function requestJson(url, options) {
|
||||
logSyncAuth("info", "发起同步请求", {
|
||||
method: (options && options.method) || "GET",
|
||||
url
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.request({
|
||||
url,
|
||||
method: (options && options.method) || "GET",
|
||||
data: options && options.data,
|
||||
header: (options && options.header) || {},
|
||||
...(Number.isFinite(Number(options && options.timeoutMs)) && Number(options && options.timeoutMs) >= 1000
|
||||
? { timeout: Math.round(Number(options && options.timeoutMs)) }
|
||||
: {}),
|
||||
success(res) {
|
||||
const ok = res && res.statusCode >= 200 && res.statusCode < 300;
|
||||
if (!ok) {
|
||||
const message =
|
||||
res && res.data && typeof res.data === "object" && res.data.message
|
||||
? String(res.data.message)
|
||||
: `sync request failed: ${res.statusCode}`;
|
||||
logSyncAuth("warn", "同步请求返回非 2xx", {
|
||||
method: (options && options.method) || "GET",
|
||||
url,
|
||||
statusCode: res && res.statusCode,
|
||||
message
|
||||
});
|
||||
reject(new Error(message));
|
||||
return;
|
||||
}
|
||||
logSyncAuth("info", "同步请求成功", {
|
||||
method: (options && options.method) || "GET",
|
||||
url,
|
||||
statusCode: res.statusCode
|
||||
});
|
||||
resolve(res.data || {});
|
||||
},
|
||||
fail(error) {
|
||||
logSyncAuth("error", "同步请求失败", {
|
||||
method: (options && options.method) || "GET",
|
||||
url,
|
||||
error: error && error.errMsg ? error.errMsg : String(error || "")
|
||||
});
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loginAndFetchToken() {
|
||||
const baseUrl = resolveSyncBaseUrl();
|
||||
const ops = getOpsConfig();
|
||||
if (!baseUrl || !ops.gatewayToken) {
|
||||
logSyncAuth("warn", "同步鉴权配置不完整", {
|
||||
hasBaseUrl: Boolean(baseUrl),
|
||||
hasGatewayToken: Boolean(ops.gatewayToken)
|
||||
});
|
||||
throw new Error("sync config incomplete");
|
||||
}
|
||||
logSyncAuth("info", "准备执行 wx.login 获取同步令牌", { baseUrl });
|
||||
const loginResult = await new Promise((resolve, reject) => {
|
||||
wx.login({
|
||||
success(res) {
|
||||
if (!res.code) {
|
||||
logSyncAuth("warn", "wx.login 成功但未返回 code");
|
||||
reject(new Error("wx.login missing code"));
|
||||
return;
|
||||
}
|
||||
logSyncAuth("info", "wx.login 成功,已拿到 code");
|
||||
resolve(res);
|
||||
},
|
||||
fail(error) {
|
||||
logSyncAuth("error", "wx.login 失败", {
|
||||
error: error && error.errMsg ? error.errMsg : String(error || "")
|
||||
});
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
const payload = await requestJson(`${baseUrl}/api/miniprogram/auth/login`, {
|
||||
method: "POST",
|
||||
data: { code: loginResult.code },
|
||||
header: {
|
||||
"content-type": "application/json",
|
||||
"x-gateway-token": ops.gatewayToken
|
||||
}
|
||||
});
|
||||
if (!payload || payload.ok !== true || !payload.token) {
|
||||
throw new Error((payload && payload.message) || "sync login failed");
|
||||
}
|
||||
const session = {
|
||||
token: String(payload.token || ""),
|
||||
expiresAt: String(payload.expiresAt || "")
|
||||
};
|
||||
writeAuthCache(session);
|
||||
logSyncAuth("info", "同步令牌获取成功", {
|
||||
expiresAt: session.expiresAt
|
||||
});
|
||||
return session;
|
||||
}
|
||||
|
||||
async function ensureSyncAuthToken() {
|
||||
const cached = readAuthCache();
|
||||
const expiresAt = +new Date(cached.expiresAt || 0);
|
||||
if (cached.token && Number.isFinite(expiresAt) && expiresAt - Date.now() > 60 * 1000) {
|
||||
logSyncAuth("info", "复用本地缓存的同步令牌", {
|
||||
expiresAt: cached.expiresAt
|
||||
});
|
||||
return String(cached.token);
|
||||
}
|
||||
logSyncAuth("info", "本地无可用同步令牌,准备重新登录");
|
||||
const session = await loginAndFetchToken();
|
||||
return session.token;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ensureSyncAuthToken,
|
||||
resolveSyncBaseUrl,
|
||||
requestJson
|
||||
};
|
||||
Reference in New Issue
Block a user