uniapp开发h5应用进行微信网页授权登录获取code失败

最近正在做企业微信内的h5应用,有微信授权登录这么个需求。微信授权登录并不复杂,整个流程就是按照文档上描述的:在入口页构造网页授权链接,跳转到该链接,微信会重定向到入口页并将code拼在url上,前端将code给到后端,后端调用微信提供的服务端api即可完成登录。

// 构造如下链接来获取code参数 
https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect\_uri=REDIRECT\_URI&response\_type=code&scope=snsapi\_base&state=STATE#wechat\_redirect

下面贴上代码,供没做过的同学参考:

onload(params) { 
	// 获取url上的code 
	let code = params.code 
	if (code) { 
		// code存在,调用接口将code传递给后端
	} else { 
		// code 不存在,走微信网页授权逻辑 
		
		// 当前网页的url,供微信重定向使用 
		let loc_href = window.location.href; 
		
		// 对当前页面的url进行微信要求的urlEncode 处理 
		loc_href = encodeURIComponent(loc_href);
		
		// 构造获取code的链接 
		let appId = '';
		
		// 企业微信应用的CorpID 或者 微信公众号的appid 
		let wxUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect\_uri=${loc_href}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`;
		
		// 跳转链接获取code 
		location.href = wxUrl; } }

代码写好后,在微信开发者工具进行调试,发现页面在微信授权链接与当前页面链接之间来回跳转,说明我们的代码一直在执行onload中的else逻辑,表示我们并没有拿到code。 因为之前做过微信网页授权登录,确信自己的代码逻辑是没有问题的。唯一区别是之前的项目做的是多页面应用,使用的是自己开源的框架fast-h5plus

我将微信重定向之后的链接拷贝了出来,如下所示:

http://www.xxxx.com/index.html?code=xxxxxx/#/pages/weAuth/weAuth

将链接贴出来之后,发现微信并没有出现bug,它把code返给了我们,只是拼的位置有些不同

// 我们需要的
http://www.xxx.com/index.html#/pages/weAuth/weAuth?code=xxxxx

// 微信实际提供的
http://www.xxx.com/index.html?code=xxxx/#/pages/weAuth/weAuth

代码无法获取code说明code拼接在路由的#号之前uniapp是无法进行解析的,自然就不能通过onload的回调参数去获取。

当时去微信社区搜索了一番,社区中提供的解决办法有两种:

  • 使用hsitory模式替代hash路由模式
  • 使用其他方法获取url上的code值

因为公司没打算使用history模式,所以只能使用第二种解决办法,代码如下

onload(){
	// 获取url上的code
	let code = this.getQueryVariable('code')
	if (code) {
		// code存在,调用接口将code传递给后端
	} else { 
		// code 不存在,走微信网页授权逻辑 
		
		// 当前网页的url,供微信重定向使用 
		let loc_href = window.location.href; 
		
		// 对当前页面的url进行微信要求的urlEncode 处理 
		loc_href = encodeURIComponent(loc_href);
		
		// 构造获取code的链接 
		let appId = '';
		
		// 企业微信应用的CorpID 或者 微信公众号的appid 
		let wxUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect\_uri=${loc_href}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`;
		
		// 跳转链接获取code 
		location.href = wxUrl; } } 
},
// 获取url参数
getQueryVariable(variable) {
      var query = window.location.search.substring(1);
      var vars = query.split("&");
      for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) { return pair[1]; }
      }
      return (false);
}

通过手动解析url获取code成功的解决了该问题,拿到code,返给后端,登录成功跳转首页,一切正常。

本来文章写到这里就该结束了,但在后续开发中,当页面需要使用微信jsapi时出问题了。

某个页面需要使用微信jsapi时,流程为 前端将当前url返给后端,后端将timestamp,nonceStr,signaure返过来。前端调用wx.config方法进行接口注入权限验证配置

wx.config({
    beta: true,// 必须这么写,否则wx.invoke调用形式的jsapi会有问题
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,企业微信的corpID
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见 附录-JS-SDK使用权限签名算法
    jsApiList: [] // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
});

在开发者工具调试时,控制台一直提示授权失败,签名无效。查看了文档中对签名生成的描述如下:

签名生成规则如下: 参与签名的参数有四个:

  • noncestr(随机字符串),
  • jsapi_ticket(如何获取参考“获取企业jsapi_ticket”以及“获取应用的jsapi_ticket接口”),
  • timestamp(时间戳),
  • url(当前网页的URL, 不包含#及其后面部分)

前端只是传递了url给后端生成签名,后端同学也反复检查了代码表示没有问题。那问题只有可能出在传递的这个url上。

微信文档描述 url 参数为当前网页的URL,不包含#及其后面部分。

正常的一个url 
http://www.xxx.com/index.html#pages/index/index?id=xxxx

去掉#号之后的url 
http://www.xxx.com/index.html

但因为我们在hash模式下,微信授权之后url变成了这样:
http://www.xxx.com/index.html?code=xxxx#/pages/index/index?id=xxx

去掉#号之后地址
http://www.xxx.com/index.html?code=xxxx

问题极有可能出在这里。去掉url上的?及后面的所有字符,传递给后端,后端重新生成签名后再执行wx.config,授权成功,问题解决!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章