页面用浏览器自带返回和安卓物理返回死循环的话,直接看高潮部分

背景

折磨我两个工作日加周末一天的问题,我觉得还是有必要记录一下,为什么程序员总是加班,就是遇到这些意想不到的问题

需求

领导:我想做两个页面,放在微信里面可以访问

我:简单啊,用H5实现

产品设计中...

产品:好了,看看没问题就开始开发吧

我:什么时候多了一个需要获取用户信息(产品总是给人惊喜不端)

没有试过微信授权这一块,首先内心三连问,能不能拒绝,能不能改需求,能不能通过熟悉的秘方实现;然而并没有什么用(笑哭表情)

开发中

业务功能没什么难点,模拟一个用户信息,很快就开发完成了...

微信网页授权

1.登录自己的服务号,查看已有的权限

注意:这里只能是服务号,订阅号没有权限,服务号只能由企业和组织申请

2.公众号设置

注意:下载这个文件放在域名对应的根目录下

3.链接的生成

"https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect"

以访问www.qq.com/#/detail.html为例,上面第2步的网页授权域名设置成 www.qq.com

REDIRECT_URI为encodeURIComponent('http://www.qq.com/#/detail.html')

SCOPE为snsapi_base或snsapi_userinfo,区别是只获取用户id,还是获取更多用户信息

state随便写吧,以123为例(没有看出具体有什么用)

其它参数不变

注意:为什么要用encodeURIComponent,你想想,你在url里面直接写url,怎么能直接把它解析成参数

4.放在微信里访问

把第3步上面生成的链接,做为聊天消息,拷贝到微信里面,点击打开,此时我们用alert(location.href)就会发现,地址变成了"http://www.qq.com/?code=生成的随机code&state=上面写的123#/detail.html"

// 获取url参数

export function getQueryVariable(variable) {

const query = window.location.search.substring(1)

const vars = query.split("&")

for (let i=0; i

const pair = vars[i].split("=")

if(pair[0] === variable) return pair[1]

}

return undefined

}

// 获取code的值

const code = getQueryVariable('code')

注意:code只能用一次,而且还有时间限制,code插入的位置尤其要注意,不是在

/#/后面,所以用vue或react的路由组件中获取路由参数方式是不可行的,老老实实的写原生js获取

5.通过code获取用户id

code获取到了以后前端就无能为力了,接下来的步骤只能交给后台了(数据安全性考虑,比如AppSecret不能暴露给前端),自古以来,前端的地位略低于后端,nodejs的出现极大的拯救了前端,虽然后面的事情前端做不了,但我们可以用nodejs或者是类似于postman这种的工具,把后面的接口模拟跑通,然后直接告诉后端,你该调什么接口,用什么参数,后端文档都不用看;当然你也可以做个小白纸,什么都抛给后端,让后端指挥你怎么做(在一个团队中,各个角色的重要性,就看能做的事情)

网页授权就这么搞完了,是不是很简单(笑哭表情),可以愉快的玩耍了

当我把这个链接通过微信右上角分享给同事一起测试时,啪啪打脸了...,呈现的现象

1.通过code获取用户id,报错了

2.分享标题,描述,图标好丑,我能不能改(好像没有分享这个需求,但不分享的话,用户怎么看,我要不要做,没有这个需求,我要不要把锅丢给产品,我好方,但仅有的一点点职业素养告诉我,我还是做吧,做为一个合格的程序员,必备的技能不就是脑补一些产品没想到需求吗(笑哭表情))

分析原因:

1.打印出分享的地址alert(location.href),为http://www.qq.com/?code=上一...,微信分享出去的是当前访问的地址(原滋原味,加了一些防腐剂,多了一个from=xxxx,应该是来源),但我理想中想要的是上面第3中的地址(重定向之前的地址),报错的原因是同一个code用了两次

解决思路:

1.自定义分享地址,此时的思路是,地址改成https://open.weixin.qq.com/co... 这种

