UNPKG

react-app-shell

Version:

react打包脚本和example, 这里的版本请忽略

393 lines (359 loc) 12 kB
import queryString from 'query-string'; import wx from 'weixin-js-sdk'; import { wechatService } from '../service'; // import message from './message'; import { appConfig, shareConfig } from '../config'; const noop = () => {}; // let debugStatus = process.env.NODE_ENV === "production" ? false : true; const debugStatus = false; /** * 微信验证状态 * @type {{ready: boolean, error: string}} */ export const wechatStatus = { /** * config信息验证是否完成 */ ready: false, /** * config信息验证错误信息 */ error: '' }; /** * 根据微信签名, 通过config接口注入权限验证配置 * 所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用 * * staging环境对应的微信公众号: 魔力好家长: appid=wxd7ec12bd329457fb * mobile 生产环境对应的微信公众号: 魔力耳朵: appid=wxa86689ab270599d4 * @param wechatSign 签名数据 * @param showShare 显示微信分享, 默认为真 * @param shareOptions 分享选项 */ export const wechatConfig = (wechatSign = {}, showShare = true, shareOptions = {}) => { const config = { debug: debugStatus, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: wechatSign.appId, // 必填,公众号的唯一标识 timestamp: wechatSign.timestamp, // 必填,生成签名的时间戳 nonceStr: wechatSign.nonceStr, // 必填,生成签名的随机串 signature: wechatSign.signature, // 必填,签名 jsApiList: [ 'chooseWXPay', 'chooseImage', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'hideMenuItems', 'showMenuItems', 'hideOptionMenu' ] // 必填,需要使用的JS接口列表 }; wx.config(config); wechatReady(showShare, shareOptions); wechatError(); }; /** * 微信, 通过ready接口处理成功验证 * @param showShare 是否显示微信分享 * @param options */ const wechatReady = (showShare, shareOptions = {}) => { wx.ready(function() { console.log('微信 js-sdk wx.ready'); // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后, // config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。 // 对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 wechatStatus.ready = true; wechatStatus.error = ''; // 配置 configShare(showShare, shareOptions); }); }; /** * 配置分享 * @param showShare * @param shareOptions */ export const configShare = (showShare, shareOptions = {}) => { console.log('configShare >>> ', shareOptions); const parser = queryString.parse(window.location.search) || {}; const { from, isappinstalled, ...rest } = parser; const location = window.location; const defaultLink = `${location.protocol}//${location.host}${ location.pathname }?${queryString.stringify(rest)}`; const options = { title: shareConfig.default.title, // 分享标题 desc: shareConfig.default.desc, // 分享描述 link: defaultLink, // 默认分享链接 imgUrl: shareConfig.default.imgUrl, // 分享图标 type: shareConfig.default.type, // 分享类型,music、video或link,不填默认为link dataUrl: shareConfig.default.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 ...shareOptions }; console.log('微信分享设置', '是否允许分享功能: ' + showShare, options); onMenuShareTimeline(options); onMenuShareAppMessage(options); onMenuShareQQ(options); onMenuShareWeibo(options); onMenuShareQZone(options); // 展示分享 或 隐藏分享 showOrHideMenuShare(showShare); }; /** * 微信, 通过error接口处理失败验证 */ const wechatError = () => { wx.error(function(res) { // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 wechatStatus.ready = false; wechatStatus.error = JSON.stringify(res); // console.error('wechatError >> 微信签名失败!', res); }); }; /** * 选择微信支付 */ export const chooseWXPay = (option) => { if (!wechatStatus.ready) { console.error('微信>>>签名失败'); return; } wx.chooseWXPay({ timestamp: option.timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 nonceStr: option.nonceStr, // 支付签名随机串,不长于 32 位 package: option.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*) signType: option.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' paySign: option.paySign, // 支付签名 success: function(res) { if (res.errMsg === 'chooseWXPay:ok') { option.success && option.success(); } else { option.fail && option.fail({ msg: res.errMsg }); } }, cancel: function() { option.cancel && option.cancel(); }, fail: function(res) { option.fail && option.fail({ msg: (res && res.errMsg) || '支付失败' }); } }); }; /** * 微信选择图片 * @param count * @param callback 回调 */ export const chooseImage = ({ count = 1, callback }) => { if (!wechatStatus.ready) { // console.error('微信>>>签名失败'); return; } wx.chooseImage({ count: count, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function(res) { callback && callback(res.localIds); } }); }; /** * 展示分享 或 屏蔽分享 */ export const showOrHideMenuShare = (showShare) => { if (showShare) { wx.showMenuItems({ menuList: [ 'menuItem:share:appMessage', 'menuItem:share:timeline', 'menuItem:share:qq', 'menuItem:share:weiboApp', 'menuItem:share:facebook', 'menuItem:share:QZone', 'menuItem:favorite', 'menuItem:openWithQQBrowser', 'menuItem:openWithSafari' ] }); } else { wx.hideMenuItems({ menuList: [ 'menuItem:share:appMessage', 'menuItem:share:timeline', 'menuItem:share:qq', 'menuItem:share:weiboApp', 'menuItem:share:facebook', 'menuItem:share:QZone', 'menuItem:favorite', 'menuItem:openWithQQBrowser', 'menuItem:openWithSafari' ] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3 }); } }; /** * 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 */ const onMenuShareTimeline = ({ title, link, imgUrl, success = noop, cancel = noop }) => { wx.onMenuShareTimeline({ title, // 分享标题 link, // 分享链接 imgUrl, // 分享图标 success, cancel }); }; /** * 获取“分享给朋友”按钮点击状态及自定义分享内容接口 */ const onMenuShareAppMessage = (options) => { const { title, desc, link, imgUrl, type, dataUrl, success = noop, cancel = noop } = options; wx.onMenuShareAppMessage({ title, // 分享标题 desc, // 分享描述 link, imgUrl, // 分享图标 type, // 分享类型,music、video或link,不填默认为link dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success, cancel // 用户取消分享后执行的回调函数 }); }; /** * 获取“分享到QQ”按钮点击状态及自定义分享内容接口 */ const onMenuShareQQ = ({ title, desc, link, imgUrl }) => { wx.onMenuShareQQ({ title, desc, link, imgUrl, success: function() { // 用户确认分享后执行的回调函数 }, cancel: function() { // 用户取消分享后执行的回调函数 } }); }; /** * 获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 */ const onMenuShareWeibo = ({ title, desc, link, imgUrl }) => { wx.onMenuShareWeibo({ title, desc, link, imgUrl, success: function() { // 用户确认分享后执行的回调函数 }, cancel: function() { // 用户取消分享后执行的回调函数 } }); }; /** * 分享到QQ空间 */ const onMenuShareQZone = ({ title, desc, link, imgUrl }) => { wx.onMenuShareQZone({ title, desc, link, imgUrl, success: function() { // 用户确认分享后执行的回调函数 }, cancel: function() { // 用户取消分享后执行的回调函数 } }); }; /** * 延迟, 单位毫秒 * @param delay * @returns {Promise<any>} */ export const getDelay = (delay) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, delay); }); }; /** * 用户授权code已经被使用 * @type {number} */ const CODE_ALREADY_USED = 40163; /** * 用户授权code无效 * @type {number} */ const CODE_INVALID = 40029; /** * 根据用户主动授权的code, 获取openId和微信token, 接口的响应 会给浏览器添加一个cookie, "wxToken" * @param code 用户主动授权的code * @param redirectUrl 当code值已被使用或者无效时的重定向地址 * @returns {Promise<T>} */ export const getOpenIdByCode = (code, redirectUrl) => { return wechatService .getOpenIdByCode(code) .then((wechatUserInfo) => { return new Promise((resolve, reject) => { if (!wechatUserInfo) { return reject(new Error({ msg: '获取授权的用户信息失败' })); } if (typeof wechatUserInfo === 'string') { /* eslint no-param-reassign: "off" */ wechatUserInfo = JSON.parse(wechatUserInfo); } // 用户授权code已经被使用 或 用户授权code无效, 则需要重定向到 redirectUrl, 然后重新获取用户授权码 if (wechatUserInfo.code === CODE_ALREADY_USED || wechatUserInfo.code === CODE_INVALID) { resolve(); redirectUrl && redirectUrl.startsWith('http') && window.location.replace(redirectUrl); return; } resolve(wechatUserInfo.openId); }); }) .catch((error) => { // console.error(error); return Promise.reject(new Error({ msg: '获取授权的用户信息失败' })); }); }; /** * 环境 * @type {string} */ const NODE_ENV = process.env.NODE_ENV || 'development'; /** * 同步检查用户授权, 如果未授权, 则让用户选择同意授权 */ export const checkUserAuth = () => { // 本地开发环境没有微信环境, 所以不做主动授权 if (NODE_ENV === 'development') { return; } console.log('同步检查用户授权, 当前Url参数:', window.location.search); // 获取微信code const { code, state } = queryString.parse(window.location.search); if (code || state) { return; } console.log('同步检查微信授权, 需要用户主动授权', window.location.search); // 用户主动授权的链接地址 const mainUserAuthUrl = appConfig.resources.mainUserAuthUrl; // 需要用户主动授权, 获取用户的头像信息 const commonAuthUrl = `${mainUserAuthUrl}&redirect_uri=${encodeURIComponent( window.location.href )}&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect`; window.location.replace(commonAuthUrl); return; };