UNPKG

@truenewx/tnxcore

Version:

互联网技术解决方案:JavaScript核心扩展支持

174 lines (160 loc) 6.72 kB
/** * 微信登录客户端支持 */ import {base64} from '../util/string.ts'; type WxLoginOptions = { id: string; appid: string; scope: string; redirect_uri: string; state: any; styletype?: string; sizetype?: string; bgcolor?: string; rst?: string; style?: string; href?: string; lang?: 'en' | string; stylelite?: number; fast_login?: number; color_scheme?: 'auto' | 'dark' | 'light'; onReady?: (ready: boolean) => void; onQRcodeReady?: () => void; onCleanup?: () => void; self_redirect?: boolean; }; (function (e: Window, t: Document) { (e as any).WxLogin = function (o: WxLoginOptions) { let n = "default"; if (o.self_redirect === true) { n = "true"; } else if (o.self_redirect === false) { n = "false"; } const r = t.createElement("iframe") as HTMLIFrameElement; const s = (new Date).getTime(); let a = "https://open.weixin.qq.com/connect/qrconnect?appid=" + o.appid + "&scope=" + o.scope + "&redirect_uri=" + o.redirect_uri + "&state=" + o.state + "&login_type=jssdk&self_redirect=" + n + "&styletype=" + (o.styletype || "") + "&sizetype=" + (o.sizetype || "") + "&bgcolor=" + (o.bgcolor || "") + "&rst=" + (o.rst || "") + "&ts=" + s; a += o.style ? "&style=" + o.style : ""; a += o.href ? "&href=" + o.href : ""; a += o.lang === "en" ? "&lang=en" : ""; a += o.stylelite === 1 ? "&stylelite=1" : ""; a += o.fast_login === 0 ? "&fast_login=0" : ""; if (o.color_scheme === "auto") { a += "&color_scheme=auto"; } else if (o.color_scheme === "dark") { a += "&color_scheme=dark"; } else if (o.color_scheme === "light") { a += "&color_scheme=light"; } r.src = a; r.setAttribute("frameBorder", "0"); r.setAttribute("allowTransparency", "true"); r.setAttribute("scrolling", "no"); r.style.width = "300px"; r.style.height = "400px"; r.allow = "local-network-access"; const c = t.getElementById(o.id); if (c && e.addEventListener && (e as any).JSON) { c.innerHTML = ""; c.appendChild(r); const i = function (evt: MessageEvent) { if (evt.origin === "https://open.weixin.qq.com") { try { const n = JSON.parse((evt as any).data); if (n && n.type === "status") { const ready = n.status === "wxReady"; if (ready && o.onReady && typeof o.onReady === "function") { o.onReady(ready); } if (n.status === "wxQRcodeReady" && o.onQRcodeReady && typeof o.onQRcodeReady === "function") { o.onQRcodeReady(); } } } catch (err) { if (console && typeof console.log === "function") { console.log("wxLogin postMessage error", err); } } } }; e.addEventListener("message", i, false); let l = false; o.onCleanup = function () { if (!l && e.removeEventListener) { e.removeEventListener("message", i, false); l = true; } } } } })(window, document); // 以上代码改编自 http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js function standardizeRedirectUri(redirectUri: string, productContextUri: string): string { let protocol = window.location.protocol; let host = window.location.host; let uri = protocol + '//' + productContextUri; if (productContextUri.startsWith(host)) { uri += redirectUri; } else { // 不是生产环境则借助于生产环境的直接重定向能力进行再跳转 uri += '/redirect/'; if (redirectUri.startsWith('/')) { // 目标跳转地址是相对地址,则加上当前网站根地址 uri += protocol.substring(0, protocol.length - 1) + '/' + host + redirectUri; } else { // 不以/开头,视为绝对地址 let index = redirectUri.indexOf('://'); if (index < 0) { // 绝对地址中一定包含:// console.error('错误的跳转目标地址:' + redirectUri); return; } uri += redirectUri.substring(0, index); // 协议部分 uri += redirectUri.substring(index + 2); } } return encodeURI(uri); } function standardizeState(state) { let stateString = ''; if (typeof state === 'object') { stateString = JSON.stringify(state); stateString = base64.encode(stateString); if (stateString.length > 128) { delete state._next; stateString = JSON.stringify(state); stateString = base64.encode(stateString); } } return stateString; } export default class Wechat { appId = ''; productContextUri = ''; constructor(appId, productContextUri) { this.appId = appId; this.productContextUri = productContextUri; } login(containerId, redirectUri, options) { options = options || {}; if (options.cssHref && options.cssHref.startsWith('/')) { options.cssHref = window.location.protocol + '//' + window.location.host + options.cssHref; } new window.WxLogin({ id: containerId, appid: this.appId, scope: "snsapi_login", redirect_uri: standardizeRedirectUri(redirectUri, this.productContextUri), href: options.cssHref, state: standardizeState(options.state), }); } authorize(redirectUri, state, silent) { // 请求参数有严格的顺序要求,不能更改参数顺序 let url = window.location.protocol + '//open.weixin.qq.com/connect/oauth2/authorize?appid=' + this.appId; url += '&redirect_uri=' + standardizeRedirectUri(redirectUri, this.productContextUri); url += '&response_type=code'; url += '&scope=' + (silent ? 'snsapi_base' : 'snsapi_userinfo'); state = standardizeState(state); if (state) { url += '&state=' + state; } window.location.href = url; } }