微信小程序:java後臺獲取openId

1、功能描述

openId是某個微信帳戶對應某個小程序或者公衆號的惟一標識,但openId必須通過後臺解密才能獲取(以前實現過前臺解密,但是因爲微信小程序的種種限制,前臺解密沒法在小程序發佈後使用)html

 

2、實現流程

1. 獲取微信用戶的登陸信息;java

2. 將encryptedData中的數據做爲參數傳給java後臺apache

3. java後臺進行解密json

 

 

3、代碼實現

1. 後臺的解密代碼小程序

 1 /**
 2      * decoding encrypted data to get openid
 3      *
 4      * @param iv
 5      * @param encryptedData
 6      * @param code
 7      * @return
 8      */
 9     @RequestMapping(value = "/decodeUserInfo", method = RequestMethod.GET)
10     private Map decodeUserInfo(String iv, String encryptedData, String code) {
11         Map map = new HashMap();
12         // login code can not be null
13         if (code == null || code.length() == 0) {
14             map.put("status", 0);
15             map.put("msg", "code 不能爲空");
16             return map;
17         }
18         // mini-Program's AppID
19         String wechatAppId = "你的小程序的AppID";
20 
21         // mini-Program's session-key
22         String wechatSecretKey = "你的小程序的session-key";
23 
24         String grantType = "authorization_code";
25 
26         // using login code to get sessionId and openId
27         String params = "appid=" + wechatAppId + "&secret=" + wechatSecretKey + "&js_code=" + code + "&grant_type=" + grantType;
28 
29         // sending request
30         String sr = HttpRequest.sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
31 
32         // analysis request content
33         JSONObject json = JSONObject.fromObject(sr);
34 
35         // getting session_key
36         String sessionKey = json.get("session_key").toString();
37 
38         // getting open_id
39         String openId = json.get("openid").toString();
40 
41         // decoding encrypted info with AES
42         try {
43             String result = AesCbcUtil.decrypt(encryptedData, sessionKey, iv, "UTF-8");
44             if (null != result && result.length() > 0) {
45                 map.put("status", 1);
46                 map.put("msg", "解密成功");
47 
48                 JSONObject userInfoJSON = JSONObject.fromObject(result);
49                 Map userInfo = new HashMap();
50                 userInfo.put("openId", userInfoJSON.get("openId"));
51                 userInfo.put("nickName", userInfoJSON.get("nickName"));
52                 userInfo.put("gender", userInfoJSON.get("gender"));
53                 userInfo.put("city", userInfoJSON.get("city"));
54                 userInfo.put("province", userInfoJSON.get("province"));
55                 userInfo.put("country", userInfoJSON.get("country"));
56                 userInfo.put("avatarUrl", userInfoJSON.get("avatarUrl"));
57                 userInfo.put("unionId", userInfoJSON.get("unionId"));
58                 map.put("userInfo", userInfo);
59                 return map;
60             }
61 
62 
63         } catch (Exception e) {
64             e.printStackTrace();
65         }
66         map.put("status", 0);
67         map.put("msg", "解密失敗");
68         return map;
69     }

 

