关键坑点:
1. 不了解调用流程:流程->前台JS获取code-->post至后台api-->先获取session_key【调用微信api,返回json】-->解密手机号方法
2. 解密方法缺少包,需要不断添加包
3.解密方法没有问题,仍然无法获取,网上找资料清理缓存。问题解决。
第一步:wxml增加按钮
第二步:js文件调用后台
getPhoneNumber(e) {
console.log(e.detail.errMsg)
console.log(e.detail.iv)
var encryptedData = e.detail.encryptedData
console.log(encryptedData)
var code=""
var that = this;
console.log(e.detail.errMsg == "getPhoneNumber:ok");
if (e.detail.errMsg == "getPhoneNumber:ok") {
wx.login({
success: function (res) {
code = res.code
console.log("code_s")//这就是code
console.log( res.code)//这就是code
console.log("code_e")//这就是code
wx.request({
url: 'https://XXXXXXX',
method: "post",
header: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
},
data: {
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
code: res.code
},
success: function (res) {
console.log(res);
}
})
}
})
}
},
第三步:后台代码,分2步;第一步获取seesion_key;第二步解密手机号
Api服务方法
@RequestMapping("/decodephone")
public void decodePhone(HttpServletRequest request, HttpServletResponse response,String encryptedData,String iv,String code){
String mbody=StringUtils.ReadAsChars(request);
System.out.println(mbody);
String msession_key= HttpUtil.doGet("https://api.weixin.qq.com/sns/jscode2session","appid=您的API的ID&secret=您的秘钥&js_code=前端传过来的CODE&grant_type=authorization_code");
WeChatAppSessionModel mdl1=JSONObject.parseObject(msession_key, WeChatAppSessionModel.class);
if(mdl1 !=null && mdl1.getSession_key()!=null)
{
try {
mbody=AES.wxDecrypt(encryptedData, mdl1.getSession_key(), iv);
response.getWriter().write("123");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("调用结束");
}
doGet 公共方法
public static String doGet(String url,String parameter)
{
String uriAPI =url+"?"+parameter ; //"http://XXXXX?str=I+am+get+String";
String result= "";
HttpClient client = createSSLClientDefault();
HttpGet httpRequst = new HttpGet(uriAPI);
try {
HttpResponse httpResponse = client.execute(httpRequst);//其中HttpGet是HttpUriRequst的子类
if(httpResponse.getStatusLine().getStatusCode() == 200)
{
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);//取出应答字符串
// 一般来说都要删除多余的字符
result.replaceAll("\r", "");//去掉返回结果中的"\r"字符,否则会在结果字符串后面显示一个小方格
}
else
httpRequst.abort();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result = e.getMessage().toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result = e.getMessage().toString();
}
return result;
}
解密方法
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;
public class AES {
// 算法名
public static final String KEY_NAME = "AES";
// 加解密算法/模式/填充方式
// ECB模式只用密钥即可对数据进行加密解密,CBC模式需要添加一个iv
public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
/**
* 微信 数据解密
* 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充
* 对称解密的目标密文:encrypted=Base64_Decode(encryptData)
* 对称解密秘钥:key = Base64_Decode(session_key),aeskey是16字节
* 对称解密算法初始向量:iv = Base64_Decode(iv),同样是16字节
*
* @param encrypted 目标密文
* @param session_key 会话ID
* @param iv 加密算法的初始向量
*/
public static String wxDecrypt(String encrypted, String session_key, String iv) {
String json = null;
byte[] encrypted64 = Base64.decodeBase64(encrypted);
byte[] key64 = Base64.decodeBase64(session_key);
byte[] iv64 = Base64.decodeBase64(iv);
byte[] data;
try {
init();
json = new String(decrypt(encrypted64, key64, generateIV(iv64)));
} catch (Exception e) {
e.printStackTrace();
}
return json;
}
/**
* 初始化密钥
*/
public static void init() throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyGenerator.getInstance(KEY_NAME).init(128);
}
/**
* 生成iv
*/
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
// iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0
// Arrays.fill(iv, (byte) 0x00);
AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME);
params.init(new IvParameterSpec(iv));
return params;
}
/**
* 生成解密
*/
public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv)
throws Exception {
Key key = new SecretKeySpec(keyBytes, KEY_NAME);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(encryptedData);
}
}