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

需求

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

现状及难点

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

解决方案

授权登录

本人将授权流程设计如下:

详细说明:

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

踩坑记录:
以下是另一个授权方案

其实如果只实现授权登录到话,这个方案是可以的,而且也很清晰,Vue客户端单方面在服务器和微信服务器之间进行通信,微信服务器不能直接和服务器通信。这种方案的坑在于当微信授权回调时会携带一个code参数,该参数会污染Vue路由导致ios上进行JS-SDK签名时失败(后续会具体描述这个问题)
2021-09-08更新
笔者已经成功解决了该方案下路由被污染的问题,可移步到笔者新发布的博客了解
Vue3项目中微信授权登录的优雅实现

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是没法签名校验成功的!
重要的事情得说三遍啊
在我另外一篇文章中对js-sdk签名做了更多的介绍,可以移步到vue微信公众号开发踩坑记录(2)

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

结语

由于本人文笔一般,思维的表达估计不到位,见解也是浅尝辄止,所以如果看官您有疑惑的地方或者有歧义欢迎来和本人交流。同时,为方便大家更好的探讨微信公众号开发相关技术,笔者也建了一个微信群,欢迎加入和大家一起学习成长。添加笔者微信imwty2023,即可进群。


开发小记
记录一次次入坑和翻坑的经历

Enjoy creating rather than coding!

1.1k 声望
93 粉丝
0 条评论
推荐阅读
Nuxt3中如何引入Vant UI+移动端适配处理
之前笔者分享了如何在Nuxt3中使用Element Plus UI,但那是PC端的UI组件库,不适用于做移动端页面。做移动端比较主流的UI库就是Vant UI了。接下来我们讲讲如何在Nuxt3中使用VantUI。

imwty阅读 535

【已结束】SegmentFault 思否写作挑战赛!
SegmentFault 思否写作挑战赛 是思否社区新上线的系列社区活动在 2 月 8 日 正式面向社区所有用户开启;挑战赛中包含多个可供作者选择的热门技术方向,根据挑战难度分为多个等级,快来参与挑战,向更好的自己前进!

SegmentFault思否20阅读 5.6k评论 10

封面图
Vue2 导出excel
2020-07-15更新 excel导出安装 {代码...} src文件夹下新建一个libs文件夹,新建一个excel.js {代码...} vue页面中使用 {代码...} ===========================以下为早期的文章今天在开发的过程中需要做一个Vue的...

原谅我一生不羁放歌搞文艺14阅读 20k评论 9

用了那么久的 SVG,你还没有入门吗?
其实在大部分的项目中都有 直接 或 间接 使用到 SVG 和 Canvas,但是在大多数时候我们只是选择 简单了解 或 直接跳过,这有问题吗?没有问题,毕竟砖还是要搬的!

熊的猫17阅读 1.5k评论 2

封面图
嘿,vue中keep-alive有个「大坑」你可能还不知道
背景是这样的,我们使用vue2开发一个在线客服使用的IM应用,基本布局是左边是访客列表,右边是访客对话,为了让对话加载更友好,我们将对话的路由使用<keep-alive>缓存起来。但是如果将所有对话都缓存,未...

wuwhs12阅读 2.5k

封面图
你可能需要的多文档页面交互方案
在日常工作中,面对不同的需求场景,你可能会遇到需要进行多文档页面间交互的实现,例如在 A 页面跳转到 B 页面进行某些操作后,A 页面需要针对该操作做出一定的反馈等等,这个看似简单的功能,却也需要根据不同...

熊的猫8阅读 1.2k

封面图
把React新文档投喂给 GPT-4 后...
大家好,我卡颂。最近,React新文档终于上线了。从内容上看,新文档包括:理论知识、学习指引API介绍从形式上看,新文档除了传统的文字内容,还包括:在线Demo示意图小测验可以说是阅读体验拉满。但是,由于文档...

卡颂7阅读 7.5k评论 3

封面图

Enjoy creating rather than coding!

1.1k 声望
93 粉丝
宣传栏