官方api:https://developers.weixin.qq.com/miniprogram/dev/api/api-login.html#wxloginobject 参考文章:https://zhuanlan.zhihu.com/p/25124713 微信小程序API文档:开放接口 · 小程序 在实际的小程序开发中,往往需要用户授权登陆并获取用户的数据,快速对接用户系统。 openId : 用户在当前小程序的唯一标识 unionId : 如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionId是相同的。详情登录微信开放平台(http://open.weixin.qq.com) 。 在微信小程序开发中,unionId等敏感数据则被加密在encryptedData,于是需要以下流程来解密敏感数据,从而获取unionId等信息。 流程 1、(客户端)微信小程序客户端调用 wx.login()接口获取登录凭证(code) //1、调用微信登录接口,获取code wx.login({ success: function (r) { var code = r.code;//登录凭证 if (code) { //2、调用获取用户信息接口 //... } else { console.log('获取用户登录态失败!' + r.errMsg) } }, fail: function () { callback(false) } }) 2、(客户端)微信小程序客户端调用 wx.getUserInfo()接口获取 用户基本信息、encryptedData(用户敏感信息加密数据) 和 iv(加密算法的初始向量 ) //1、调用微信登录接口,获取code wx.login({ success: function (r) { var code = r.code;//登录凭证 if (code) { //2、调用获取用户信息接口 wx.getUserInfo({ success: function (res) { console.log({encryptedData: res.encryptedData, iv: res.iv, code: code}) //3.解密用户信息 获取unionId //... }, fail: function () { console.log('获取用户信息失败') } }) } else { console.log('获取用户登录态失败!' + r.errMsg) } }, fail: function () { callback(false) } }) 3、(客户端)将前面获取到的 code 、encryptedData、iv发送到自己的服务器(开发者服务器),通过自己的服务器(开发者服务器)解密获取信息 //1、调用微信登录接口,获取code wx.login({ success: function (r) { var code = r.code;//登录凭证 if (code) { //2、调用获取用户信息接口 wx.getUserInfo({ success: function (res) { console.log({encryptedData: res.encryptedData, iv: res.iv, code: code}) //3.请求自己的服务器,解密用户信息 获取unionId等加密信息 wx.request({ url: 'https://xxxx.com/wxsp/decodeUserInfo',//自己的服务接口地址 method: 'post', header: { 'content-type': 'application/x-www-form-urlencoded' }, data: {encryptedData: res.encryptedData, iv: res.iv, code: code}, success: function (data) { //4.解密成功后 获取自己服务器返回的结果 if (data.data.status == 1) { var userInfo_ = data.data.userInfo; console.log(userInfo_) } else { console.log('解密失败') } }, fail: function () { console.log('系统错误') } }) }, fail: function () { console.log('获取用户信息失败') } }) } else { console.log('获取用户登录态失败!' + r.errMsg) } }, fail: function () { console.log('登陆失败') } }) 4、(服务端 java)自己的服务器发送code到微信服务器获取openid(用户唯一标识)和session_key(会话密钥),最后将encryptedData、iv、session_key通过AES解密获取到用户敏感数据 a、获取秘钥并处理解密的controller(这里用的是springMVC) /** * 解密用户敏感数据 * * @param encryptedData 明文,加密数据 * @param iv 加密算法的初始向量 * @param code 用户允许登录后,回调内容会带上 code(有效期五分钟),开发者需要将 code 发送到开发者服务器后台,使用code 换取 session_key api,将 code 换成 openid 和 session_key * @return */ @ResponseBody @RequestMapping(value = "/decodeUserInfo", method = RequestMethod.POST) public Map decodeUserInfo(String encryptedData, String iv, String code) { Map map = new HashMap(); //登录凭证不能为空 if (code == null || code.length() == 0) { map.put("status", 0); map.put("msg", "code 不能为空"); return map; } //小程序唯一标识 (在微信小程序管理后台获取) String wxspAppid = "xxxxxxxxxxxxxx"; //小程序的 app secret (在微信小程序管理后台获取) String wxspSecret = "xxxxxxxxxxxxxx"; //授权(必填) String grant_type = "authorization_code"; //////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid //////////////// //请求参数 String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type; //发送请求 String sr = HttpRequest.sendGet("https://api.weixin.qq.com/sns/jscode2session", params); //解析相应内容(转换成json对象) JSONObject json = JSONObject.fromObject(sr); //获取会话密钥(session_key) String session_key = json.get("session_key").toString(); //用户的唯一标识(openid) String openid = (String) json.get("openid"); //////////////// 2、对encryptedData加密数据进行AES解密其中包含这openid和unionid //////////////// try { String result = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8"); if (null != result && result.length() > 0) { map.put("status", 1); map.put("msg", "解密成功"); JSONObject userInfoJSON = JSONObject.fromObject(result); Map userInfo = new HashMap(); userInfo.put("openId", userInfoJSON.get("openId")); userInfo.put("nickName", userInfoJSON.get("nickName")); userInfo.put("gender", userInfoJSON.get("gender")); userInfo.put("city", userInfoJSON.get("city")); userInfo.put("province", userInfoJSON.get("province")); userInfo.put("country", userInfoJSON.get("country")); userInfo.put("avatarUrl", userInfoJSON.get("avatarUrl")); userInfo.put("unionId", userInfoJSON.get("unionId")); map.put("userInfo", userInfo); return map; } } catch (Exception e) { e.printStackTrace(); } map.put("status", 0); map.put("msg", "解密失败"); return map; }