详解Vue微信公众号开发踩坑全记录


Posted in Javascript onAugust 21, 2017

本文介绍了Vue微信公众号开发踩坑全记录,分享给大家,也给自己留个笔记。

需求

  • 微信授权登录(基于公众号的登录方案)
  • 接入JS-SDK实现图片上传,分享等功能

现状及难点

  • 采用的Vue框架,前后端分离模式(vue工程仅作为客户端),用户通过域名访问的是客户端,但是微信授权中涉及签名和token校验依赖服务端
  • JS-SDK需要向服务端获取签名,且获取签名中需要的参数包括所在页面的url,但由于单页应用的路由特殊,其中涉及到IOS和android微信客户端浏览器内核的差异性导致的兼容问题

解决方案

授权登录

授权流程如下:

详解Vue微信公众号开发踩坑全记录

详细说明:

  1. 用户访问网站主域名
  2. vue客户端(domain/)接收请求,在路由解析前判断用户是否登录(比如检查cookie);
  3. 如果没有登录,则通过api获取微信授权地址,获取后跳转到微信服务端授权页面;
  4. 用户确认授权,微信服务器发起回调请求,这时需要回调到服务器端(domain/api/xxx)
  5. 服务器端保存用户信息,进行注册登录操作(记录cookie),重定向到vue客户端(domain/)
  6. 重复第一步,授权登录成功

踩坑记录:

以下是一个错误授权方案

详解Vue微信公众号开发踩坑全记录

这个方案为什么错误呢?其实如果只实现授权登录到话,这个方案是可以的,而且也很清晰,vue客户端单方面在服务器和微信服务器之间进行通信,微信服务器不能直接和服务器通信。这种方案的坑在于当微信授权回调时会携带一个code参数,该参数会污染vue路由导致ios上进行JS-SDK签名时失败(后续会具体描述这个问题)

JS-SDK签名

对于签名,官方是这么说的

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用