2. 前臺代碼微信小程序

 1 wx.login({
 2       success: function (res) {
 3         that.globalData.code = res.code;//登陸憑證
 4         if (that.globalData.code) {
 5           //二、調用獲取用戶信息接口
 6           // 查看是否受權
 7           wx.getUserInfo({
 8             success: function (res) {
 9               that.globalData.encryptedData = res.encryptedData
10               that.globalData.iv = res.iv
11               console.log('[INFO] app.js/ ',{ encryptedData: res.encryptedData, iv: res.iv, code: that.globalData.code })
12               //3.請求本身的服務器,解密用戶信息 獲取unionId等加密信息
13               wx.request({
14                 url: 'https://www.****.cn/***/****/decodeUserInfo',//本身的服務接口地址
15                 method: 'get',
16                 header: {
17                   "Content-Type": "applciation/json"
18                 },
19                 data: { encryptedData: res.encryptedData, iv: res.iv, code: that.globalData.code },
20                 success: function (data) {
21 
22                   //4.解密成功後 獲取本身服務器返回的結果
23                   if (data.data.status == 1) {
24                     var userInfos = data.data.userInfo;
25                     that.globalData.openId = userInfos.openId;
26                     console.log('[INFO] app.js/ userInfo:',userInfos)
27                   } else {
28                     console.log('[INFO] app.js/ 解密失敗')
29                   }
30                 },
31                 fail: function () {
32                   console.log('[INFO] app.js/ 系統錯誤')
33                 }
34               })
35             },
36             fail: function () {
37               console.log('[INFO] app.js/ 獲取用戶信息失敗')
38             }
39           })
40         } else {
41           console.log('[INFO] app.js/ 獲取用戶登陸態失敗!' + r.errMsg)
42         }
43       },
44       fail: function () {
45         console.log('[INFO] app.js/ 登錄失敗')
46       }
47     })
48 
49     // 獲取用戶信息
50     wx.getSetting({
51       success: res => {
52         if (res.authSetting['scope.userInfo']) {
53           // 已經受權,能夠直接調用 getUserInfo 獲取頭像暱稱,不會彈框
54           wx.getUserInfo({
55             success: res => {
56               // 能夠將 res 發送給後臺解碼出 unionId
57               this.globalData.userInfo = res.userInfo;
58 
59               // 因爲 getUserInfo 是網絡請求,可能會在 Page.onLoad 以後才返回
60               // 因此此處加入 callback 以防止這種狀況
61               if (this.userInfoReadyCallback) {
62                 this.userInfoReadyCallback(res)
63               }
64             }
65           })
66         }
67       }
68     })
69   },

 

