近期作了一个微信公众号先后分离项目,前端采用Vue2开发,后端SpringBoot,今天火烧眉毛的来给你们分享一下此次在开发中遇到的一些坑以及解决办法。css
在这里,一些公众号的基本配置我就很少说了,不懂的能够看一下微信开发文档。前端
话很少说,我们开始吧!vue
首先须要经过npm安装微信的JS-SDKjava
npm -install weixin-js-sdk --save
因为项目是基于微信公众号开发的,全部受权的时候微信会本身判断用户所用的浏览器是否为微信浏览器,因此咱们这里并无判断用户使用的是哪一种浏览器。webpack
接着,新建一个jssdk.js,用来初始化微信JS-SDK。该方法接收一个对象参数,用于微信分享参数设置。由于微信签名数据须要后端人员生成,因此须要使用axios来获取这些数据。而后前端调用wx.config方法完成配置,这里须要注ios
意的地方有几点:git
因为每一个页面的分享内容不通,每次跳转页面的时候都须要从新调用wx.config配置分享内容,因此我使用router的全局后置钩子touter.afterEach,分享参数经过路由中的meta获取,你也能够经过接口的形式配置。web
import Vue from 'vue'
import Router from 'vue-router'
import CourseDetail from '@/components/CourseDetail'
import StudyAbroad from '@/article/StudyAbroad'
import MuseumIndustry from '@/article/MuseumIndustry'
import WeekendCamp from '@/article/WeekendCamp'
import ColdSummerCamp from '@/article/ColdSummerCamp'
import Login from '@/login/Login'
import Member from '@/member/Member'
import RechargeRecord from '@/member/RechargeRecord'
import CustomerService from '@/member/CustomerService'
import FeedBack from '@/member/FeedBack'
import NearFuture from '@/future/NearFuture'
import PersonalData from '@/member/PersonalData'
import RechargeDetails from '@/member/RechargeDetails'
import RechargeSuccess from '@/member/RechargeSuccess'
import RechargeFile from '@/member/RechargeFile'
import Payment from '@/member/Payment'
import Invalid from '@/member/Invalid'
import ResultAlready from '@/member/ResultAlready'
import NotStarted from '@/member/NotStarted'
import ClassList from '@/components/Classlist'
import Fillinformation from '@/components/Fillinformation/Fillinformation'
import SignupDetail from '@/components/SignupDetail/SignupDetail'
import WxFail from '@/components/result/WxFail'
import CourseFail from '@/components/result/CourseFail'
import SignupSuccess from '@/components/result/SignupSuccess'
import SignupFail from '@/components/result/SignupFail'
import Ditu from '@/components/Ditu'
import Author from '@/author/Author'
import DelToken from '@/member/DelToken'
import wx from '@/wx/jssdk'
import global from '@/global/global'
Vue.use(Router)
let router = new Router({
// mode: 'history', // 把Router的mode修改成history模式,VueRouter默认的模式为HASH模式
routes: [
{
path: '/CourseDetail/:courseId',
name: 'CourseDetail',
component: CourseDetail,
meta: {
title: '课程详情',
type: true,
shareInfo: {
title: '知育童行',
desc: '打造丰富多彩的亲子活动,帮助家长们给孩子更全面的素质教育。',
imgUrl: global.WX_STATIC_URL + '/images/share/share.png'
}
},
props: true
},
{
path: '/StudyAbroad',
name: 'StudyAbroad',
component: StudyAbroad,
meta: {
title: '微留学',
type: false
}
},
{
path: '/MuseumIndustry',
name: 'MuseumIndustry',
component: MuseumIndustry,
meta: {
title: '博物行',
type: false
}
},
{
path: '/WeekendCamp',
name: 'WeekendCamp',
component: WeekendCamp,
meta: {
title: '周末营地',
type: false
}
},
{
path: '/author',
name: 'Author',
component: Author,
meta: {
title: '受权中',
type: false
}
},
{
path: '/DelToken',
name: 'DelToken',
component: DelToken,
meta: {
title: '删除缓存',
type: false
}
}
],
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { x: 0, y: 0 }
}
}
})
// 全局守卫,微信受权
router.beforeEach((to, from, next) => {
// 路由发生变化修改页面title
if (to.meta.title) {
document.title = to.meta.title
}
if (process.env.NODE_ENV !== 'development') {
const token = window.localStorage.getItem('token')
if (token) {
if (to.path === '/author') {
next({
path: '/'
})
} else {
next()
}
} else {
if (to.path !== '/author') {
// 保存用户进入的url
window.localStorage.setItem('authUrl', to.fullPath)
// 跳转到微信受权页面
window.location.href = process.env.BASE_URL + '/wx/OAuth2/index'
} else {
next()
}
}
} else {
window.localStorage.setItem('token', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJvUUFFYndSSU5VVlhPLVZoOWhEcDUzX3RNeEgwIn0.eShRG4fVFFv4w2gHnkyh7QDdVpG1meOHSZXOrbq-psE')
}
next()
})
router.afterEach((to, from) => {
// 微信JSSDK统一处理
wx.init({
title: to.meta.type ? to.meta.shareInfo.title : '',
desc: to.meta.type ? to.meta.shareInfo.desc : '',
link: global.SHARE_URL + '/#' + to.path,
imgUrl: to.meta.type ? to.meta.shareInfo.imgUrl : '',
type: to.meta.type
})
})
export default router
import wx from 'weixin-js-sdk'
import axios from '@/utils/request'
import app from '@/main'
const jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData', 'chooseImage', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'chooseWXPay', 'openLocation']
/**
* 微信分享配置
* @param url 分享Url
* @param isShowShareMenu true:显示分享菜单 false:禁用
*/
function init (shareBean) {
axios.post('/wx/config/getJsApiSignature', {
url: window.location.href.split('#')[0]
}).then(function (response) {
let data = response.data
wx.config({
debug: false,
appId: data.appId, // 和获取Ticke的必须同样------必填,公众号的惟一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature, // 必填,签名,见附录1
// 须要分享的列表项:发送给朋友,分享到朋友圈,分享到QQ,分享到QQ空间
jsApiList: jsApiList
})
// 处理验证失败的信息
wx.error(function (res) {
console.error('验证失败返回的信息')
})
// 处理验证成功的信息
wx.ready(function () {
// 自定义“分享给朋友”及“分享到QQ”按钮的分享内容(1.4.0)
if (shareBean.type) {
wx.updateAppMessageShareData({
title: shareBean.title, // 分享标题
desc: shareBean.desc, // 分享描述
link: shareBean.link, // 分享连接,该连接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareBean.imgUrl, // 'http://cicstatic.thjinrong.com/static/images/ClassicsList/share/chinese.png', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
console.info('分享成功')
}
})
// 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容(1.4.0)
wx.updateTimelineShareData({
title: shareBean.title, // 分享标题
link: shareBean.link, // 分享连接,该连接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareBean.imgUrl, // 分享图标
success: function () {
// 设置成功
console.info('分享成功')
}
})
}
// 隐藏全部非基础按钮接口
if (!shareBean.type) {
wx.hideAllNonBaseMenuItem()
} else {
wx.showAllNonBaseMenuItem()
}
})
})
}
/**
* 上传图片
*/
function chooseImage () {
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 能够指定是原图仍是压缩图,默认两者都有
sourceType: ['album', 'camera'], // 能够指定来源是相册仍是相机,默认两者都有
success: function (res) {
// let localIds = res.localIds // 返回选定照片的本地ID列表,localId能够做为img标签的src属性显示图片
wx.getLocalImgData({
localId: res.localIds[0], // 图片的localID
success: function (res) {
// localData是图片的base64数据,能够用img标签显示
// store.dispatch('setLocalId', res.localData)
}
})
}
})
}
/**
* 支付
*/
function pay (data) {
wx.chooseWXPay({
timestamp: data.data.timeStamp, // 支付签名时间戳,注意微信jssdk中的全部使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: data.data.nonceStr, // 支付签名随机串,不长于 32 位
package: data.data.packageValue, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: data.data.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: data.data.paySign, // 支付签名
outTradeNo: data.data.outTradeNo, // 商户订单号
success: function (res) {
// 支付成功后的回调函数
console.info(res)
if (res.errMsg === 'chooseWXPay:ok') {
// 使用以上方式判断前端返回,微信团队郑重提示 :
// res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
// app.$store.dispatch('updateStatus', true)
console.info('支付成功')
} else {
app.$store.dispatch('updateStatus', false)
console.info('支付失败')
}
},
// 支付取消回调函数
cancel: function (res) {
app.$store.dispatch('updateStatus', false)
console.info('取消支付')
},
// 支付失败回调函数
fail: function (res) {
app.$store.dispatch('updateStatus', false)
console.info('支付失败')
}
})
}
/**
* 地图
* @param 纬度
* @param 经度
*/
function map (params) {
wx.openLocation({
latitude: params.latitude, // 纬度,浮点数,范围为90 ~ -90
longitude: params.longitude, // 经度,浮点数,范围为180 ~ -180
name: params.name, // 位置名
address: params.address, // 地址详情说明
scale: params.scale, // 地图缩放级别,整形值,范围从1~28。默认为最大
infoUrl: params.infoUrl // 在查看位置界面底部显示的超连接,可点击跳转
})
}
export default {
init: init,
chooseImage: chooseImage,
pay: pay,
map: map
}
咱们项目中只使用到了分享,支付,地图功能,到这里微信分享就开发好了,须要注意几点:vue-router
咱们将封装好的jssdk.js放入全局vue中,这样使用起来方便。在main.js中引入jssdk.js,再将jssdk抛出的对象放入全局变量中。npm
支付以前,须要调用后端接口完成统一下单,下单成功以后才能够调用微信支付,话很少说,直接上代码了。
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import './assets/css/reset.css' import './assets/js/font' import axios from '@/utils/request.js' import wx from '@/wx/jssdk' import VConsole from 'vconsole' import global from '@/global/global' import store from '@/store/index' // 全局处理错误提示、数据加载 import {ToastPlugin, LoadingPlugin} from 'vux' Vue.use(ToastPlugin) Vue.use(LoadingPlugin) // VConsole加载 process.env.NODE_ENV === 'test' && Vue.use(new VConsole()) // import 'element-ui/lib/theme-chalk/index.css' Vue.config.productionTip = false Vue.prototype.axios = axios Vue.prototype.globalParams = global // 加载mock模块 process.env.NODE_ENV === 'mock' && require('@/mock/login') process.env.NODE_ENV === 'mock' && require('@/mock/classList') process.env.NODE_ENV === 'mock' && require('@/mock/courseDetail') process.env.NODE_ENV === 'mock' && require('@/mock/fillinformation') process.env.NODE_ENV === 'mock' && require('@/mock/signupDetail') // 引入工具集 Vue.prototype.toolkit = require('@/utils/toolkit') // 微信JSSDK Vue.prototype.wx = wx /* eslint-disable no-new */ const app = new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' }) export default app
// 微信支付
weChatPayment (orderId) {
let _this = this
this.axios.post('/wx/pay/act', {
orderId: orderId,
body: 'Demo-充值',
}).then(function (res) {
let data = res.data
if (data.code === 1) {
// 统一下单返回参数
_this.wx.pay(data)
} else if (data.code === 0) {
console.info('统一支付下单失败')
_this.$store.dispatch('updateStatus', false)
}
})
},
做为java开发的我,只能给你们分享这么多了,不喜勿喷,谢谢各位大神 !!!