vue中使用微信公众号js-sdk踩坑记录


Posted in Javascript onMarch 29, 2019

最近又在vue中捣鼓了下微信公众号api的接入,不得不说这里边水是真的深啊,上次分享了微信授权登录和js-sdk签名的部分,其中很多朋友私信我表示了疑惑,今天我就再次尝试理顺一下这里边的坑吧:

微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。
通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。

分享页面到朋友圈

上文是从官方文档中摘出来的,由此可见,我们如果要实现在公众号的内嵌h5中实现微信分享,支付等功能,就得引入js-sdk。
使用js-sdk有一个关键的环节,那就是通过config接口注入权限验证配置,而配置中有个signature参数是需要借助服务端获取的,这里就不过多探讨了,大家通过官方文档可以深入了解。

Hash or History?

上篇文章,我推荐大家在vue中配置vue-router使用hash模式,那么hash模式和history模式到底有什么差别呢?我举个栗子,假设我们都通过http://domain.com进入,然后跳转到路由为/jssdk的页面需要用到jssdk,那么实际js-sdk进行签名校验时所获取的当前页面url在ios和andrioid是不同的,这里我通过表格展示出来:

vue中使用微信公众号js-sdk踩坑记录

真相都在表格里,我表达能力不好恕我偷个懒23333333。

如果阁下没有接入分享指定页面的需求的话,hash模式很方便,但是无奈笔者需要接微信分享,如果使用hash模式,分享出去的地址,微信会自动处理掉#后边的部分,那么我就没法分享指定页面到朋友圈或者给朋友了。

怎么办呢,只能硬着脑子解决history问题咯,其实也好解决,就是iOS需要使用第一次进入页面的URL获取签名,安卓每次路由切换都重新配置签名。我这里罗列两个方案:

1.入口文件中记录页面URL,在页面组件创建完成后,ios获取记录的url进行签名,android获取当前路由(window.location.href.split('#')[0]),请移步我的上一篇博客

2.入口文件中直接进行签名和注入配置,仅针对android在每次切换路由时再重新签名和配置。该方案适合所有页面都需要用到js-sdk的情况

问题记录

现列出我在捣鼓过程中遇到的一个个bug:

1.安卓设备能分享ios设备不能分享;
出现该问题的原因就是因为采用了history模式,且没有考虑到ios校验签名获取的url是第一次访问的url而使用了切换后的url。

2.ios设备进入页面时不能分享,手动刷新页面后才能分享;
多次测试后我发现,测试分享的时候,如果是访问的链接没带http://的话,除了首页其他页面都是失效的,测试时落地页ur必须要加http://

3.点击链接能正常分享,点击别人分享的图文消息之后不能分享;