vue中路由有history和hash两种模式;在history模式下,理想的设计方案是,当进入到需要用到JS-SDK组件时,获取以下当前url(也就是通过 location.href.split(‘#')[0]获得到的地址)传递到服务端进行签名,应该就没问题了,但是IOS获取的url并不是调用微信js的时候所在页面的地址,而是进入到网站第一个页面的地址。

网上查询到一个方案是针对ios设备进入页面时先将当前url记录下来,到授权页面时将记录的url传递给服务端进行签名。该方案经实践是可行的,妈妈再也不用担心我的网址很丑很难看啦。

另外一个方案就是使用hash模式,这种模式下,url永远都只是主域名地址,省去了传递url的烦恼,也没必要处理兼容,所以如果不建议路由中有#的话,该方案应该是首选方案。

这里还有一个深坑,那就是如果授权方案采用了上述中的vue客户端处理回调的方式,那么ios将永远无法签名成功,为什么呢,因为这种方案路由通常是这样子的:

http://domain.com/?code=xxxxxx&stat=#/xxx

这种路由中带了参数的url是没法签名校验成功的!
这种路由中带了参数的url是没法签名校验成功的!
这种路由中带了参数的url是没法签名校验成功的!
重要的事情得说三遍啊

Coding

任何不上代码的吹逼都是耍流氓,这里笔者分享下在vue中具体怎么coding的。

微信授权登录

笔者在项目中使用的vue-router进行路由控制,使用了vuex记录用户登录信息,但是由于vuex中存储的内容在页面刷新后会丢失,所以服务端同时也写了用户登录状态到cookie中,vue中需要通过这两个条件进行登录判断,不多BB,直接看代码吧

// ... other code

router.beforeEach((to, from, next) => {
 if ((!VueCookie.get('user') && !store.state.userInfo)) {
  // 第一次访问
  console.log('授权登录')
  // 跳转到微信授权页面,微信授权地址通过服务端获得
  axios.post('/api/login').then(res => {
   var data = res.data
   if (data.code === 100) {
    window.location.href = data.data
   }
  })
 } else if (!store.state.userInfo) {
  // 刷新页面,获取数据存入vuex
  axios.get('/api/currentuser').then(res => {
   if (res.data.code === 100) {
    store.dispatch('setUserInfo', res.data.data)
    next()
   }
  })
  console.log('cookie生效期内登录')
  next()
 } else {
  // 已经登录
  console.log('已登录')
  next()
 }
})

//... other code

history模式下的JS-SDK签名

在入口文件中将当前url存入vuex

// ... other code
router.beforeEach((to, from, next) => {
 document.title = to.meta.title
 // 处理jssdk签名,兼容history模式
 if (!store.state.url) {
  store.commit('setUrl', document.URL)
 }
 // ... other code

在需要获取签名的组件中获取并进行配置

// ... other code
created () {
   var sef = this
   var url = ''
   // 判断是否是ios微信浏览器
   if (window.__wxjs_is_wkwebview === true) {
    url = this.$store.state.url.split('#')[0]
   } else {
    url = window.location.href.split('#')[0]
   }
   this.$http.get('/api/jssdk?url=' + url).then(function (res) {
    sef.lists = res.data.data
    hmTools.wechact(sef.lists, sef) //js-sdk配置
   })
  }
// ...other code

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 可以拖动的DIV(二)
Jun 26 Javascript
jQuery学习笔记之jQuery原型属性和方法
Jun 09 Javascript
jquery实现类似EasyUI的页面布局可改变左右的宽度
Sep 12 Javascript
javascript检测两个数组是否相似
May 19 Javascript
javascript实现跨域的方法汇总
Jun 25 Javascript
原生js的数组除重复简单实例
May 24 Javascript
jQueryUI中的datepicker使用方法详解
May 25 Javascript
BootStrap中Datepicker控件带中文的js文件
Aug 10 Javascript
浅谈vue路径优化之resolve
Oct 13 Javascript
在vue中使用v-bind:class的选项卡方法
Sep 27 Javascript
Vue-cli3简单使用(图文步骤)
Apr 30 Javascript
Vue项目接入Paypal实现示例详解
Jun 04 Javascript
前端图片懒加载(lazyload)的实现方法(提高用户体验)
Aug 21 #Javascript
Vue编写多地区选择组件
Aug 21 #Javascript
使用vue制作FullPage页面滚动效果
Aug 21 #Javascript
详解Layer弹出层样式
Aug 21 #Javascript
JS数组操作之增删改查的简单实现
Aug 21 #Javascript
JS实现评价的星星功能
Aug 20 #Javascript
详解A标签中href=""的几种用法
Aug 20 #Javascript
You might like
声音就能俘获人心,蕾姆,是哪个漂亮小姐姐配音呢?
2020/03/03 日漫
基于mysql的论坛(6)
2006/10/09 PHP
php生成二维码的几种方式整理及使用实例
2013/06/03 PHP
PHP上传Excel文件导入数据到MySQL数据库示例
2016/10/25 PHP
利用jquery包将字符串生成二维码图片
2013/09/12 Javascript
浅谈javascript中createElement事件
2014/12/05 Javascript
jQuery实现鼠标滚轮动态改变样式或效果
2015/01/05 Javascript
异步安全加载javascript文件的方法
2015/07/21 Javascript
IE下JS保存图片的简单实例
2016/07/15 Javascript
javascript实现用户点击数量统计
2016/12/25 Javascript
JS传播事件、取消事件默认行为、阻止事件传播详解
2017/08/14 Javascript
webpack dll打包重复问题优化的解决
2018/10/10 Javascript
使用pm2自动化部署node项目的方法步骤
2019/01/28 Javascript
百度小程序自定义通用toast组件
2019/07/17 Javascript
Python3控制路由器——使用requests重启极路由.py
2016/05/11 Python
请不要重复犯我在学习Python和Linux系统上的错误
2016/12/12 Python
详解如何在python中读写和存储matlab的数据文件(*.mat)
2018/02/24 Python
在PyCharm导航区中打开多个Project的关闭方法
2019/01/17 Python
详解python中index()、find()方法
2019/08/29 Python
pytorch制作自己的LMDB数据操作示例
2019/12/18 Python
python实现3D地图可视化
2020/03/25 Python
pycharm 对代码做静态检查操作
2020/06/09 Python
浅谈keras使用中val_acc和acc值不同步的思考
2020/06/18 Python
Python绘制组合图的示例
2020/09/18 Python
python 爬虫基本使用——统计杭电oj题目正确率并排序
2020/10/26 Python
python安装sklearn模块的方法详解
2020/11/28 Python
CSS实现圆形放大镜狙击镜效果 只有圆圈里的放大
2012/12/10 HTML / CSS
css3弹性盒子flex实现三栏布局的实现
2020/11/12 HTML / CSS
钉钉企业内部H5微应用开发详解
2020/05/12 HTML / CSS
欧铁通票官方在线销售网站:Eurail.com
2017/10/14 全球购物
PatPat阿根廷:妈妈们的购物平台
2019/05/30 全球购物
酒吧创业计划书
2014/01/18 职场文书
大学生家政服务项目创业计划书
2014/01/30 职场文书
MySQL时间盲注的五种延时方法实现
2021/05/18 MySQL
微信告警的zabbix监控系统 监控整个NGINX集群
2022/04/18 Servers
Win10服务主机占用内存怎么办?Win10服务主机进程占用大量内存解决方法
2022/09/23 数码科技