由于最近工作太忙导致很少时间去整理,由于之前写的vue调用微信的SDK比较火,所以打算再出一个更加详细的版本
1 首先自己遇到一个比较坑的就是,weixin-jsapi它本身断更了,版本接不上,更不上SDK本身的更新速度,在此批斗一下作者,哈哈哈开玩笑的,所以大家还是选择 cnpm install weixin-js-sdk --save
以下简写的路径是因为我在vue.config.js中配置了路径的缩写,比如下面调用接口 ——api/* 等只是调用暴露的接口方法而已
2 来点干货 首先在src/libs/wechat.js ,文件路径下面建立这么一个js文件,用于编写公用的包括分享等一些函数
getJssDK是后端的接口,通过完整域名的路由用于换取签名以及appid等,大家可以简单的理解为一个调用微信方法的工具类,到时候啥项目都直接copy就能用的
wechat.js
import wx from 'weixin-js-sdk'
import store from '@/store'
import { getJSSDK } from '_api/wechat'
const wxUtils = (jsUrl, isShare) => {//不管是调用分享获取地址都必须经过他的同意才可以,有点类似小程序的canIuse的那种感觉,我允许你用了你才能用,而且你得告诉我你要调用啥
return new Promise((resolve, reject) => {
getJSSDK({ jsUrl }).then(({data})=> {
wx.config({
debug: false, // TODO: 测试阶段使用
appId: data.appid,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [ //告诉微信,俺要地址,分享,摄像头,把权限给我别墨迹哈哈
'getLocation',
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline',
'scanQRCode',
'hideAllNonBaseMenuItem',
'hideMenuItems'
]
})
wx.ready(() => {/准备就绪即成功之后
resolve()
})
wx.error(res => {
console.log('接口调取失败', JSON.stringify(res))
})
}).catch(error => {
reject()
console.log(error)
})
})
}
// 微信支付
const WXinvoke = (orderId, resolve, reject) => {//这个大家可以纯作参考,没具体实例
// payorders({ orderId: orderId }).then(res => {
// if (typeof window.WeixinJSBridge == 'undefined') {
// if (document.addEventListener) {
// document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false)
// } else if (document.attachEvent) {
// document.attachEvent('WeixinJSBridgeReady', onBridgeReady)
// document.attachEvent('onWeixinJSBridgeReady', onBridgeReady)
// }
// } else {
// onBridgeReady()
// }
// function onBridgeReady() {
// window.WeixinJSBridge.invoke(
// 'getBrandWCPayRequest', {
// 'appId': res.appId, // 公众号名称,由商户传入
// 'timeStamp': res.timeStamp, // 时间戳,自1970年以来的秒数
// 'nonceStr': res.nonceStr, // 随机串
// 'package': res.package,
// 'signType': res.signType, // 微信签名方式:
// 'paySign': res.paySign // 微信签名
// },
// function(res) {
// setTimeout(function() {
// if (res.err_msg == 'get_brand_wcpay_request:ok') {
// resolve()
// } else {
// reject()
// }
// }, 500)
// })
// }
// }).catch(error => {
// reject()
// })
}
// 隐藏功能按钮
const hideItems = isShare => {
if (isShare) {//这边的isShare详见下面store的判断,简单的理解为有的页面我不想让你分享
// 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
wx.hideMenuItems({ //隐藏部分按钮
menuList: [
'menuItem:share:timeline', // 分享给朋友圈
'menuItem:share:qq', // 分享到QQ
'menuItem:share:weiboApp', // 分享到Weibo
'menuItem:favorite', // 收藏
'menuItem:share:facebook', // 分享到FB
'menuItem:share:QZone', // 分享到 QQ 空间
'menuItem:editTag', // 编辑标签
'menuItem:delete', // 删除
'menuItem:copyUrl', // 复制链接
'menuItem:originPage', // 原网页
'menuItem:readMode', // 阅读模式
'menuItem:openWithQQBrowser', // 在QQ浏览器中打开
'menuItem:openWithSafari', // 在Safari中打开
'menuItem:share:email', // 邮件
'menuItem:share:brand' // 一些特殊公众号
]
})
} else {
// 隐藏所有非基础按钮接口 “基本类”按钮详见附录3
wx.hideAllNonBaseMenuItem() //隐藏所有分享按钮不让你分享
}
}
// 获取地理位置
const getLocation = () => {
return new Promise((resolve, reject) => {
wx.getLocation({
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
success: response => {
resolve(response)
},
fail: err => {
console.log('获取位置失败', JSON.stringify(err))
},
cancel: err => {
console.log('用户拒绝授权获取地理位置', err)
}
})
})
}
// 分享
const wxShare = () => {
return new Promise((resolve, reject) => {
let { title, desc, imgUrl } = store.state.wechat.shareInfo
let link = window.location.href
wx.updateAppMessageShareData({
title, // 分享标题
desc, // 分享描述
link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl, // 分享图标
success: function() {
// 设置成功
}
})
wx.updateTimelineShareData({
title, // 分享标题
desc, // 分享描述
link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl, // 分享图标
success: function() {
// 设置成功
}
})
wx.onMenuShareAppMessage({
title, // 分享标题
desc, // 分享描述
link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl, // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function() {
// 用户确认分享后执行的回调函数
},
cancel: function() {
// 用户取消分享后执行的回调函数
}
})
wx.onMenuShareTimeline({
title, // 分享标题
link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl, // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
}
})
})
}
// 扫码
const qrScan = (resolve, reject) => {
wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有
success: response => {
// 当needResult 为 1 时,扫码返回的结果
resolve(response)
},
fail: err => {
reject(err)
console.log('请在微信环境下进行扫码操作!')
}
})
}
export { hideItems, getLocation, WXinvoke, wxShare, qrScan }
export default wxUtils
3在main.js中对路由进行引用
main.js
import router from './router'
import store from './store'
router.beforeEach(async(to, from, next) => {
// 判断用户是否进行过授权
if (store.getters.openId) { //判断store里面是否存在openId
try {
store.getters.roleType === '' && await store.dispatch('wechat/getUserInfo') // 根据openID获取户基础信息
} catch (error) { }
next()
} else {//如果没有openId那就重新走授权接口
let idx = to.fullPath.indexOf('code')
let CODE = idx === -1 ? '' : getParams(to.fullPath).code
await store.dispatch('wechat/goToAuth', { CODE })
let path = ''
if (idx > 1) {
path = to.fullPath.substring(0, idx - 1)
}
next(path)
}
})
router.afterEach((to, from) => { //对于微信分享或者是获取经纬度这些不需要路由前调用的咱就放到这边
let jsUrl = encodeURIComponent(window.location.protocol + '//' + window.location.host + to.fullPath)
store.dispatch('wechat/wxUtilsSet', { isInit: from.matched.length === 0, jsUrl, pathName: to.name }) //isInit用于判断用户是否首次登录
})
4store中的配置,在这里我也建了一个wechat.js
cnpm install js-cookie --save
import Cookies from 'js-cookie'//用于存储openId的为了防止刷新页面频繁调用授权,路由中有判断
import wxUtils, { getLocation, hideItems, wxShare } from '@/libs/wechat'//上面的wechat.js暴露的方法
import { authorization, getAccessTokenByCode, getRoleType } from '_api/wechat' //这边都是接口 authorization:授权接口重定向拿code的,getAccessTokenByCode:更具code获取openId的,getRoleType:根据openId获取自己想要的基础信息的
// TODO: 本地调试 DEBUG 可改为 true ,打包需改为 false
const DEBUG = false //当调试页面时
const DE_OPENID = ''//自己和后端要一个openID仅用于调试阶段
let defaultOpenId = DEBUG ? DE_OPENID : ''
try { // 用户关闭了本地存储功能,此时在外层加个try...catch
if (!defaultOpenId) {
defaultOpenId = Cookies.get('openId')
}
} catch (e) { }
let defaultGps = { lng: 125.309186, lat: 32.306358 } //设置默认经纬度
let defaultShareInfo = {//设置分享的内容
title: '',
imgUrl: 'https://lecturer.qdsgvision.com/logo.jpg',
desc: ''
}
const state = {
openId: defaultOpenId,//微信用的openId
gps: defaultGps,//用户地理位置
roleType: '', // 0-游客 1-邀请者 2-讲师 3-教育部(自己项目从后台获取的用户角色可以忽略)
lecturerId: '', // 讲师ID(自己项目从后台获取的用户ID可以忽略)
shareInfo: defaultShareInfo,//设置默认分享的信息
isInit: false //是否首次进入页面
}
const mutations = {
CHANGE_OPENID(state, id) {//设置openId,预存cookie方法
state.openId = id
try {
Cookies.set('openId', id, { expires: cookieExpires || 1 })
// 数据改变的时候把数据拷贝一份保存到localStorage里面
} catch (e) { }
},
CHANGE_GPS(state, info) {//改变state地理位置
state.gps = info
},
CHANGE_ROLETYPE(state, roleType) {//改变state角色信息
state.roleType = roleType
},
CHANGE_LECTURERID(state, lecturerId) {//改变state角色ID
state.lecturerId = lecturerId
},
CHANGE_SHARE_INFO(state, info) {//改变state分享内容
if (!info) {
state.shareInfo = defaultShareInfo
} else {
let { title, desc, imgUrl } = defaultShareInfo
state.shareInfo = {
title: info.title || title,
desc: info.desc || desc,
imgUrl: info.imgUrl || imgUrl
}
}
},
CHANGE_INIT_STATE(state, flag) { //改变state判断是不是第一次进入页面
state.isInit = flag
}
}
const actions = {
// 去授权
async goToAuth({ commit, dispatch }, { CODE }) { //调用授权方法,详见beforeRouter中的调用时候
if (CODE) {//拿到code和后端换取openId
await getAccessTokenByCode({ code: CODE }).then(({ data }) => {
commit('CHANGE_OPENID', data.openid)
})
await dispatch('getUserInfo')
} else {
await authorization({ redirectUri: window.location.href }).then(res => {//调用接口进行重定向
window.location.href = res.data
})
}
},
getUserInfo({ state, commit }) {//根据openId得到用户个人角色以及id等信息
return new Promise((resolve, reject) => {
getRoleType(state.openId).then(({ data }) => {
commit('CHANGE_ROLETYPE', data.roleType)
commit('CHANGE_LECTURERID', data.lecturerId)
resolve()
}).catch(err => {
reject(err)
})
})
},
async wxUtilsSet(options, { isInit, jsUrl, pathName }) { //isInit判断是否首次进入页面,jsUrl:全路由,用于调用接口获取签名,值得一提的是分享比较麻烦,不同路由的分享必须得重新获取签名,pathName:路由名称用于过滤不需要分享的页面
return new Promise((resolve, reject) => {
options.commit('CHANGE_INIT_STATE', isInit)
wxUtils(jsUrl).then(() => {
let shareMenu = ['VisionList', 'VisionDetails', 'EyeshieldList', 'EyeshieldDetails', 'LecturerList', 'LecturerDetails']
hideItems(shareMenu.includes(pathName))//隐藏不需要分享页面的路由name
// 获取用户位置
isInit && getLocation().then(({ longitude, latitude }) => { //调用微信地理位置
options.commit('CHANGE_GPS', { lng: longitude, lat: latitude })
resolve()
})
wxShare() //调用分享方法
}).catch(err => {
reject(err)
})
})
},
setShareInfo({ commit }, payload) { //在可以调用的页面咱们在created里面调用即可,设置咱们要分享的内容即可
commit('CHANGE_SHARE_INFO', payload)
wxShare()
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
5进行分享操作
created() {
this.$store.dispatch('wechat/setShareInfo', { title: '我要分享的标题是啥来着' })
},