2.自定义标题,描述和图片

3.最终方案看下面

微信网页分享

1.还是先配置相应的权限

2.生成签名(后端做的,前端可以选择跳过)

这个时候就不得不吐槽微信的文档了,残缺了,在第一步就卡住了,只能求助网友,后面我发现

这里有,IP白名单也要设置,否则是拿不到access_token的,其它的签名怎么生成的后端照着文档做就行了

注意点:网页授权和分享是两个完全独立的模块,分享的access_token和授权返回的access_token是完全不一样的概念

3.前端配置

yarn add weixin-js-sdk

此时我的版本是"weixin-js-sdk": "^1.4.0-test", 微信客户端的版本是7.0.4,竟然遇到一个大坑

微信官方让我用最新的接口,我试了很久都没有调通,总以为是自己的姿势不对,后面实在不行了,我试了一下老接口,竟然通了,竟然通了,竟然通了,我想崩溃了

上代码

wx.config({

debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,在pc端时会打印出来,不需要的话可以将true改成false。

appId: data.appid, // 必填,公众号的唯一标识

timestamp: data.timestamp, // 必填,生成签名的时间戳

nonceStr: data.nonceStr, // 必填,生成签名的随机串

signature: data.signature, // 必填,签名

jsApiList: ['onMenuShareAppMessage','onMenuShareTimeline','onMenuShareQQ','onMenuShareQZone']

})

wx.ready(function () {

//分享到朋友圈

wx.onMenuShareTimeline({

title, // 分享标题

link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致

imgUrl, // 分享图标

})

//分享给朋友

wx.onMenuShareAppMessage({

title, // 分享标题

desc, // 分享描述

link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致

imgUrl, // 分享图标

})

//分享到QQ

wx.onMenuShareQQ({

title, // 分享标题

desc, // 分享描述

link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致

imgUrl, // 分享图标

})

//分享到QQ空间

wx.onMenuShareQZone({

title, // 分享标题

desc, // 分享描述

link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致

imgUrl, // 分享图标

})

})

注意:

1.data是后台返回的签名信息

2.分享链接,该链接域名必须与当前页面对应的公众号JS安全域名一致,公众号里面配置的是www.qq.com,这里分享的地址只能是以www.qq.com开头的,和我们理想的https://open.weixin.qq.com/co... 开头差距很大(怎么授权,好方)

如果只是单纯的自定义分享,到这里就结束了,如果既要分享又要授权,又有问题需要解决了

4.重定向

进入页面之后。location.href = 'https://open.weixin.qq.com/co...' (下面都称为重定向)

用的是同一个页面,所以需要判断url有没有code,来决定是否要执行第2步,否则会死循环

文章写到这里,已经解决了授权+分享,是不是感觉故事很平稳,一部好的电影怎么能这么快结束

高潮(大坑来了)

现象

微信中打开页面,用安卓的物理返回键,点一下返回不了,需要连续快速点两下才能退出

分析原因

打开的页面是不带code的地址,经过重定向后,生成了带code的地址,此时浏览器的历史记录中会有两条记录,从带code的地址返回到不带code的地址,页面判断没有带code,又会重定向到带code的页面,产生了死循环

解决方案

1.不让它产生多一条的记录