2. HttpRequest工具類api

  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 
 12     public static void main(String[] args) {
 13         //發送 GET 請求
 14         String s=HttpRequest.sendGet("http://v.qq.com/x/cover/kvehb7okfxqstmc.html?vid=e01957zem6o", "");
 15         System.out.println(s);
 16 
 17 //        //發送 POST 請求
 18 //        String sr=HttpRequest.sendPost("http://www.toutiao.com/stream/widget/local_weather/data/?city=%E4%B8%8A%E6%B5%B7", "");
 19 //        JSONObject json = JSONObject.fromObject(sr);
 20 //        System.out.println(json.get("data"));
 21     }
 22 
 23     /**
 24      * 向指定URL發送GET方法的請求
 25      *
 26      * @param url
 27      *            發送請求的URL
 28      * @param param
 29      *            請求參數,請求參數應該是 name1=value1&name2=value2 的形式。
 30      * @return URL 所表明遠程資源的響應結果
 31      */
 32     public static String sendGet(String url, String param) {
 33         String result = "";
 34         BufferedReader in = null;
 35         try {
 36             String urlNameString = url + "?" + param;
 37             URL realUrl = new URL(urlNameString);
 38             // 打開和URL之間的鏈接
 39             URLConnection connection = realUrl.openConnection();
 40             // 設置通用的請求屬性
 41             connection.setRequestProperty("accept", "*/*");
 42             connection.setRequestProperty("connection", "Keep-Alive");
 43             connection.setRequestProperty("user-agent",
 44                     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
 45             // 創建實際的鏈接
 46             connection.connect();
 47             // 獲取全部響應頭字段
 48             Map<String, List<String>> map = connection.getHeaderFields();
 49             // 遍歷全部的響應頭字段
 50             for (String key : map.keySet()) {
 51                 System.out.println(key + "--->" + map.get(key));
 52             }
 53             // 定義 BufferedReader輸入流來讀取URL的響應
 54             in = new BufferedReader(new InputStreamReader(
 55                     connection.getInputStream()));
 56             String line;
 57             while ((line = in.readLine()) != null) {
 58                 result += line;
 59             }
 60         } catch (Exception e) {
 61             System.out.println("發送GET請求出現異常!" + e);
 62             e.printStackTrace();
 63         }
 64         // 使用finally塊來關閉輸入流
 65         finally {
 66             try {
 67                 if (in != null) {
 68                     in.close();
 69                 }
 70             } catch (Exception e2) {
 71                 e2.printStackTrace();
 72             }
 73         }
 74         return result;
 75     }
 76 
 77     /**
 78      * 向指定 URL 發送POST方法的請求
 79      *
 80      * @param url
 81      *            發送請求的 URL
 82      * @param param
 83      *            請求參數,請求參數應該是 name1=value1&name2=value2 的形式。
 84      * @return 所表明遠程資源的響應結果
 85      */
 86     public static String sendPost(String url, String param) {
 87         PrintWriter out = null;
 88         BufferedReader in = null;
 89         String result = "";
 90         try {
 91             URL realUrl = new URL(url);
 92             // 打開和URL之間的鏈接
 93             URLConnection conn = realUrl.openConnection();
 94             // 設置通用的請求屬性
 95             conn.setRequestProperty("accept", "*/*");
 96             conn.setRequestProperty("connection", "Keep-Alive");
 97             conn.setRequestProperty("user-agent",
 98                     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
 99             // 發送POST請求必須設置以下兩行
100             conn.setDoOutput(true);
101             conn.setDoInput(true);
102             // 獲取URLConnection對象對應的輸出流
103             out = new PrintWriter(conn.getOutputStream());
104             // 發送請求參數
105             out.print(param);
106             // flush輸出流的緩衝
107             out.flush();
108             // 定義BufferedReader輸入流來讀取URL的響應
109             in = new BufferedReader(
110                     new InputStreamReader(conn.getInputStream()));
111             String line;
112             while ((line = in.readLine()) != null) {
113                 result += line;
114             }
115         } catch (Exception e) {
116             System.out.println("發送 POST 請求出現異常!"+e);
117             e.printStackTrace();
118         }
119         //使用finally塊來關閉輸出流、輸入流
120         finally{
121             try{
122                 if(out!=null){
123                     out.close();
124                 }
125                 if(in!=null){
126                     in.close();
127                 }
128             }
129             catch(IOException ex){
130                 ex.printStackTrace();
131             }
132         }
133         return result;
134     }
135 }

 

3. AesCbuUtil工具類服務器

 1 import org.apache.commons.codec.binary.Base64;
 2 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 3 
 4 import javax.crypto.BadPaddingException;
 5 import javax.crypto.Cipher;
 6 import javax.crypto.IllegalBlockSizeException;
 7 import javax.crypto.NoSuchPaddingException;
 8 import javax.crypto.spec.IvParameterSpec;
 9 import javax.crypto.spec.SecretKeySpec;
10 import java.io.UnsupportedEncodingException;
11 import java.security.*;
12 import java.security.spec.InvalidParameterSpecException;
13 
14 public class AesCbcUtil {
15 
16     static {
17         //BouncyCastle是一個開源的加解密解決方案,主頁在http://www.bouncycastle.org/
18         Security.addProvider(new BouncyCastleProvider());
19     }
20 
21     /**
22      * AES解密
23      *
24      * @param data           //密文,被加密的數據
25      * @param key            //祕鑰
26      * @param iv             //偏移量
27      * @param encodingFormat //解密後的結果須要進行的編碼
28      * @return
29      * @throws Exception
30      */
31     public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
32 //        initialize();
33 
34         //被加密的數據
35         byte[] dataByte = Base64.decodeBase64(data.getBytes());
36         //加密祕鑰
37         byte[] keyByte = Base64.decodeBase64(key.getBytes());
38         //偏移量
39         byte[] ivByte = Base64.decodeBase64(iv.getBytes());
40 
41 
42         try {
43             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
44 
45             SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
46 
47             AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
48             parameters.init(new IvParameterSpec(ivByte));
49 
50             cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
51 
52             byte[] resultByte = cipher.doFinal(dataByte);
53             if (null != resultByte && resultByte.length > 0) {
54                 String result = new String(resultByte, encodingFormat);
55                 return result;
56             }
57             return null;
58         } catch (NoSuchAlgorithmException e) {
59             e.printStackTrace();
60         } catch (NoSuchPaddingException e) {
61             e.printStackTrace();
62         } catch (InvalidParameterSpecException e) {
63             e.printStackTrace();
64         } catch (InvalidKeyException e) {
65             e.printStackTrace();
66         } catch (InvalidAlgorithmParameterException e) {
67             e.printStackTrace();
68         } catch (IllegalBlockSizeException e) {
69             e.printStackTrace();
70         } catch (BadPaddingException e) {
71             e.printStackTrace();
72         } catch (UnsupportedEncodingException e) {
73             e.printStackTrace();
74         }
75 
76         return null;
77     }
78 
79 }
相關文章
相關標籤/搜索