微信jssdk封装

/*** @file 微信JS-SDK封装*/import apis from '../common/apis'
import query from '../common/query'
import axios from '../plugins/axios'
import loadScript from '../utils/load-script'
import { isWeChat, isAndroidWeChat, isIOSWeChat, encodeSearchParams } from './'
import track from 'common/sa'const location = global.location
const REGEXP_SUCCESS = /^w+:ok$/i/*** 获取当前页面URL(去除hash)* @returns {string} 页面URL*/
function getCurrentURL() {return location.href.split('#')[0]
}export default {jWeixin: null,promise: null,signature: null,url: '',/*** 微信JS-SDK初始化* @returns {Promise} Promise实例*/init() {if (!this.promise) {this.promise = new Promise((resolve, reject) => {if (!isWeChat()) {reject('请在微信中打开当前页面')return}Promise.all([this.initScript(),this.initSignature(),]).then(([jWeixin, signature]) => {jWeixin.config({appId: signature.appId,timestamp: signature.timestamp,nonceStr: signature.nonceStr,signature: signature.signature,jsApiList: ['showMenuItems','hideMenuItems','onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone','chooseWXPay','addCard','closeWindow',],})jWeixin.ready(() => {this.promise = nullresolve(jWeixin)})jWeixin.error(res => reject(res.errMsg))}).catch((e) => {this.promise = nullreject(e)})})}// 确保同时多次调用时,只进行一次初始化return this.promise},/*** 加载脚本文件* @returns {Promise} Promise实例*/initScript() {return new Promise((resolve, reject) => {if (this.jWeixin) {resolve(this.jWeixin)return}loadScript('//res.wx.qq.com/open/js/jweixin-1.2.0.js', {async: true,defer: true,}).then(() => {resolve(this.jWeixin = (global.jWeixin || global.wx))}).catch(() => {reject('加载微信JSSDK文件失败')})})},/*** 获取签名信息* @returns {Promise} Promise实例*/initSignature() {return new Promise((resolve, reject) => {const url = getCurrentURL()if (this.signature && url === this.url) {resolve(this.signature)return}this.url = urlaxios.request({url: apis.common.wechat.sign,method: 'POST',headers: {'Content-Type': 'application/x-www-form-urlencoded',},// 此接口必须使用URLSearchParams传参data: encodeSearchParams({url,// 如果有券ID,则后端以该券ID对应的商户公众号进行签名,否则使用默认的X卡公众号进行签名channelId: query.channelId,}),}).then((data) => {const signature = data.resultif (!signature) {reject('签名信息无效')return}// 判断路由是否已经变化if (signature.url !== getCurrentURL()) {reject('签名URL与当前页面URL不一致')return}this.signature = signatureresolve(signature)}).catch(() => {reject('获取签名信息失败')})})},/*** init的简化版* @param {Function} resolve - 初始化成功回调函数* @param {Function} reject - 初始化失败回调函数* @returns {Promise} Promise实例*/ready(resolve, reject) {return this.init().then(resolve).catch(reject)},/*** 分享微信分享成功时的数据埋点* @param {Object} options - 需要sa埋点的数据内容* @param {String} mode - 当前分享模式* @returns {Object} 分享参数*/getShareTrack(options, mode) {if (!options.trackData) {return options}return Object.assign({}, options, {// 微信分享回调success() {const param = Object.assign({}, options.trackData, {shareMethod: mode,})track.share(param)},})},/*** 微信分享接口封装* @param {Object} options - 配置项* @returns {Promise} Promise实例*/share(options) {if (options.imgUrl && options.imgUrl.startsWith('//')) {options.imgUrl = `http:${options.imgUrl}`}return new Promise((resolve, reject) => {options = Object.assign({// XXX: iOS版微信自动配置的链接不会随着路由切换自动更新,而location.href会正常更新link: location.href,}, options)// XXX: 微信不支持//开头的图片地址if (options.imgUrl && String(options.imgUrl).indexOf('//') === 0) {options.imgUrl = `http:${options.imgUrl}`}this.ready((jWeixin) => {// 分享到朋友圈jWeixin.onMenuShareTimeline(this.getShareTrack(options, '朋友圈'))// 分享给朋友jWeixin.onMenuShareAppMessage(this.getShareTrack(options, '分享给朋友'))// 分享到QQjWeixin.onMenuShareQQ(this.getShareTrack(options, '分享到QQ'))// 分享到腾讯微博jWeixin.onMenuShareWeibo(this.getShareTrack(options, '腾讯微博'))// 分享到QQ空间jWeixin.onMenuShareQZone(this.getShareTrack(options, 'QQ空间'))resolve()}, reject)})},/*** 批量显示功能按钮接口* @param {Object} options - 配置项* @returns {Promise} Promise实例*/show(options) {return new Promise((resolve, reject) => {this.ready((jWeixin) => {jWeixin.showMenuItems(Object.assign({}, options, {/*** 调用成功回调函数* @param {Object} response - 响应数据*/success(response) {if (REGEXP_SUCCESS.test(response.errMsg)) {resolve()} else {reject()}},/*** 调用失败回调函数*/fail: () => {reject()},}))}, reject)})},/*** 批量隐藏功能按钮接口* @param {Object} options - 配置项* @returns {Promise} Promise实例*/hide(options) {return new Promise((resolve, reject) => {this.ready((jWeixin) => {jWeixin.hideMenuItems(Object.assign({}, options, {/*** 调用成功回调函数* @param {Object} response - 响应数据*/success(response) {if (REGEXP_SUCCESS.test(response.errMsg)) {resolve()} else {reject()}},/*** 调用失败回调函数*/fail: () => {reject()},}))}, reject)})},/*** 批量添加卡券接口封装* @param {Object} options - 配置项* @returns {Promise} Promise实例*/addCard(options) {return new Promise((resolve, reject) => {this.ready((jWeixin) => {jWeixin.addCard(Object.assign({}, options, {/*** 调用成功回调函数* @param {Object} response - 响应数据*/success(response) {if (REGEXP_SUCCESS.test(response.errMsg)) {resolve()} else {reject()}},/*** 调用失败回调函数*/fail: () => {reject()},}))}, reject)})},/*** 微信支付接口封装* @param {Object} options - 配置项* @returns {Promise} Promise实例*/pay(options) {return new Promise((resolve, reject) => {if (!isAndroidWeChat() && !isIOSWeChat()) {reject('请在手机微信中打开当前页面进行支付')return}const WeixinJSBridge = global.WeixinJSBridge/*** 微信Bridge回调函数*/function onBridgeReady() {const params = Object.assign({package: options.wxPackage,}, options)WeixinJSBridge.invoke('getBrandWCPayRequest', params, (response) => {// response schema: { err_code: String, err_desc: String, err_msg: String }switch (response.err_msg) {case 'get_brand_wcpay_request:ok':resolve()breakcase 'get_brand_wcpay_request:cancel':reject(response.err_desc || '支付取消')break// case 'get_brand_wcpay_request:fail':default:reject(response.err_desc || '支付失败')}})}if (typeof WeixinJSBridge === 'undefined') {if (document.addEventListener) {document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false)} else if (document.attachEvent) {document.attachEvent('WeixinJSBridgeReady', onBridgeReady)document.attachEvent('onWeixinJSBridgeReady', onBridgeReady)}} else {onBridgeReady()}})},
}

Published by

风君子

独自遨游何稽首 揭天掀地慰生平