小程序手机号如何授权——过程与细节(sessionKey过期,wx.checkSession())
一切来源于官方文档。
官方文档中,button组件中就有提供专门用于获取手机号的写法;——小程序开放文档
进入具体说明可以看到:官方代码示例
<button class="login_btn" plain="true" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
getPhoneNumber:function(e){
var that = this;
if(wx.getStorageSync("session_key")){//先判断缓存中是否有session_key,
wx.checkSession({//检测session_key是否过期
success: function() {
console.log("未过期")
if(e.detail.errMsg=='getPhoneNumber:ok'){
console.log(e)
that.$http('xxxx解密手机号接口',{//将手机号授权返回的参数,传给后端,进行手机号解密
sessionKey:wx.getStorageSync('session_key'),
encryptedData:e.detail.encryptedData,
iv:e.detail.iv,
}).then(res=>{
if(res.code==20000){
console.log(res.data)//成功拿到用户手机号
}else{
}
})
}else{
}
},
fail: function () {//session_key过期,则需要微信登录接口wx.login(),来重新获取session_key
console.log("过期")
wx.login({
success(res) {
console.log('wxlogin',res);
if (res.code) {
// 服务器端接口--获取sessionKey
that.$http('xxx获取session_key接口',{//,那code换取session_key,和并存入缓存
code:res.code,
}).then(res=>{
if(res.code==20000){
wx.setStorageSync('session_key', res.data.session_key);
if(e.detail.errMsg=='getPhoneNumber:ok'){
console.log(e)
that.$http('xxxx解密手机号接口',{//将手机号授权返回的参数,传给后端,进行手机号解密
sessionKey:wx.getStorageSync('session_key'),
encryptedData:e.detail.encryptedData,
iv:e.detail.iv,
}).then(res=>{
if(res.code==20000){
console.log(res.data)//成功拿到手机号
}else{
}
})
}else{
}
}
})
} else {
console.log('失败!' + res.errMsg)
}
},
fail(res){
console.log('error',res);
}
})
}
})
}else{//如果缓存中没有session_key,直接按步骤,登录,拿session_key,进而获取手机号
wx.login({
success(res) {
console.log('wxlogin',res);
if (res.code) {
// 服务器端接口--获取sessionKey
that.$http('xxx获取session_key接口',{
code:res.code,
}).then(res=>{
if(res.code==20000){
wx.setStorageSync('session_key', res.data.session_key);
if(e.detail.errMsg=='getPhoneNumber:ok'){
console.log(e)
that.$http('xxxx解密手机号接口',{
sessionKey:wx.getStorageSync('session_key'),
encryptedData:e.detail.encryptedData,
iv:e.detail.iv,
}).then(res=>{
if(res.code==20000){
console.log(res.data)//成功拿到手机号
}else{
}
})
}else{
}
}
})
} else {
console.log('失败!' + res.errMsg)
}
},
fail(res){
console.log('error',res);
}
})
}
},
总结:正常按照官方文档操作就没什么大问题,只不过尤其要注意一下,sessionKey是否过期,如果过期就会出现解密失败,这也是为什么有的同志在实际项目中遇到,明明之前可以的,怎么有的时候解密失败啊。
重点来了:关于wx.checkSession,微信社区有反馈bug,说调用wx.checkSession一直走success,然后实际调用手机号解密却又失败。。。。。
(这里做出我自己的分析:之所以wx.checkSession一直走success,很大可能是因为小程序默认的在app.js文件中的wx.login()方法没有删除,导致你在手机号授权页之前就更新了登录态,所以一直成功;也可能是因为特殊业务的原因在别的页面也有wx.login()的方法存在。接下来说一说为啥sessionKey没过期,但是手机号解密却失败呢?原因可能有几种情况:1,登录态未过期,其实真的不代表你的sessionKey就不过期,尤其是我这种不按官方来,非要把sessionKey存在我客户端的人来说;2,借着1来说,也可能就是你的sessionKey没有更新,这种没更新可能就是你别的地方调用wx.login()中紧接着调用的接口后端处理时是会更新sessionKey的,但是你没有更新你本地的sessionKey,可以检查下,因为你不可能就单单调个wx.login(),里面肯定有接口请求的,看一下;3,就是看下图:
有的同志可能想着我在回调里紧跟着调用wx.login()拿到最新的sessionKey不就不怕过期了吗?哎!完犊子,此时sessionKey是最新的了,但是手机号回调加密的内容是先触发的啊,早于你新生成的sessionKey啊,换句话说,加密的是老的那个当时还未过期的sessionKey,然后你这会再拿最新的sessionKey去解密,势必解密失败的。当然如果是像我上头代码里的,首次调用时,在回调里拿sessionkey就是没问题的)
补充:关于button样式的问题,因为授权必须通过button来触发,但是直接复制过来的button样式又没办法用,需要自己去改;
.login_btn{
width: 100rpx;
height: 44rpx;
padding: 0;
background-color: transparent;
border-radius: 22rpx;
border-color: #ffffff;
line-height: 40rpx;
font-size: 26rpx;
outline: none;
color: #ffffff;
margin: 0;
margin-bottom: 12rpx;
}
实际样式结合业务调整即可
这个属性也可以作为参考。