关于wx.getProfile和wx.login获取解密数据偶发失败的原因

这是手机号正确获取的方式。

wx.checkSession({
success(){
//session_key 未过期,并且在本生命周期一直有效
//session_key还在啊
Util.consolelog('session_key还在,在哪里?')
that.getPhoneNumber(e);
},
fail(){
// session_key 已经失效,需要重新执行登录流程
wx.login({
success(res) {
if (res.code) {
e.code=res.code;
that.getPhoneNumber(e);
} else {
Util.consolelog('登录失败!' + res.errMsg)
}
}
})
}
})

再看看获取头像等的方式

GetUserProfile: function (cb) {
var that = this;
console.log('this.globalData.GetUserProfile-that', that);
console.log('this.globalData.GetUserProfile-this', that.userInfo);
if (this.userInfo) {
//typeof cb == "function" && cb(this.globalData.userInfo)
typeof cb == "object" && cb.hasgetWxInfoSuccess(that.userInfo);
} else {

//调用登录接口
wx.getUserProfile({
desc: '业务需要',
success(res){
console.log('res',res);
wx.login({
success: function (r) {
// console.log('login',r)
typeof cb == "function" && cb(that.userInfo);


try {
var s = JSON.parse(res.rawData);
} catch (e) {
var s = {};
}

var o = {
nick: s.nickName,
sex: s.gender,
avatar: s.avatarUrl,
country: s.country,
city: s.city,
code: r.code,
province: s.province,
rawdata: res.rawData,
encryptedData: res.encryptedData,
signature: res.signature,
iv: res.iv,
rc_member_id: wx.getStorageSync('rc_member_id')
};
console.log('o', o);

$.ajax({
service: 'user.wxxcxLogin',
method: 'POST',
data: o,
succ: function (res,all) {
if (res && res.token) {
$.setSession(res);
if ($.store('RECM')) {
var Partner = require("model/Partner.js");
//有推荐会员ID+当前用户是登陆用户的话,发起关联关系2019年07月26日18:48:27
Partner.RecMember.Add({
data: {
r_user_id: $.store('RECM'),
channel: $.store('RECM_CHANNEL')?$.store('RECM_CHANNEL'):'link',
channel_params: $.store('RECM_CHANNEL_PARAMS')?$.store('RECM_CHANNEL_PARAMS'):'unknow',
},
succ: function (res) {
console.log('授权登陆时,推荐成功:', recm + '推荐了' + $.store('S[MEMBER]'))
},
fail: function (res,all) {
console.log('授权登陆时,推荐失败:', all.msg);

}
})
}

cb.hasgetWxInfoSuccess(that.userInfo);

}
}
});
}
});
}
});
}
},

看到区别没有,获取头像的地方是每次都wx.login后传递了一个r.code,但是实际上如果把这个code带给后端用来解密会偶发解密失败。

原因:

你看这几个参数都是getProfile里获取的

rawdata: res.rawData,
encryptedData: res.encryptedData,
signature: res.signature,

只有code:r.code是wx.login里获取的

你能确保res.encryptedData时用到的code和wx.login时的code一致吗?不一定的,官方有说明,特别是手机号获取的时候(说wx.login时会刷新登陆态,要checksession一下,这个同样适用于getProfile)。

===

仔细读官方下面的这段话

会话密钥 session_key 有效性

开发者如果遇到因为 session_key 不正确而校验签名失败或解密失败,请关注下面几个与 session_key 有关的注意事项。

  1. wx.login 调用时,用户的 session_key 可能会被更新而致使旧 session_key 失效(刷新机制存在最短周期,如果同一个用户短时间内多次调用 wx.login,并非每次调用都导致 session_key 刷新)。开发者应该在明确需要重新登录时才调用 wx.login,及时通过 auth.code2Session 接口更新服务器存储的 session_key。
  2. 微信不会把 session_key 的有效期告知开发者。我们会根据用户使用小程序的行为对 session_key 进行续期。用户越频繁使用小程序,session_key 有效期越长。
  3. 开发者在 session_key 失效时,可以通过重新执行登录流程获取有效的 session_key。使用接口 wx.checkSession可以校验 session_key 是否有效,从而避免小程序反复执行登录流程。
  4. 当开发者在实现自定义登录态时,可以考虑以 session_key 有效期作为自身登录态有效期,也可以实现自定义的时效性策略。