首先想到的是location.replace(url), 发现把url替换成授权的地址时(https://open.weixin.qq.com/co...),并不会像想象中的那样工作,还是会有两条历史记录(不清楚微信为什么不解决,还是解决不了)

结果:失败

2.代码控制清除一条历史记录

const params = getQueryParams()

const code = sessionStorage.getItem('code')

if (!params.code && !code) {

let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${yourAppId}&redirect_uri=${encodeURIComponent(location.href)}&response_type=code&scope=snsapi_base&state=1#wechat_redirect`

window.location.replace(url)

} else if(!code){

sessionStorage.setItem('code', params.code)

history.back()

}

搜索了一大圈,看见了这段代码(来自:https://www.cnblogs.com/wonyu...),仿佛看见了光,里面比较讲究的就是

sessionStorage(只在当前会话有效),用当前会话窗口储存的code,来判断不带code的页面要不要重定向

看似很完美的代码,还是逃不过微信的大坑,通过链接进入时,偶尔会遇到页面空白

原因:

上面用到的历史记录返回,页面不刷新(偶尔),我尝试过强制微信浏览器刷新,甚至怀疑是vue的坑,然后用原生写了一段js来操作dom,并没有什么用

最后发现返回的时候,js都能正常的执行,UI不重新渲染,UI不重新渲染,UI不重新渲染,偶尔出现,不是必现,我再次好方

结果:偶尔失败

3.返回两次,才能退出

借鉴上面的思路,判断当前会话窗口储存的code是否有值,有值就不重定向

结果:解决了偶尔不渲染的问题和死循环的问题,但对于有轻微强迫症的我来说,需要点两次才能返回还是挺难接受的

本来属于愉快的周末,就在微信这个大坑里结束了,关上电脑,沉思一会(想想如何说服测试同学这个问题解决不了,是微信的坑(笑哭表情))

结尾

处女座最大的悲哀就是心里不能放事情,总感觉不踏实,休息也休息不好(悲哀)

突然想到前段时间开发的app,自己控制过android的返回,微信会不会也提供了自定义返回呢,经过一大堆的搜索,发现js就有能监听浏览器返回的事件(有些知识点不用,慢慢就忘了),兜兜转转了一大圈,至少用我的周末帮大家证明了网上说的很多方式行不通,哈哈哈,终极解决,上代码(vue的思路)

created () { // 当前需要直接退出的页面

window.history.pushState('_android_back', null, location.href)

window.addEventListener("popstate", this.popstate, false)

},

destroyed: function () { // 记得清除,不然单页面,其它页面也可以用

window.removeEventListener("popstate", this.popstate, false)

},

methods: {

popstate () {

wx.closeWindow() // 微信网页退出

}

}

注意:为什么要多window.history.pushState('_android_back', null, location.href)这句代码,因为popstate只能监听pushState创建的

备注:微信的文档会更新,当你使用时(看一下这篇文章的出生时间),最好参考官方文档,如果你觉得有一点帮助了你,请点个赞(程序员写文章不容易,最烦写这种随时可能过时的文章,哈哈哈)

微信授权Java重定向前端地址_微信网页授权+分享踩过的坑相关推荐

  1. url 微信公众号开发 配置失效_微信公众号开发之授权登录

    一.UnionId和openId 微信登录最重要的两个返回信息,一个是UnionId,一个是OpenId.两者之间有着必然的联系. UnionID机制的作用说明:如果开发者拥有多个移动应用.网站应用和 ...

  2. 微信接口开发之高级篇系列【网页授权详细说明【提供测试账号使用】】

    本篇文章你将学到:在自己做的微信网站里,利用oauth2.0网页授权接口获取用户的信息(openid,姓名,性别,地区,头像等).如大转盘等游戏记录哪个微信用户获得什么奖品.H5等小游戏需要把分数与对 ...

  3. java用户头像保存_微信授权后获取用户头像保存到服务器

    最近做一个有关微信授权登录的项目,关于授权就不多说了,我获取到用户基本信息,格式如下: $user_info = '{"openid":"xx","n ...

  4. java如何获取手机号码_微信小程序+Java获取用户授权手机号码

    前言 小程序内可以直接通过授权获取用户微信号绑定的手机号码或用户添加的其他手机号码,这样可以使得小程序在进行账户的身份可控上又提高了一步,那么应该如何来获取手机号码呢?这篇文章就和大家一起来研究一下. ...

  5. jssdk 获取微信收货地址_微信收货地址共享开发接口讲解

    写在前面的话:微信开发者文档写的比较清楚,也不容易出错,可是偏偏收货地址共享那儿写的比较绕,同时也会有很多坑,这里总结一下. ======正文开始====== 微信收货地址共享开发接口基本使用场景是: ...

  6. java实现qq抢红包_微信抢红包到底是怎么抢到的?

    " 微信抢红包功能,一下子拉近了长辈与我们之间的距离,每年都是盼望着亲人群抢红包,今天来给大家分享一下,为啥抢红包有人多,有人少,什么时候抢最合适?" 01 - 微信抢红包 场景描 ...

  7. java微信个人订阅号发信息_微信个人公众号开发-java

    一:申请公众号 无聊的去申请一个个人公众号,试了下微信实现自定义菜单与自定义对话的一些基本功能,如果多花点时间,金钱(= =!)还是有不少功能可以使用,还是蛮有意思的. 废话不多说,先看一下申请的流程 ...

  8. java微信无感支付怎么开通_微信支付之无感支付

    停车免密支付功能的开发  首先我们需要做的是申请微信商户号并开通微信代扣 场景图 前端功能开发: 车辆进场 车辆入场,停车场将用户车牌信息传给小程序.小程序根据车牌信息查询用户是否开通微信免密支付,将 ...

  9. obs多推流地址_微信小程序直播电脑端OBS推流直播教程

    微信小程序直播经过一个月的内测邀请,很多商家都已经开通了,之前的直播商家们都是用手机端推流直播的,本周微信官方团队更新了小程序直播插件,1.03版本的都支持电脑端推流了,下面就把具体操作图文教程传授给 ...

最新文章

  1. 哪个学校计算机系学大物,计算机系各专业专业及名校介绍
  2. GoEasy导入依赖的时候报错,包用不了,maven导包
  3. python实现真正的冒泡排序算法(时间复杂度优化版)!
  4. CSDN 十大技术主题盘点-云原生篇
  5. vue-router判断页面未登录时,自动跳转到登录页
  6. Linux下安装MySQL数据库以及用C语言编程存取数据库
  7. 商业认知,新的一年已经开始,许多老板都制订了新的目标
  8. Copula理论学习(三)--copula理论及参数copula函数族
  9. 阿佐数据分析python小抄【pandas基础数据处理】
  10. 基于DFA算法的敏感词过滤的go语言实现
  11. 如何在上海租房,数据有话说
  12. waves系统服务器,waves服务器:插件挂多了电脑宕机了?Impact Server服务器拯救你的电脑CPU!...
  13. html5辨别音高,音理知识基础:音高和时值
  14. 改为国内镜像时jenkins plugin提示: Update information obtained: 不可用 ago;
  15. B站最全Redis教程全集(2021最新版)(图灵学院诸葛)学习笔记一--五种数据结构与应用场景
  16. 51单片机与ESP8266轻松上手Onenet(二)--onenet AT指令测试
  17. 立创梁山派学习笔记——GPIO输出控制
  18. linux webdav服务,Ubuntu 配置WebDav服务器
  19. or计算遇到存在零“0”的情况
  20. base64图裁剪 php_php图片上传类(支持缩放、裁剪、图片缩略功能)

热门文章

  1. 逻辑分析仪软件基础使用方法( 基于logic 1.2.18)
  2. Rackspace云文件
  3. wavecom java_使用java操作wavecom来发送短信
  4. Error:No suitable device found: no device found for connection System eth0
  5. 应用概率统计(陈魁)第十章(方差分析)部分课后答案
  6. 学术报告系列(三) - 复杂海况无人艇虚实迁移学习方法
  7. 2021,中国计算产业的“攀登者勋章”
  8. [ChatGPT]-01-chatgpt可以做什么?如何调教
  9. 【老生谈算法】matlab实现压缩感知重构算法之正则化正交匹配追踪(ROMP)——ROMP
  10. 在本地环境中利用iodine工具建立DNS隧道