| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- <!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>
- body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background: #f5f5f5; color: #333; }
- .wrap { max-width: 480px; margin: 80px auto; padding: 24px; text-align: center; }
- .tip { font-size: 15px; line-height: 1.6; color: #666; }
- .err { color: #333; margin-top: 12px; word-break: break-all; }
- .fail { color: #c00; }
- </style>
- </head>
- <body>
- <div class="wrap">
- <p class="tip" id="tip">正在授权,请稍候…</p>
- <p class="err" id="err"></p>
- </div>
- <script>
- /**
- * 部署说明:
- * 1) 同源部署:API_BASE 留空
- * 2) Nginx 静态 + 独立 API:API_BASE 填后端地址
- * 3) 公众号后台「网页授权域名」= 本页域名
- * 4) 已有 openId 时也会调 /mp/silent/userInfo 刷新拉黑/加销售信息
- */
- var API_BASE = 'https://wx.jy.cc/apis';
- var APP_ID = 'wxe704b34112659eb1';
- var OPENID_KEY = 'mp_silent_openid';
- function $(id) { return document.getElementById(id); }
- 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 showError(msg) {
- $('tip').textContent = '授权失败';
- $('err').className = 'err fail';
- $('err').textContent = msg || '未知错误';
- }
- function finishOk(openId, jumpUrl, tip, blacklisted) {
- clearCodeFromUrl();
- if (openId) {
- try { sessionStorage.setItem(OPENID_KEY, openId); } catch (e) {}
- }
- var url = (jumpUrl || '').replace(/^\s+|\s+$/g, '');
- if (url && !isSameAuthPage(url)) {
- $('tip').textContent = '授权成功,正在跳转…';
- $('err').textContent = '';
- location.replace(url);
- return;
- }
- $('tip').textContent = tip || '授权成功';
- $('err').className = blacklisted ? 'err fail' : 'err';
- $('err').textContent = '';
- }
- function applyBizRes(res) {
- if (!res || res.code !== 200 || !res.openId) {
- showError((res && res.msg) || '获取用户信息失败');
- return;
- }
- finishOk(res.openId, res.url || '', res.tip || '', !!res.blacklisted);
- }
- /** 已有 openId:每次进入都调后端刷新业务信息 */
- function loadUserInfo(openId, state) {
- $('tip').textContent = '正在获取信息…';
- postJson(apiUrl('/mp/silent/userInfo'), {
- openId: openId,
- state: state || undefined
- }).then(applyBizRes).catch(function (e) {
- showError('网络异常:' + (e && e.message ? e.message : e));
- });
- }
- 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();
- });
- }
- function start() {
- if (!isWeChat()) {
- showError('请在微信中打开本页面');
- return;
- }
- var appId = qs('appId') || APP_ID;
- var state = qs('state') || '';
- var code = qs('code');
- if (!code) {
- var cachedOpenId = '';
- try { cachedOpenId = sessionStorage.getItem(OPENID_KEY) || ''; } catch (e) {}
- // 已有 openId 且非强制重新授权:仍调接口拿拉黑/加销售信息
- if (cachedOpenId && qs('force') !== '1') {
- loadUserInfo(cachedOpenId, state);
- 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) {
- if (!res || res.code !== 200 || !res.oauthUrl) {
- showError((res && res.msg) || '获取授权链接失败');
- return;
- }
- location.replace(res.oauthUrl);
- }).catch(function (e) {
- showError('网络异常:' + (e && e.message ? e.message : e));
- });
- return;
- }
- // 同一 code 只换一次票;已换过则用 openId 再拉业务信息
- var codeLockKey = 'mp_silent_code_' + code;
- try {
- if (sessionStorage.getItem(codeLockKey) === 'done') {
- var doneOpenId = '';
- try { doneOpenId = sessionStorage.getItem(OPENID_KEY) || ''; } catch (e) {}
- if (doneOpenId) {
- loadUserInfo(doneOpenId, qs('state') || state);
- } else {
- showError('授权状态异常,请刷新重试');
- }
- return;
- }
- if (sessionStorage.getItem(codeLockKey) === 'pending') {
- return;
- }
- sessionStorage.setItem(codeLockKey, 'pending');
- } catch (e) {}
- var resolveState = qs('state') || state;
- postJson(apiUrl('/mp/silent/resolve'), {
- code: code,
- appId: appId || undefined,
- state: resolveState || undefined
- }).then(function (res) {
- if (!res || res.code !== 200 || !res.openId) {
- try { sessionStorage.removeItem(codeLockKey); } catch (e) {}
- showError((res && res.msg) || '获取 openId 失败');
- return;
- }
- try { sessionStorage.setItem(codeLockKey, 'done'); } catch (e) {}
- applyBizRes(res);
- }).catch(function (e) {
- try { sessionStorage.removeItem(codeLockKey); } catch (e2) {}
- showError('网络异常:' + (e && e.message ? e.message : e));
- });
- }
- start();
- </script>
- </body>
- </html>
|