解决方案:

<button @tap="GetUserProfile"></button>

1、 

getUserProfilePromise() {
return new Promise((resolve, reject) => {
uni.getUserProfile({
desc: '获取您的昵称、头像、性别',
success: userRes => {
console.log('getUserProfile-res', userRes);
resolve(userRes);
},
fail: userErr => {
uni.showToast({
title: '授权失败',
icon: 'error'
});
console.log('getUserProfile-err', userErr);
reject(userErr);
}
});
});
},
getLoginCode() {
return new Promise((resolve, reject) => {
uni.login({
provider: 'weixin',
success: loginRes => {
console.log('loginRes', loginRes);
resolve(loginRes);
}
});
});
},


GetUserProfile: function (cb) {
var that = this;
console.log('this.globalData.GetUserProfile-that', that);
console.log('this.globalData.GetUserProfile-this', that.userInfo);
if (this.userInfo) {
//typeof cb == "function" && cb(this.globalData.userInfo)
typeof cb == "object" && cb.hasgetWxInfoSuccess(that.userInfo);
} else {
//使用promise防止偶发解密失败问题2021-10-16 22:59:12
// 注意使用函数的写法,避免出现错误
let userProFile = this.getUserProfilePromise();
let loginCode = this.getLoginCode();
loginCode
.then(code => {
return code;
})
.then(codeFromWxLogin => {
return new Promise((resolve, reject) => {
userProFile
.then(res => {
resolve({ codeFromWxLogin, iv: res.iv, rawData: res.rawData, encryptedData: res.encryptedData, signature: res.signature,userInfoFromProfile:res.userInfo});
})
.catch(err => {
reject(err);
});
});
})
.then(res => {
console.log('promise-res', res);
//执行网络请求
typeof cb == "function" && cb(that.userInfo);

/* try {
var s =res;// JSON.parse(res.rawData);
} catch (e) {
var s = {};
} */

var o = {
nick:res.userInfoFromProfile.nickName,
sex:res.userInfoFromProfile.gender,
avatar:res.userInfoFromProfile.avatarUrl,
country:res.userInfoFromProfile.country,
city:res.userInfoFromProfile.city,
province:res.userInfoFromProfile.province,
rawdata: res.rawData,
encryptedData: res.encryptedData,
signature: res.signature,
iv: res.iv,
code: res.codeFromWxLogin.code,
rc_member_id: wx.getStorageSync('rc_member_id')
};
console.log('o', o);

$.ajax({
service: 'user.wxxcxLogin',
method: 'POST',
data: o,
succ: function (res,all) {
if (res && res.token) {
$.setSession(res);
if ($.store('RECM')) {
var Partner = require("model/Partner.js");
//有推荐会员ID+当前用户是登陆用户的话,发起关联关系2019年07月26日18:48:27
Partner.RecMember.Add({
data: {
r_user_id: $.store('RECM'),
channel: $.store('RECM_CHANNEL')?$.store('RECM_CHANNEL'):'link',
channel_params: $.store('RECM_CHANNEL_PARAMS')?$.store('RECM_CHANNEL_PARAMS'):'unknow',
},
succ: function (res) {
console.log('授权登陆时,推荐成功:', recm + '推荐了' + $.store('S[MEMBER]'))
},
fail: function (res,all) {
console.log('授权登陆时,推荐失败:', all.msg);

}
})
}

cb.hasgetWxInfoSuccess(that.userInfo);

}
}
});

})
.catch(err => {
console.log('userProfile-err', err);
});
}
},

原文地址:https://www.cnblogs.com/showker/p/15415541.html