客户端
getPhoneNumber: function (e) {
let that=this;
wx.login({
success: function (res) {
if (e.detail.errMsg == 'getPhoneNumber:fail user deny') {
wx.navigateTo({
url: '../../pages/userLogin/userLogin',
});
} else {
if (e.detail.errMsg == 'getPhoneNumber:fail:cancel to confirm login') {
wx.navigateTo({
url: '../../pages/userLogin/userLogin?url='+that.data.url
});
}
else {
//console.log(res.code);
wx.request({
url: api.AESdecrypt,
data: {
'encryptedDataStr': e.detail.encryptedData,
'code': res.code,
'iv': e.detail.iv
},
method: 'post',
header: { 'content-type': 'application/x-www-form-urlencoded' },
success: function (data) {
console.log(data);
app.globalData.userInfo = data.data.data;
setTimeout(function(){
wx.navigateBack({ changed: true });//返回上一页
},500);
},
error: function () {
tip.showToast('error');
},
fail: function (err) {
tip.showToast(err);
}
})
}
}
}
});
},
服务端
try
{
string encryptedDataStr = System.Web.HttpContext.Current.Request["encryptedDataStr"],
code = System.Web.HttpContext.Current.Request["code"],
iv = System.Web.HttpContext.Current.Request["iv"];
ReturnData resultMsg = new ReturnData();
resultMsg.state = (int)StatusCodeEnum.Success;
resultMsg.message = StatusCodeEnum.Success.GetEnumText();
string strresult = "";
string Appid = "Appid";
string Secret = "Secret ";
string grant_type = "authorization_code";
GetUsersHelper GetUsersHelper = new Controllers.GetUsersHelper();
//向微信服务端 使用登录凭证 code 获取 session_key 和 openid
string url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Appid + "&secret=" + Secret + "&js_code=" + code + "&grant_type=" + grant_type;
Stream s_re = WebRequest.Create(url).GetResponse().GetResponseStream();
StreamReader sr = new StreamReader(s_re, Encoding.UTF8);
string strLine = sr.ReadToEnd();
sr.Close();
//将字符串转换为json格式
JObject jo = (JObject)JsonConvert.DeserializeObject(strLine);
result res = new result();
try
{
//微信服务器验证成功
res.openid = jo["openid"].ToString();
res.session_key = jo["session_key"].ToString();
}
catch (Exception)
{
//微信服务器验证失败
res.errcode = jo["errcode"].ToString();
res.errmsg = jo["errmsg"].ToString();
WriteInfo(res.errmsg);
}
if (!string.IsNullOrEmpty(res.openid))
{
//用户数据解密
strresult = GetUsersHelper.AESDecrypt(encryptedDataStr, res.session_key,iv);//.AES_decrypt(encryptedDataStr,res.session_key,iv);//
JObject jos = (JObject)JsonConvert.DeserializeObject(strresult);
ResultInfo ress = new ResultInfo();
ress.phoneNumber = jos["phoneNumber"].ToString();
var model = Ioc.Get<IUserRepository>().FindMobile(ress.phoneNumber);
resultMsg.data = model;
}
else
{
strresult = null;
resultMsg.data = strresult;
}
return resultMsg;
}
catch (Exception ex)
{
WriteInfo(ex.Message);
return new ReturnData
{
state=200,
message="error",
data=null
};
}
解密.net
public string AESDecrypt(string inputdata, string AesKey, string AesIV)
{
try
{
RijndaelManaged rijalg = new RijndaelManaged();
//-----------------
//设置 cipher 格式 AES-128-CBC
rijalg.KeySize = 128;
rijalg.Padding = PaddingMode.PKCS7;
rijalg.Mode = CipherMode.CBC;
rijalg.Key = Convert.FromBase64String(AesKey);
rijalg.IV = Convert.FromBase64String(AesIV);
byte[] encryptedData = Convert.FromBase64String(inputdata);
//解密
ICryptoTransform decryptor = rijalg.CreateDecryptor(rijalg.Key, rijalg.IV);
string result;
using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
result = srDecrypt.ReadToEnd();
}
}
}
return result;
}
catch (Exception ex)
{
ApiUserController apis = new ApiUserController();
apis.WriteInfo("jiemi"+ex.Message);
return null;
}
}
我来解答下吧,这问题我也遇到过,问题出在哪里呢,就出在点击 button 的地方,没有 wx.login 得到code 的时候,iv和encryptedData 就已存在一个session_key ,和之后得到的session_key 就不同了,我第一的逻辑是在点击button按钮的时候重新获取code,发送请求给服务器,让服务器去解密新的session_key和opendid 这样会有一定的几率导致 登录态session_key 更新,后台会报 解密微信用户信息异常 :javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption 当然这个报错是有一定的概率的,这就是楼主的情况 。 我之后想过 登录之后再调用一次 wx.login 方法 获取下code 再等点击获取电话号码按钮的时候 把这个code传递给后台,但是这个code 会有 5分钟的有效期 超过5分钟就会报 invalid code 失效的code 最后想到了 微信的api wx.checksession方法,但是该方法只会去校验 session_key是否有效,并不能去校验code 是否过期 ,由于session_key的过期时间官方没有给,code的过期时间只有5分钟,所以还得转变思路,就是在使用wx.checksession的时候在成功的回调里 说明session_key是有效的,所以就给后台传递一个有效的标识,让后台使用之前的session_key,带上点击事件e里面获取的iv 和 encryptedData 来解密用户的电话号码 在失败的回调里,说明这个时候的session_key失效了,就走楼主的逻辑,重新调用wx.login方法,获取最新的code 交给后台去解密有效的session_key,最终解决该问题
//如果用户点击确定就采取的操作
if (e.detail.errMsg === 'getPhoneNumber:ok') {
//测试会话是否有效 code是否过期
wx.checkSession({
success(){
//session_key 未过期,并且在本生命周期一直有效 发送请求获取电话号码 usesessionkey为session_key是否过期的标识 getPhone 是通用的进行解密电话号码的方法
that.getPhone(that.data.usesessionkey, e.detail.iv, e.detail.encryptedData, that);
console.log('success');
},
fail(){
console.log('fail');
// session_key 已经失效,需要重新执行登录流程 获取新的code 发送给后台去获取最新的sesson_key
wx.login({
success(res) {
if (res.code){
that.getPhone(res.code, e.detail.iv, e.detail.encryptedData, that);
}
}
})
}
})
}
已经找到根源了,详情去看我博客吧 微信小程序加密解密 C# 以及 填充无效,无法被移除错误的解决方案 Padding is invalid and cannot be removed
求解
先在onload里调用https://api.weixin.qq.com/sns/jscode2session?appid=" + Appid + "&secret=" + Secret + "&js_code=" + code + "&grant_type=" + grant_type;获取session_key,并记录,然后再进行解密,解密时把session_key一同传过去
我也是遇到这种情况,不知道怎么解决了
先在onload里调用https://api.weixin.qq.com/sns/jscode2session?appid=" + Appid + "&secret=" + Secret + "&js_code=" + code + "&grant_type=" + grant_type;获取session_key,并记录,然后再进行解密,解密时把session_key一同传过去