微信小程序获取用户的unionId以及手机号
- 后端接口入参:
- code :临时登录凭证(必传)
- encryptedData:密文
- iv:偏移量
- 控制层接口:
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 }
- 发送请求的工具类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 }
- 解密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 }
- 解密手机号的工具类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 }
- 参考博客:
- 注:解密手机号与unionId分别写在2个接口中(解密的入参不同),unionId解不出来要去检查一下你的微信开放平台(微信开放平台)是否有绑定微信小程序。