| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
- <title>正在加载中</title>
- <style>
- html, body { margin: 0; padding: 0; background: #fff; }
- </style>
- </head>
- <body>
- <script>
- /**
- * 空白页:抬头「正在加载中」,拿到跳转链接后 location.replace。
- * 调用约定(每种进入场景只打 1 次对应接口):
- * - 首次进入无 openId → GET /mp/silent/authUrl,再跳转微信
- * - 微信回跳带 code → 只调 POST /mp/silent/resolve
- * - 再次进入已有 openId → 只调 POST /mp/silent/userInfo
- */
- var API_BASE = 'https://wx.jy.cc/apis';
- var APP_ID = 'wxe704b34112659eb1';
- var OPENID_KEY = 'mp_silent_openid';
- var BIZ_CACHE_KEY = 'mp_silent_biz_cache';
- var REQ_LOCK_KEY = 'mp_silent_req_lock';
- /** 同一次授权回跳若页面被加载两次,短时间内复用结果,避免 resolve + userInfo */
- var BIZ_CACHE_TTL_MS = 8000;
- var pageBooted = false;
- function qs(name) {
- var m = location.search.match(new RegExp('[?&]' + name + '=([^&]*)'));
- return m ? decodeURIComponent(m[1].replace(/\+/g, ' ')) : '';
- }
- function isWeChat() {
- return /MicroMessenger/i.test(navigator.userAgent || '');
- }
- function currentPageUrlWithoutQuery() {
- return location.origin + location.pathname;
- }
- function apiUrl(path) {
- var base = (API_BASE || '').replace(/\/$/, '');
- return base + path;
- }
- function normalizePath(pathname) {
- if (!pathname || pathname === '/') return '/';
- return pathname.replace(/\/$/, '');
- }
- function isSameAuthPage(url) {
- if (!url) return true;
- try {
- var u = new URL(url, location.href);
- return u.origin === location.origin
- && normalizePath(u.pathname) === normalizePath(location.pathname);
- } catch (e) {
- return false;
- }
- }
- function clearCodeFromUrl() {
- if (window.history && history.replaceState) {
- history.replaceState(null, '', location.pathname + (location.hash || ''));
- }
- }
- function finishOk(openId, jumpUrl) {
- clearCodeFromUrl();
- if (openId) {
- try { sessionStorage.setItem(OPENID_KEY, openId); } catch (e) {}
- }
- var url = (jumpUrl || '').replace(/^\s+|\s+$/g, '');
- if (url && !isSameAuthPage(url)) {
- location.replace(url);
- }
- // 无跳转链接:保持空白页,抬头仍为「正在加载中」
- }
- function saveBizCache(res) {
- try {
- sessionStorage.setItem(BIZ_CACHE_KEY, JSON.stringify({
- t: Date.now(),
- openId: res.openId || '',
- url: res.url || ''
- }));
- } catch (e) {}
- }
- function readBizCache(openId) {
- try {
- var raw = sessionStorage.getItem(BIZ_CACHE_KEY);
- if (!raw) return null;
- var o = JSON.parse(raw);
- if (!o || o.openId !== openId) return null;
- if (Date.now() - (o.t || 0) > BIZ_CACHE_TTL_MS) return null;
- return o;
- } catch (e) {
- return null;
- }
- }
- /** 页面级 + 短时存储锁,防止并发/双加载重复请求 */
- function tryLockRequest(kind) {
- if (window.__mpSilentReqing) {
- return false;
- }
- try {
- var now = Date.now();
- var raw = sessionStorage.getItem(REQ_LOCK_KEY);
- if (raw) {
- var o = JSON.parse(raw);
- if (o && o.kind === kind && now - (o.t || 0) < 3000) {
- return false;
- }
- }
- sessionStorage.setItem(REQ_LOCK_KEY, JSON.stringify({ kind: kind, t: now }));
- } catch (e) {}
- window.__mpSilentReqing = true;
- return true;
- }
- function unlockRequest() {
- window.__mpSilentReqing = false;
- }
- function applyBizRes(res) {
- if (!res || res.code !== 200 || !res.openId) {
- unlockRequest();
- return;
- }
- saveBizCache(res);
- unlockRequest();
- finishOk(res.openId, res.url || '');
- }
- function getJson(url) {
- return fetch(url, { method: 'GET', credentials: 'omit' }).then(function (res) {
- return res.json();
- });
- }
- function postJson(url, body) {
- return fetch(url, {
- method: 'POST',
- credentials: 'omit',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(body || {})
- }).then(function (res) {
- return res.json();
- });
- }
- /** 调 authUrl 获取授权链接后跳转微信 */
- function goWechatOAuth(appId, state) {
- if (!tryLockRequest('authUrl')) {
- return;
- }
- var redirectUri = currentPageUrlWithoutQuery();
- var authQuery = 'redirectUri=' + encodeURIComponent(redirectUri);
- if (appId) authQuery += '&appId=' + encodeURIComponent(appId);
- if (state) authQuery += '&state=' + encodeURIComponent(state);
- getJson(apiUrl('/mp/silent/authUrl?' + authQuery)).then(function (res) {
- unlockRequest();
- if (!res || res.code !== 200 || !res.oauthUrl) {
- return;
- }
- location.replace(res.oauthUrl);
- }).catch(function () {
- unlockRequest();
- });
- }
- /** 只调 userInfo 一次 */
- function loadUserInfoOnce(openId, state) {
- var cached = readBizCache(openId);
- if (cached) {
- finishOk(cached.openId, cached.url);
- return;
- }
- if (!tryLockRequest('userInfo')) {
- return;
- }
- postJson(apiUrl('/mp/silent/userInfo'), {
- openId: openId,
- state: state || undefined
- }).then(applyBizRes).catch(function () {
- unlockRequest();
- });
- }
- /** 只调 resolve 一次 */
- function resolveOnce(code, appId, state) {
- var codeLockKey = 'mp_silent_code_' + code;
- try {
- if (sessionStorage.getItem(codeLockKey) === 'done') {
- clearCodeFromUrl();
- var openId = '';
- try { openId = sessionStorage.getItem(OPENID_KEY) || ''; } catch (e) {}
- if (openId) {
- loadUserInfoOnce(openId, state);
- }
- return;
- }
- if (sessionStorage.getItem(codeLockKey) === 'pending') {
- return;
- }
- sessionStorage.setItem(codeLockKey, 'pending');
- } catch (e) {}
- if (!tryLockRequest('resolve')) {
- return;
- }
- postJson(apiUrl('/mp/silent/resolve'), {
- code: code,
- appId: appId || undefined,
- state: state || undefined
- }).then(function (res) {
- if (!res || res.code !== 200 || !res.openId) {
- try { sessionStorage.removeItem(codeLockKey); } catch (e) {}
- unlockRequest();
- return;
- }
- try { sessionStorage.setItem(codeLockKey, 'done'); } catch (e) {}
- applyBizRes(res);
- }).catch(function () {
- try { sessionStorage.removeItem(codeLockKey); } catch (e2) {}
- unlockRequest();
- });
- }
- function start() {
- if (pageBooted) {
- return;
- }
- pageBooted = true;
- document.title = '正在加载中';
- if (!isWeChat()) {
- return;
- }
- var appId = qs('appId') || APP_ID;
- var state = qs('state') || '';
- var code = qs('code');
- if (code) {
- resolveOnce(code, appId, state);
- return;
- }
- var cachedOpenId = '';
- try { cachedOpenId = sessionStorage.getItem(OPENID_KEY) || ''; } catch (e) {}
- if (cachedOpenId && qs('force') !== '1') {
- loadUserInfoOnce(cachedOpenId, state);
- return;
- }
- goWechatOAuth(appId, state);
- }
- start();
- </script>
- </body>
- </html>
|