UNPKG

@yorkjs/wechat

Version:

process wechat auth/pay/share tool

296 lines (282 loc) 11.3 kB
/** * wechat.js v2.0.0 * (c) 2021-2022 shushu2013 * Released under the MIT License. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@yorkjs/url')) : typeof define === 'function' && define.amd ? define(['exports', '@yorkjs/url'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Url = {}, global.Url)); })(this, (function (exports, Url) { 'use strict'; var STORAGE_PREFIX = '@@wechat@@'; var AUTH_PAGE_UNLOAD_TIMESTAMP = 'auth_page_unload_timestamp'; var globalConfig; function init$1(config) { globalConfig = config; // 记录发起授权时,页面离开时的时间戳(微信授权,可能会弹出授权提示框) // 用作微信授权后,重定向回来判断时间是否过期 config.onPageLeave(setAuthPageUnloadTimestamp); } function getGlobalConfig() { return globalConfig; } function getStorage(key) { return globalConfig.storage.get((STORAGE_PREFIX + "_" + key)); } function setStorage(key, value) { globalConfig.storage.set((STORAGE_PREFIX + "_" + key), value); } function removeStorage(key) { globalConfig.storage.remove((STORAGE_PREFIX + "_" + key)); } var userAgent = navigator.userAgent; /iphone|ipad/i.test(userAgent); var isAndroid = /android/i.test(userAgent); var isAuthing = false; function setAuthPageUnloadTimestamp() { if (isAuthing) { setStorage(AUTH_PAGE_UNLOAD_TIMESTAMP, getGlobalConfig().getTimestamp()); } } // https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/Official_Accounts/official_account_website_authorization.html // 应用授权作用域 // snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid), // snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) // const SCOPES = ['snsapi_base', 'snsapi_userinfo'] function auth(state, url, scope, appId, componentAppId) { // 注意: 微信参数顺序和大小写有要求 var uri = encodeURIComponent(url); var queryStr = "appid=" + appId + "&redirect_uri=" + uri + "&response_type=code&scope=" + scope + "&state=" + state; if (componentAppId) { queryStr += "&component_appid=" + componentAppId; } isAuthing = true; location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?" + queryStr + "#wechat_redirect"; } function endAuth$1(biz) { isAuthing = false; removeStorage(AUTH_PAGE_UNLOAD_TIMESTAMP); } function normalizeShareUrl$1(url, callback) { return normalizeUrl$1(url, function (urlObj) { if (callback) { callback(urlObj); } // Bugfix: https://zhuanlan.zhihu.com/p/45068949 // 安卓系统,把 /# 变成 /?#,防止微信分享时,把链接 # 后边的字符串都截掉了,导致分享出去的链接不对 var hasSearch = urlObj.search && urlObj.search !== '?'; if (isAndroid && !hasSearch && urlObj.hash) { urlObj.hash = "?" + (urlObj.hash); } }); } function normalizeUrl$1(url, callback) { // 去除微信授权相关 state 和 code var urlObj = Url.parseUrl(url); if (!urlObj) { return url; } if (urlObj.search) { var queryObj = Url.parseQuery(urlObj.search.slice(1)); if (queryObj.state && queryObj.code) { delete queryObj.state; delete queryObj.code; var searchStr = Url.stringifyQuery(queryObj); urlObj.search = searchStr ? ("?" + searchStr) : ''; } } if (callback) { callback(urlObj); } return Url.stringifyUrl(urlObj); } // 弹出授权页面 function startAuth$1(biz, url, appId, componentAppId) { var state = encodeURIComponent(biz); var scope = 'snsapi_userinfo'; auth(state, url, scope, appId, componentAppId); } // 静默授权,不弹出授权页面 function startSilentAuth$1(biz, url, appId, componentAppId) { var state = encodeURIComponent(biz); var scope = 'snsapi_base'; auth(state, url, scope, appId, componentAppId); } var stateMap = {}; function isValidTimestamp(expireTimestamp) { var nowTimestamp = getGlobalConfig().getTimestamp(); var authPageUnloadTimestamp = getStorage(AUTH_PAGE_UNLOAD_TIMESTAMP); if (authPageUnloadTimestamp) { return nowTimestamp - authPageUnloadTimestamp < expireTimestamp; } return false; } function checkQueryState(query, checkRule) { var expireSeconds = checkRule.expireSeconds; var once = checkRule.once; var state = query.state; if (state) { // 1 时间是否过期 if (expireSeconds && !isValidTimestamp(expireSeconds * 1000)) { return false; } // 2 是否读取过了 if (once && stateMap[state]) { return false; } return true; } return false; } // 解析 query function parseAuthQuery(url) { var query = {}; var urlObj = Url.parseUrl(url); if (!urlObj.search) { return query; } var queryObj = Url.parseQuery(urlObj.search.slice(1)); if (queryObj.state && queryObj.code) { query.code = queryObj.code; query.state = queryObj.state; } return query; } // 读取 query function getAuthQuery$1(url, checkRule) { var query = parseAuthQuery(url); var state = query.state; var code = query.code; if (state && code) { // 1. 不需要校验 if (!checkRule) { return query; } var once = checkRule.once; // 2. 校验 query 自身参数 if (!checkQueryState(query, checkRule)) { return {}; } // 3. 在当前页面生命周期生效,只读一次,记录 stateMap if (once) { stateMap[state] = true; } } return query; } function share$1(wx, signature, jsApiList, shareInfo, debug) { if ( debug === void 0 ) debug = false; return new Promise(function (resolve, reject) { // config 信息验证后会执行 ready 方法,所有接口调用都必须在 config 接口获得结果之后, // config 是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口, // 则须把相关接口放在 ready 函数中调用来确保正确执行 wx.config({ debug: debug, appId: signature.appId, timestamp: signature.timestamp, nonceStr: signature.nonceStr, signature: signature.signature, jsApiList: jsApiList }); wx.ready(function () { wx.checkJsApi({ jsApiList: jsApiList, success: function(res) { var result = res.checkResult; if (result.updateAppMessageShareData) { wx.updateAppMessageShareData({ title: shareInfo.title, desc: shareInfo.content, link: shareInfo.url, imgUrl: shareInfo.image }); } if (result.updateTimelineShareData) { wx.updateTimelineShareData({ title: shareInfo.title, link: shareInfo.url, imgUrl: shareInfo.image, }); } if (result.onMenuShareWeibo) { wx.onMenuShareWeibo({ title: shareInfo.title, desc: shareInfo.content, link: shareInfo.url, imgUrl: shareInfo.image }); } // 旧版,用来适配Android if (result.onMenuShareAppMessage) { // 即将废弃 wx.onMenuShareAppMessage({ title: shareInfo.title, desc: shareInfo.content, link: shareInfo.url, imgUrl: shareInfo.image }); } if (result.onMenuShareTimeline) { // 即将废弃 wx.onMenuShareTimeline({ title: shareInfo.title, link: shareInfo.url, imgUrl: shareInfo.image, }); } } }); }); wx.error(function (res) { // config 信息验证失败会执行 error 函数,如签名过期导致验证失败, // 具体错误信息可以打开 config 的 debug 模式查看, // 也可以在返回的 res 参数中查看,对于 SPA 可以在这里更新签名 reject(res); }); resolve(); }); } function pay$1(params) { return new Promise(function (resolve, reject) { if (window.WeixinJSBridge) { window.WeixinJSBridge.invoke('getBrandWCPayRequest', params, function (res) { var err_msg = res.err_msg; if (err_msg == 'get_brand_wcpay_request:ok') { resolve(res); } else if (err_msg !== 'get_brand_wcpay_request:cancel') { reject(err_msg || '支付失败'); } }); } else { reject('缺少微信环境支持'); } }); } var init = init$1; var startAuth = startAuth$1; var startSilentAuth = startSilentAuth$1; var endAuth = endAuth$1; var getAuthQuery = getAuthQuery$1; var share = share$1; var pay = pay$1; var normalizeUrl = normalizeUrl$1; var normalizeShareUrl = normalizeShareUrl$1; /** * 版本 */ var version = "2.0.0"; exports.endAuth = endAuth; exports.getAuthQuery = getAuthQuery; exports.init = init; exports.normalizeShareUrl = normalizeShareUrl; exports.normalizeUrl = normalizeUrl; exports.pay = pay; exports.share = share; exports.startAuth = startAuth; exports.startSilentAuth = startSilentAuth; exports.version = version; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=wechat.js.map