Vue2中实现微信分享支付功能
Vue2中实现微信分享支付功能
近期做了一个微信公众号前后分离项目,前端采用Vue2开发,后端SpringBoot,今天迫不及待的来给大家分享一下这次在开发中遇到的一些坑以及解决办法。
在这里,一些公众号的基本配置我就不多说了,不懂的可以看一下微信开发文档。
话不多说,咱们开始吧!
安装微信JS-SDK
首先需要通过npm安装微信的JS-SDK
npm -install weixin-js-sdk --save
由于项目是基于微信公众号开发的,所有授权的时候微信会自己判断用户所用的浏览器是否为微信浏览器,所以我们这里并没有判断用户使用的是哪种浏览器。
封装JS-SDK
接着,新建一个jssdk.js,用来初始化微信JS-SDK。该方法接收一个对象参数,用于微信分享参数设置。因为微信签名数据需要后端人员生成,所以需要使用axios来获取这些数据。然后前端调用wx.config方法完成配置,这里需要注
意的地方有几点:
- SPA单页面应用,url都有携带#,通过url获取config配置签名时,截取#号之前的数据当作入参。
- wx.config入参中的jsApiList一定要配置你用到的微信JS方法。
- 微信js-sdk-1.4.0废弃之前的“onMenuShareTimeline”,“onMenuShareAppMessage”,“onMenuShareQQ”,取代它们的是“updateAppMessageShareData”,“updateTimelineShareData”。详情见:微信开发文档
初始化微信JS-SDK
由于每个页面的分享内容不通,每次跳转页面的时候都需要重新调用wx.config配置分享内容,所以我使用router的全局后置钩子touter.afterEach,分享参数通过路由中的meta获取,你也可以通过接口的形式配置。
实现代码
router路由index.js
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
jssdk.js
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
}
我们项目中只使用到了分享,支付,地图功能,到这里微信分享就开发好了,需要注意几点:
- 微信JS判断支付成功,使用 res.errMsg === 'chooseWXPay:ok' 判断,微信JS取消支付/支付失败不是在success回调函数中判断,而是通过cancel回调函数和fail回调函数判断。
- 地图经纬度一定不要写反。嘿嘿嘿!
微信支付
我们将封装好的jssdk.js放入全局vue中,这样使用起来方便。在main.js中引入jssdk.js,再将jssdk抛出的对象放入全局变量中。
支付之前,需要调用后端接口完成统一下单,下单成功之后才可以调用微信支付,话不多说,直接上代码了。
// 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开发的我,只能给大家分享这么多了,不喜勿喷,谢谢各位大神 !!!
Vue2中实现微信分享支付功能的更多相关文章
- 不接入微信sdk,在APP中实现微信分享,支付
前段时间在很多地方接入了微信的sdk,发现过程比较繁琐,此外因为导入的sdk比较大会影响最终APP打包的体积,所以就有了不接入sdk也实现相同的功能的想法. 要实现这个目标我个人认为最困难的地方是不知 ...
- vue项目中关于微信分享的坑,以及安卓和ios获取location.href不同的处理
最近做vue项目的微信公众号项目,涉及到微信分享,记录一下心得,以备后用,vue路由用的是hash模式: 该项目只是公众号里面的h5链接,不需要获取code获取access_token的票据,因此前端 ...
- app中使用微信分享注意事项
1. 在微信公众平台开通一个微信公众号,https://mp.weixin.qq.com 2. 将自己制作好的已签名的app安装到手机上 3. 下载微信开放平台获取应用签名的apk--- gen ...
- android APP 中微信分享功能实现 的总结
//花了很长时间最终完成了微信分享功能,中间走了很多弯路,在此做一下小结,希望对在应用中使用到微信分享的朋友有所帮助. 主要问题就是下面两个: 1.为什么运行了项目之后,微信分享只是闪了一下就没有了? ...
- AndroidStudio用微信官方方法接入微信分享功能
转载请注明出处:http://www.cnblogs.com/wangoublog/p/5367950.html 现在微信的功能众所周知,用户量.影响力也是惊人,很多应用接入微信的功能已成为一种不可缺 ...
- Vue+Vue-router微信分享功能
在使用vue和vue-router路由框架已经开发过好几个项目了,其中也遇到不少坑,有些坑各种搜也没有找到非常理想的答案. vue学习相对来说还是比较简单,官方文档说明非常清楚(https://cn. ...
- AndroidStudio怎么实现微信分享功能
在应用中添加微信分享功能,需要在微信开放平台上传你的应用,审核通过后方可使用此功能. https://open.weixin.qq.com/网址 申请的过程比较简单,这里就不追溯了,贴一个友情链接 h ...
- VueJs单页应用实现微信网页授权及微信分享功能
在实际开发中,无论是做PC端.WebApp端还是微信公众号等类型的项目的时候,或多或少都会涉及到微信相关的开发,最近公司项目要求实现微信网页授权,并获取微信用户基本信息的功能及微信分享的功能,现在总算 ...
- 如何在ios中集成微信登录功能
在ios中集成微信的登录功能有两种方法 1 用微信原生的api来做,这样做的好处就是轻量级,程序负重小,在Build Settings 中这样设置 然后设置 友盟的设置同上,但是要注意,加入你需要的所 ...
随机推荐
- Django的模型层(2)---多表操作
多表操作 创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对 ...
- 3D特效焦点图
在线演示 本地下载
- POJ 之 WERTYU
WERTYU Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8371 Accepted: 4007 Descriptio ...
- SpringBoot2.0之整合ActiveMQ(点对点模式)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- linux 进程学习笔记-进程ID,PID
PID,进程号 , 范围在2~(??为什么需要这么多),而一个名为idle (或swapper)的进程占据的编号0,init进程占据了编号1. 进程0和进程1 : 系统启动时会从无到有地创建进程0,它 ...
- APIO2018爆零记
Day1 集合 7点和yyc他们在学校简单的集合了一下 在大通道看到了整个年级来上操 嘲讽了一番就大摇大摆的走出了校门 校门口看无迟到周的权益部长lzj同学满眼的羡慕 2333 然后到了裕龙酒店登记入 ...
- 【Lintcode】135.Combination Sum
题目: Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C ...
- idea自动重置language level和java compiler解决办法:修改setting
maven工程: 错误: -source 1.6 中不支持 diamond 运算符. 尝试按网的的方式修改后,自动恢复,也在pom文件指定版本,依然不行. 后来发现:pom这样配置了: <plu ...
- 计算机网络HTTP、TCP/IP包
参考: TCP-IP数据包结构详解 HTTP报文格式详解 Http协议报文格式 HTTP请求/响应报文结构 [Java知识]GET和POST请求的区别
- mysql Split函数
mysql没有split函数,这里手动写一个: ),)) BEGIN CREATE TEMPORARY TABLE IF NOT EXISTS temp_split ( col ) ); DELETE ...