猜想1:点击图文消息时候,微信进行签名校验的url去掉了自己添加的参数,所以我们在进行签名时也要去掉微信添加的参数? 所以我把微信参数即`?from=singlemessage&isappinstalled=0'这个部分去掉,结果依旧是分享失败,而我自己随意加一个参数,分享则正常,我随意加两个参数的时候,分享却又不正常了。

猜想2: 微信分享进行签名校验的url仅能允许一个参数?所以我这样写:url = location.href.split('&')[0],验证后发现是错误的,再仔细一想我居然有这么可怕的想法,连官方文档都不相信了。

猜想3:url难道需要进行编码?即url = encodeURIComponent(window.location.href.split('#')[0])经我多次debug,终于找到问题,就是需要对签名的url进行编码,word哥,不容易啊

仅需要对签名的url进行编码,分享配置中的url不需要编码
仅需要对签名的url进行编码,分享配置中的url不需要编码
仅需要对签名的url进行编码,分享配置中的url不需要编码

这里又是一个坑,务必小心。

经常N次的debug和尝试之后我码了几十行代码,解决了以上所有问题,回首一看我真的是年轻啊,也就那么简单的逻辑,也许换个人一步就到位了,我却和各种各样的bug战斗了n多遍(改动一点代码就要上生产环境debug的心酸有谁能懂),唉。。。

Coding

分享一下我怎么按照第二种方案进行微信分享配置的
由于我项目中需求是基本所有页面都需要能分享,所以在每个page组件中去获取签名是不实际的,所以我就想借助vue-router的after钩子去完成分享配置的操作,对于android则还需要重新进行签名。

// main.js
...
import wx from 'weixin-js-sdk'
import request from 'axios'
...
router.afterEach((to, from) => {
 let _url = window.location.origin + to.fullPath
 // 非ios设备,切换路由时候进行重新签名
 if (window.__wxjs_is_wkwebview !== true) {
 request.get('/api/jssdk?url=' + encodeURIComponent(_url)).then(function (_lists) {
  // 注入配置
  wx.config({
  ...
  })
 })
 }
 // 微信分享配置
 wx.ready(function () {
 wx.onMenuShareTimeline({
  ...
 })
 wx.onMenuShareAppMessage({
  ...
 })
 })
})

...
// ios 设备进入页面则进行js-sdk签名
if (window.__wxjs_is_wkwebview === true) {
 let _url = window.location.href.split('#')[0]
 request.get('/api/jssdk?url=' + encodeURIComponent(_url)).then(function (res) {
 let _lists = res
 wx.config({
  debug: false,
  appId: _lists.appId,
  timestamp: _lists.timestamp,
  nonceStr: _lists.nonceStr,
  signature: _lists.signature,
  jsApiList: ['chooseImage', 'uploadImage', 'previewImage', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareTimeline', 'chooseWXPay']
 })
 })
}

总结: 总之简要概括就是要想分享成功,必须签名是成功的,要想签名成功,必须保证调用签名配置的时候微信校验签名获取的url(ios永远是第一次进入页面的url)和我们请求服务端获取签名时提交的url一致。

调用微信支付

两个方案何去何从

h5使用微信支付,细心的人会发现,微信是有两个方案的,我大致了解了一个,一个是js-sdk中开放的能力,一个是微信支付开放平台提供的接口

js-sdk版本:

vue中使用微信公众号js-sdk踩坑记录

微信支付版本:

vue中使用微信公众号js-sdk踩坑记录

如果你只需要在公众号中调用支付,两个方法都可以,笔者由于已经使用js-sdk接入了其他功能,所以这里就选择了chooseWXPay方式。

接入步骤

在其他功能都接入成功的前提下,接支付就很快很方便了,笔者把主要步骤列下:

  1. 微信公众平台中配置好js安全接口域名(例如www.imwty.com),这个是调用js-sdk的前提,公众号支付也是基于js-sdk;
  2. 微信支付平台中设置支付目录,参见微信支付开发文档,这里要说明的是,你需要进行支付的页面路由是什么,就要配置什么,而且需要在后边加上/(例如www.imwty.com/pay/)
  3. 调用js-sdk签名配置(wechat.config),上文已有提及。
  4. 在点击支付按钮的逻辑中,调用wechat.chooseWXPay()方法,该方法也涉及到支付签名,需要从服务端去获取签名信息

注意的点:访问支付页面务必不要遗漏/,微信那边会严格比较调用第4步骤时你所在的页面路由和支付平台中设置的路由是否一致。

Coding

这里主要展示第4步骤中笔者的写法,仅供参考

...
methods () {
 handlerPay () {**粗体文本**
 let self = this
 // 进行支付签名
 apiUtil.get('/api/jssdk/pay', {amount: this.amount}).then(function (wxmsg) {
  self.$wechat.chooseWXPay({
  // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
   appId: wxmsg.appId,
   timestamp: wxmsg.timeStamp,
   nonceStr: wxmsg.nonceStr, // 支付签名随机串,不长于 32 位
   package: wxmsg.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
   signType: wxmsg.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
   paySign: wxmsg.paySign, // 支付签名
   success: function (res) {
   // 支付成功的回调函数
   },
   cancel: function (res) {
   // 支付取消的回调函数
   },
   error: function (res) {
   // 支付失败的回调函数
   }
 }).catch(function () {
  ...
 })
 }
}

结语

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

Javascript 相关文章推荐
js将控件隐藏的方法及display属性介绍
Jul 04 Javascript
用unescape反编码得出汉字示例
Apr 24 Javascript
Jquery1.9.1源码分析系列(六)延时对象应用之jQuery.ready
Nov 24 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
Mar 22 Javascript
JS实现动态表格的添加,修改,删除功能(推荐)
Jun 15 Javascript
ES6记录异步函数的执行时间详解
Aug 31 Javascript
js实现鼠标拖拽多选功能示例
Aug 01 Javascript
Vee-Validate的使用方法详解
Sep 22 Javascript
基于express中路由规则及获取请求参数的方法
Mar 12 Javascript
详解Vue2.5+迁移至Typescript指南
Aug 01 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
Sep 17 Javascript
element-ui中按需引入的实现
Dec 25 Javascript
微信小程序学习笔记之本地数据缓存功能详解
Mar 29 #Javascript
微信JS-SDK updateAppMessageShareData安卓不能自定义分享详解
Mar 29 #Javascript
详解vue配置后台接口方式
Mar 29 #Javascript
微信小程序学习笔记之获取位置信息操作图文详解
Mar 29 #Javascript
点击按钮弹出模态框的一系列操作代码实例
Mar 29 #Javascript
VUE解决微信签名及SPA微信invalid signature问题(完美处理)
Mar 29 #Javascript
微信小程序生成分享海报方法(附带二维码生成)
Mar 29 #Javascript
You might like
discuz安全提问算法
2007/06/06 PHP
php中使用addslashes函数报错问题的解决方法
2013/02/06 PHP
解析关于java,php以及html的所有文件编码与乱码的处理方法汇总
2013/06/24 PHP
php类常量用法实例分析
2015/07/09 PHP
php+ajax无刷新上传图片实例代码
2015/11/17 PHP
PHP面向对象程序设计之对象生成方法详解
2016/12/02 PHP
List the Codec Files on a Computer
2007/06/11 Javascript
用js实现的自定义的对话框的实现代码
2010/03/21 Javascript
简单的代码实现jquery定时器
2014/01/03 Javascript
JavaSciprt中处理字符串之sup()方法的使用教程
2015/06/08 Javascript
JS实现网页右侧带动画效果的伸缩窗口代码
2015/10/29 Javascript
详解页面滚动值scrollTop在FireFox与Chrome浏览器间的兼容问题
2015/12/03 Javascript
Async Validator 异步验证使用说明
2017/07/03 Javascript
vue全局使用axios的方法实例详解
2018/11/22 Javascript
vue.draggable实现表格拖拽排序效果
2018/12/01 Javascript
微信小程序实现的动态设置导航栏标题功能示例
2019/01/31 Javascript
[36:16]完美世界DOTA2联赛PWL S3 access vs Rebirth 第一场 12.19
2020/12/24 DOTA
Python获取当前时间的方法
2014/01/14 Python
Python实现爬取知乎神回复简单爬虫代码分享
2015/01/04 Python
Python之str操作方法(详解)
2017/06/19 Python
Pyspider中给爬虫伪造随机请求头的实例
2018/05/07 Python
如何实现删除numpy.array中的行或列
2018/05/08 Python
Django 开发环境与生产环境的区分详解
2019/07/26 Python
Python一键安装全部依赖包的方法
2019/08/12 Python
pycharm不能运行.py文件的解决方法
2020/02/12 Python
详解H5本地储存Web Storage
2017/07/03 HTML / CSS
HTML5 本地存储之如果没有数据库究竟会怎样
2013/04/25 HTML / CSS
香蕉共和国工厂店:Banana Republic Factory
2018/06/09 全球购物
农药学硕士毕业生自荐信
2013/09/25 职场文书
大学生社会实践评语
2014/04/25 职场文书
产品生产计划书
2014/05/07 职场文书
实习指导教师评语
2014/12/30 职场文书
学生检讨书
2015/01/27 职场文书
2016创先争优活动党员公开承诺书
2016/03/24 职场文书
vue+elementui 实现新增和修改共用一个弹框的完整代码
2021/06/08 Vue.js
SpringCloud中分析讲解Feign组件添加请求头有哪些坑梳理
2022/06/21 Java/Android