|
@@ -0,0 +1,208 @@
|
|
|
|
|
+package com.happy.common.util;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+// vo实体类参数
|
|
|
|
|
+
|
|
|
|
|
+import com.happy.Model.weixin.CodeEntityVo;
|
|
|
|
|
+import com.happy.Model.weixin.WeiXinUtil;
|
|
|
|
|
+import org.bouncycastle.util.encoders.Base64;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.apache.http.util.TextUtils;
|
|
|
|
|
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
|
+
|
|
|
|
|
+import javax.crypto.Cipher;
|
|
|
|
|
+import javax.crypto.spec.IvParameterSpec;
|
|
|
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
|
|
|
+import javax.imageio.ImageIO;
|
|
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
|
|
+import java.io.*;
|
|
|
|
|
+import java.net.HttpURLConnection;
|
|
|
|
|
+import java.net.URL;
|
|
|
|
|
+import java.net.URLConnection;
|
|
|
|
|
+import java.security.AlgorithmParameters;
|
|
|
|
|
+import java.security.Security;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+
|
|
|
|
|
+public class WechatUtil {
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取小程序code换取openid、session_key
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param code
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static JSONObject getOpenId(String code) {
|
|
|
|
|
+
|
|
|
|
|
+ String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + WeiXinUtil.appid_c
|
|
|
|
|
+ + "&secret=" + WeiXinUtil.screct_c + "&js_code=" + code + "&grant_type=authorization_code";
|
|
|
|
|
+ PrintWriter out = null;
|
|
|
|
|
+ BufferedReader in = null;
|
|
|
|
|
+ String line;
|
|
|
|
|
+ StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
|
+ try {
|
|
|
|
|
+ URL realUrl = new URL(url);
|
|
|
|
|
+ // 打开和URL之间的连接
|
|
|
|
|
+ URLConnection conn = realUrl.openConnection();
|
|
|
|
|
+
|
|
|
|
|
+ // 设置通用的请求属性 设置请求格式
|
|
|
|
|
+ //设置返回类型
|
|
|
|
|
+ conn.setRequestProperty("contentType", "text/plain");
|
|
|
|
|
+ //设置请求类型
|
|
|
|
|
+ conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
|
|
|
|
|
+ //设置超时时间
|
|
|
|
|
+ conn.setConnectTimeout(1000);
|
|
|
|
|
+ conn.setReadTimeout(1000);
|
|
|
|
|
+ conn.setDoOutput(true);
|
|
|
|
|
+ conn.connect();
|
|
|
|
|
+ // 获取URLConnection对象对应的输出流
|
|
|
|
|
+ out = new PrintWriter(conn.getOutputStream());
|
|
|
|
|
+ // flush输出流的缓冲
|
|
|
|
|
+ out.flush();
|
|
|
|
|
+ // 定义BufferedReader输入流来读取URL的响应 设置接收格式
|
|
|
|
|
+ in = new BufferedReader(
|
|
|
|
|
+ new InputStreamReader(conn.getInputStream(), "UTF-8"));
|
|
|
|
|
+ while ((line = in.readLine()) != null) {
|
|
|
|
|
+ stringBuffer.append(line);
|
|
|
|
|
+ }
|
|
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(stringBuffer.toString());
|
|
|
|
|
+ return jsonObject;
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ //使用finally块来关闭输出流、输入流
|
|
|
|
|
+ finally {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (out != null) {
|
|
|
|
|
+ out.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (in != null) {
|
|
|
|
|
+ in.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (IOException ex) {
|
|
|
|
|
+ ex.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取公众号code换取openid、access_token
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param code
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static JSONObject getGOpenId(String code) {
|
|
|
|
|
+
|
|
|
|
|
+ String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
|
|
|
|
|
+ + WeiXinUtil.appid_g
|
|
|
|
|
+ + "&secret="
|
|
|
|
|
+ + WeiXinUtil.screct_g
|
|
|
|
|
+ + "&code="
|
|
|
|
|
+ + code + "&grant_type=authorization_code";
|
|
|
|
|
+ PrintWriter out = null;
|
|
|
|
|
+ BufferedReader in = null;
|
|
|
|
|
+ String line;
|
|
|
|
|
+ StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
|
+ try {
|
|
|
|
|
+ URL realUrl = new URL(url);
|
|
|
|
|
+ // 打开和URL之间的连接
|
|
|
|
|
+ URLConnection conn = realUrl.openConnection();
|
|
|
|
|
+
|
|
|
|
|
+ // 设置通用的请求属性 设置请求格式
|
|
|
|
|
+ //设置返回类型
|
|
|
|
|
+ conn.setRequestProperty("contentType", "text/plain");
|
|
|
|
|
+ //设置请求类型
|
|
|
|
|
+ conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
|
|
|
|
|
+ //设置超时时间
|
|
|
|
|
+ conn.setConnectTimeout(1000);
|
|
|
|
|
+ conn.setReadTimeout(1000);
|
|
|
|
|
+ conn.setDoOutput(true);
|
|
|
|
|
+ conn.connect();
|
|
|
|
|
+ // 获取URLConnection对象对应的输出流
|
|
|
|
|
+ out = new PrintWriter(conn.getOutputStream());
|
|
|
|
|
+ // flush输出流的缓冲
|
|
|
|
|
+ out.flush();
|
|
|
|
|
+ // 定义BufferedReader输入流来读取URL的响应 设置接收格式
|
|
|
|
|
+ in = new BufferedReader(
|
|
|
|
|
+ new InputStreamReader(conn.getInputStream(), "UTF-8"));
|
|
|
|
|
+ while ((line = in.readLine()) != null) {
|
|
|
|
|
+ stringBuffer.append(line);
|
|
|
|
|
+ }
|
|
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(stringBuffer.toString());
|
|
|
|
|
+ return jsonObject;
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ //使用finally块来关闭输出流、输入流
|
|
|
|
|
+ finally {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (out != null) {
|
|
|
|
|
+ out.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (in != null) {
|
|
|
|
|
+ in.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (IOException ex) {
|
|
|
|
|
+ ex.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 在上面的代码中我们已经获取到了openid和session_key了,而code信息中是不能获取到用户的手机号码的,
|
|
|
|
|
+ * 解析微信手机号的相关数据需要openid和session_key才行,所以在上面代码中,我将相关数据返回给了前端,
|
|
|
|
|
+ * 前端将我传回的参数,还有第二次请求中的iv、encryptedData一起传回给后端,然后我们进行解密
|
|
|
|
|
+ * **/
|
|
|
|
|
+ public static Map<String, Object> getPhoneNumber(CodeEntityVo vo,String openid,String session_key) {
|
|
|
|
|
+ Map<String,Object> map=new HashMap<>();
|
|
|
|
|
+ if (openid!=null) {
|
|
|
|
|
+ if(session_key==null){
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ map.put("openid",openid);
|
|
|
|
|
+ // 被加密的数据
|
|
|
|
|
+ byte[] dataByte = Base64.decode(vo.getEncryptedData());
|
|
|
|
|
+ // 加密秘钥
|
|
|
|
|
+ byte[] keyByte = Base64.decode(session_key);
|
|
|
|
|
+ // 偏移量
|
|
|
|
|
+ byte[] ivByte = Base64.decode(vo.getIv());
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
|
|
|
|
|
+ int base = 16;
|
|
|
|
|
+ String result = null;
|
|
|
|
|
+ if (keyByte.length % base != 0) {
|
|
|
|
|
+ int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
|
|
|
|
|
+ byte[] temp = new byte[groups * base];
|
|
|
|
|
+ Arrays.fill(temp, (byte) 0);
|
|
|
|
|
+ System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
|
|
|
|
|
+ keyByte = temp;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 初始化
|
|
|
|
|
+ Security.addProvider(new BouncyCastleProvider());
|
|
|
|
|
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
|
|
|
|
|
+ SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
|
|
|
|
|
+ AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
|
|
|
|
|
+ parameters.init(new IvParameterSpec(ivByte));
|
|
|
|
|
+ // 初始化
|
|
|
|
|
+ cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
|
|
|
|
|
+ byte[] resultByte = cipher.doFinal(dataByte);
|
|
|
|
|
+ if (null != resultByte && resultByte.length > 0) {
|
|
|
|
|
+ result = new String(resultByte, "UTF-8");
|
|
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(result);
|
|
|
|
|
+ map.put("param",jsonObject);
|
|
|
|
|
+ return map;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|