微信小程序:java后台获取openId

一、功能描述

openId是某个微信账户对应某个小程序或者公众号的唯一标识,但openId必须经过后台解密才能获取(之前实现过前台解密,可是由于微信小程序的种种限制,前台解密无法在小程序发布后使用)

二、实现流程

1. 获取微信用户的登录信息;

2. 将encryptedData中的数据作为参数传给java后台

3. java后台进行解密

三、代码实现

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           //2、调用获取用户信息接口
 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工具类

  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 }

原文地址:https://www.cnblogs.com/huiAlex/p/9463181.html

时间: 2024-10-06 21:00:25

微信小程序:java后台获取openId的相关文章

微信小程序结合后台数据管理实现商品数据的动态展示、维护

微信小程序给我们提供了一个很好的开发平台,可以用于展现各种数据和实现丰富的功能,本篇随笔介绍微信小程序结合后台数据管理实现商品数据的动态展示.维护,介绍如何实现商品数据在后台管理系统中的维护管理,并通过小程序的请求Web API 平台获取JSON数据在小程序界面上进行动态展示. 1.整体性的架构设计 我们整体性的架构设计,包含一个Web管理后台.一个Web API统一接口层.当然还有数据库什么,另外还有一个小程序客户端.整个架构体系还是以我之前随笔介绍的<整合微信小程序的Web API接口层的架

微信小程序开发如何获取定位信息

当我们在使用微信小程序时,会弹出一个获取你的定位信息.那么这个功能是怎样实现的,下面木鱼小铺(https://www.muyu007.cn)就和大家科普一下微信小程序开发如何获取定位信息? 我们一般通过调用wx.getLocation()获取当前的地理位置,为了能够获得准确的定位信息,我们还需要借助第三方地图服务API来实现.比如腾讯地图或百度地图. 下面我们就以借助腾讯地图为例,看看如何获取定位信息. 第一步:你需要去腾讯地图平台上注册一个账号,在管理后台中创建密钥. 第二步:登录进入有一个界

微信小程序wx.getLocation()获取经纬度及JavaScript SDK调用腾讯地图API获取某一类地址

简介 腾讯位置服务为微信小程序提供了基础的标点能力.线和圆的绘制接口等地图组件和位置展示.地图选点等地图API位置服务能力支持,使得开发者可以自由地实现自己的微信小程序产品. 在此基础上,腾讯位置服务微信小程序JavaScript SDK是专为小程序开发者提供的LBS数据服务工具包,可以在小程序中调用腾讯位置服务的POI检索.关键词输入提示.地址解析.逆地址解析.行政区划和距离计算等数据服务,让您的小程序更强大! 有时候我们在做微信小程序时有些功能需要获取当前的地理位置及附近地点的一些要求,但是

微信小程序传值以及获取值方法

微信小程序传值以及获取值方法,传值有两种方法,对应也有获取值得方法, 1.设置id的方法标识跳转后传递的参数值: 2.通过使用data - xxxx 的方法来标识要传递的值 微信小程序设置id的方法标识来传值 在要跳转的item处,设置一个id并给当前的id赋值上对应的key值,比如一部电影的id(后面带着id去下一个页面查询,详细信息)如: 后我们在js的bindtap的响应事件中获取,并传递到下一个界面中: 获取到id传的值 通过e.currentTarget.id;获取设置的id值,并通过

微信小程序之动态获取元素宽高

我以前一直以为微信小程序不能动态获取view元素的宽高.但是自从看到: wx.createSelectorQuery() 这个api接口,以前的某些问题就能得到解决了... 那么,这个api接口怎么用呢? 首先,这个接口会返回一个对象实例. var obj=wx.createSelectorQuery(); 下面的就是返回的对象实例 obj 的所有内容. 返回的 obj 有五个方法: 1.  obj.in(component):没用过这个方法,多用于组件的选择器. 2.   obj.select

[技术博客] 微信小程序的formid获取

微信小程序的formid获取 formId的触发 微信小程序可以通过收集用户的formid,获取formid给用户主动推送微信消息.获取formid有两个途径,一个是触发一次表单提交,或者触发一次支付行为.如果要给用户主动推送模板消息,就需要拿到足够多的formid. 用表单的方法一定需要绑定bindsubmit,button的form-type设置为submit,在js代码中可以通过e.detail.formId 获取formId. 实例: <form bindsubmit="submi

原创:微信小程序java实现AES解密并获取unionId

来自:微信小程序联盟 如果大家使用小程序的同时还在使用公众号的话,可能会用到unionId这种功能,由于公司业务需要,我们需要使用unionId,具体使用方法,请参考微信开放平台的说明,但是在微信小程序的文档中只给出了部分语言实现的源码,竟然没有java的,小程序的开发人员是有多么懒.难道大家都不用java写后台??? 什么鬼,然后开始了各种AES踩坑之路,其实参考了很多的网上的教程,再次不能一一列出来给大家了,(因为我写这篇文章的时候,已经是解决问题一周以后了),也收到管理员的很多帮助,再次写

微信小程序管理后台介绍

微信小程序的管理后台,每次进入都需要扫码,还是特别不爽,现在微信小程序还没正式发布,很多人都还没看到管理后台,这里抢先发布出来 ------------------------------------------------------------ http://www.cnblogs.com/likwo/p/6057258.html 好推小程序统计:https://weixin.hotapp.cn关键指标分析推广效果,一行代码接入微信登录 ---------------------------

[小程序]微信小程序登陆并获取用户信息

1.小程序js端调用框架登陆API,获取到一个临时code,拿着这个code去调用自己的服务端接口 2.在自己的服务器端,使用app_id app_secrect code可以获取到用户的openid,这个id是用户唯一的id并且不会改变,可以把这个id返回给小程序端小程序端本地保存openid 3.获取用户信息很简单,并且不需要自己的服务器处理,只需要小程序端提供的API.前端页面wxml使用一个按钮,按钮里增加几个属性,就可以回调到小程序js部分的方法上,并且带着用户的个人信息,如昵称 头像