1.前端小程序传入后端接口的入参如下:
code :临时登录凭证(必传)
encryptedData:密文
iv:偏移量
2.接收到入参后的java后端接口中的代码如下:
1 @Action(value = "findWx")
2 public void findWx() throws IOException {
3 System.out.println("开始");
4 //小程序返回登录相关信息(自定义返回给小程序的信息)
5 RequestWxAppMsg msg = new RequestWxAppMsg();
6 msg.setCode(AppActionResultCode.CODE_FAILURE);
7 System.out.println("wxcode:" + code);
8 System.out.println("encryptedData:" + encryptedData);
9 System.out.println("iv:" + iv);
10 /*======================================================*/
11 //登录凭证不能为空
12 if (code == null || code.length() == 0) {
13 msg.setCode(AppActionResultCode.CODE_FAILURE);
14 System.out.println("登录凭证不能为空");
15 }
16 //小程序唯一标识 (在微信小程序管理后台获取)
17 String wxspAppid = "***************";
18 //小程序的 app secret (在微信小程序管理后台获取)
19 String wxspSecret = "***************";
20 //授权(必填)
21 String grant_type = code;
22 /*========1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid=========*/
23 //请求参数
24 String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type;
25 //发送请求
26 String sr = HttpRequest.sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
27 //解析相应内容(转换成json对象)
28 JSONObject json = JSONObject.fromObject(sr);
29 //获取会话密钥(session_key)
30 String session_key = json.get("session_key").toString();
31 //用户的唯一标识(openid)
32 String openid = (String) json.get("openid");
33 //返回的数据
34 msg.setOpenId(openid);
35 System.out.println("请求成功获取openId以及会话密钥(如果不需要unionId以及手机号此刻可以直接结束返回openId)");
36 /*=========2、对encryptedData加密数据进行AES解密(unionId)========================*/
37 try {
38 String result = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
39 System.out.println("解密结果:"+result);
40 if (null != result && result.length() > 0) {
41 JSONObject userInfoJSON = JSONObject.fromObject(result);
42 //返回的数据
43 msg.setUnionId((String) userInfoJSON.get("unionId"));
44 msg.setCode(AppActionResultCode.CODE_SUCCESS);
45 }
46 } catch (Exception e) {
47 e.printStackTrace();
48 }
49 /*=========2、对encryptedData加密数据进行AES解密(phone)========================*/
50 try {
51 String phone = AuthLoginUtil.getPhone(encryptedData,session_key,iv);
52 if(!phone.equals("")){
53 msg.setPhone(phone);
54 }
55 } catch (InvalidAlgorithmParameterException e) {
56 // TODO Auto-generated catch block
57 e.printStackTrace();
58 }
59 doOutput(msg);
60 }
View Code
3.发送请求的工具类HttpRequest代码如下:
1 import java.io.BufferedReader;
2 import java.io.IOException;
3 import java.io.InputStreamReader;
4 import java.io.PrintWriter;
5 import java.net.URL;
6 import java.net.URLConnection;
7 import java.util.List;
8 import java.util.Map;
9
10 public class HttpRequest{
11 public static void main(String[] args) {
12 //发送 GET 请求
13 String s=HttpRequest.sendGet("http://v.qq.com/x/cover/kvehb7okfxqstmc.html?vid=e01957zem6o", "");
14 System.out.println(s);
15 //发送 POST 请求
16 //String sr=HttpRequest.sendPost("http://www.toutiao.com/stream/widget/local_weather/data/?city=%E4%B8%8A%E6%B5%B7", "");
17 //JSONObject json = JSONObject.fromObject(sr);
18 //System.out.println(json.get("data"));
19 }
20 /**
21 * 向指定URL发送GET方法的请求
22 *
23 * @param url
24 * 发送请求的URL
25 * @param param
26 * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
27 * @return URL 所代表远程资源的响应结果
28 */
29 public static String sendGet(String url, String param) {
30 String result = "";
31 BufferedReader in = null;
32 try {
33 String urlNameString = url + "?" + param;
34 URL realUrl = new URL(urlNameString);
35 // 打开和URL之间的连接
36 URLConnection connection = realUrl.openConnection();
37 // 设置通用的请求属性
38 connection.setRequestProperty("accept", "*/*");
39 connection.setRequestProperty("connection", "Keep-Alive");
40 connection.setRequestProperty("user-agent",
41 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
42 // 建立实际的连接
43 connection.connect();
44 // 获取所有响应头字段
45 Map<String, List<String>> map = connection.getHeaderFields();
46 // 遍历所有的响应头字段
47 for (String key : map.keySet()) {
48 System.out.println(key + "--->" + map.get(key));
49 }
50 // 定义 BufferedReader输入流来读取URL的响应
51 in = new BufferedReader(new InputStreamReader(
52 connection.getInputStream()));
53 String line;
54 while ((line = in.readLine()) != null) {
55 result += line;
56 }
57 } catch (Exception e) {
58 System.out.println("发送GET请求出现异常!" + e);
59 e.printStackTrace();
60 }
61 // 使用finally块来关闭输入流
62 finally {
63 try {
64 if (in != null) {
65 in.close();
66 }
67 } catch (Exception e2) {
68 e2.printStackTrace();
69 }
70 }
71 return result;
72 }
73
74 /**
75 * 向指定 URL 发送POST方法的请求
76 *
77 * @param url
78 * 发送请求的 URL
79 * @param param
80 * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
81 * @return 所代表远程资源的响应结果
82 */
83 public static String sendPost(String url, String param) {
84 PrintWriter out = null;
85 BufferedReader in = null;
86 String result = "";
87 try {
88 URL realUrl = new URL(url);
89 // 打开和URL之间的连接
90 URLConnection conn = realUrl.openConnection();
91 // 设置通用的请求属性
92 conn.setRequestProperty("accept", "*/*");
93 conn.setRequestProperty("connection", "Keep-Alive");
94 conn.setRequestProperty("user-agent",
95 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
96 // 发送POST请求必须设置如下两行
97 conn.setDoOutput(true);
98 conn.setDoInput(true);
99 // 获取URLConnection对象对应的输出流
100 out = new PrintWriter(conn.getOutputStream());
101 // 发送请求参数
102 out.print(param);
103 // flush输出流的缓冲
104 out.flush();
105 // 定义BufferedReader输入流来读取URL的响应
106 in = new BufferedReader(
107 new InputStreamReader(conn.getInputStream()));
108 String line;
109 while ((line = in.readLine()) != null) {
110 result += line;
111 }
112 } catch (Exception e) {
113 System.out.println("发送 POST 请求出现异常!"+e);
114 e.printStackTrace();
115 }
116 //使用finally块来关闭输出流、输入流
117 finally{
118 try{
119 if(out!=null){
120 out.close();
121 }
122 if(in!=null){
123 in.close();
124 }
125 }
126 catch(IOException ex){
127 ex.printStackTrace();
128 }
129 }
130 return result;
131 }
132 }
View Code
4.解密unionId的工具类AesCbcUtil代码如下:
1 import org.apache.commons.codec.binary.Base64;
2 import org.bouncycastle.jce.provider.BouncyCastleProvider;
3 import javax.crypto.BadPaddingException;
4 import javax.crypto.Cipher;
5 import javax.crypto.IllegalBlockSizeException;
6 import javax.crypto.NoSuchPaddingException;
7 import javax.crypto.spec.IvParameterSpec;
8 import javax.crypto.spec.SecretKeySpec;
9 import java.io.UnsupportedEncodingException;
10 import java.security.*;
11 import java.security.spec.InvalidParameterSpecException;
12
13 public class AesCbcUtil {
14
15 static {
16 Security.addProvider(new BouncyCastleProvider());
17 }
18
19 /**
20 * AES解密
21 *
22 * @param data //密文,被加密的数据
23 * @param key //秘钥
24 * @param iv //偏移量
25 * @param encodingFormat //解密后的结果需要进行的编码
26 * @return
27 * @throws Exception
28 */
29 public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
30 //被加密的数据
31 byte[] dataByte = Base64.decodeBase64(data);
32 //加密秘钥
33 byte[] keyByte = Base64.decodeBase64(key);
34 //偏移量
35 byte[] ivByte = Base64.decodeBase64(iv);
36 try {
37 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
38
39 SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
40
41 AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
42 parameters.init(new IvParameterSpec(ivByte));
43
44 cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
45
46 byte[] resultByte = cipher.doFinal(dataByte);
47 if (null != resultByte && resultByte.length > 0) {
48 String result = new String(resultByte, encodingFormat);
49 return result;
50 }
51 return null;
52 } catch (NoSuchAlgorithmException e) {
53 e.printStackTrace();
54 } catch (NoSuchPaddingException e) {
55 e.printStackTrace();
56 } catch (InvalidParameterSpecException e) {
57 e.printStackTrace();
58 } catch (InvalidKeyException e) {
59 e.printStackTrace();
60 } catch (InvalidAlgorithmParameterException e) {
61 e.printStackTrace();
62 } catch (IllegalBlockSizeException e) {
63 e.printStackTrace();
64 } catch (BadPaddingException e) {
65 e.printStackTrace();
66 } catch (UnsupportedEncodingException e) {
67 e.printStackTrace();
68 }
69
70 return null;
71 }
72
73 }
View Code
5.解密手机号的工具类AuthLoginUtil代码如下:
1 import java.io.UnsupportedEncodingException;
2 import java.security.InvalidAlgorithmParameterException;
3 import org.apache.tomcat.util.codec.binary.Base64;
4 import com.alibaba.fastjson.JSON;
5 import com.alibaba.fastjson.JSONObject;
6
7 public class AuthLoginUtil {
8 //解密得到电话号码
9 public static String getPhone(String encryptedData,String sessionKey,String iv) throws InvalidAlgorithmParameterException, UnsupportedEncodingException{
10 String phone="";
11 byte[] resultByte = AES.decrypt(Base64.decodeBase64(encryptedData),
12 Base64.decodeBase64(sessionKey),
13 Base64.decodeBase64(iv));
14 if (null != resultByte && resultByte.length > 0) {
15 String userInfo = new String(resultByte, "UTF-8");
16 System.out.println(userInfo);
17 JSONObject userJson =JSON.parseObject(userInfo);
18 phone = userJson.getString("phoneNumber");
19 System.out.println("电话:"+phone);
20 //解密成功
21 System.out.println("解密成功");
22 } else {
23 System.out.println("解密报错");
24 }
25 return phone;
26 }
27 }
View Code
参考博客如下:
https://zhuanlan.zhihu.com/p/25124713
注:
解密手机号与unionId分别写在2个接口中(解密的入参不同)
unionId解不出来要去检查一下你的微信开放平台(微信开放平台)是否有绑定微信小程序