本文主要总结微信小程序通过后台请求访问微信用户信息
创建一个微信小程序工程(自行百度)
微信小程序index.js代码
//index.js//获取应用实例const app = getApp() Page({ data: { motto: 'Hello World', userInfo: {}, backUserInfo:{},//后台得到的微信用户信息 hasUserInfo: false, canIUse: wx.canIUse('button.open-type.getUserInfo') }, //事件处理函数 bindViewTap: function() { wx.navigateTo({ url: '../logs/logs' }) }, onLoad: function () { //1.静默操作获取用户信息 调用wx.login var that = this; wx.login({ success:function(res){ var code = res.code;//2.登录凭证code console.log('code==='+code); if(null!=code){ wx.getUserInfo({ success:function(ress){ console.log('res===' + res); //3.请求自己的服务器,解密用户信息 wx.request({ url: 'http://xxxx.com/wcsp/oauth', method:'post', header:{ 'content-type': 'application/x-www-form-urlencoded' }, data: { encryptedData: ress.encryptedData, iv: ress.iv, code: code}, success:function(res){ console.log('resjava===' + res.data.openId); that.setData({ backUserInfo:res//将后台返回的数据赋值给backUserInfo }) } }) } }) } } }) if (app.globalData.userInfo) { this.setData({ userInfo: app.globalData.userInfo, hasUserInfo: true }) } else if (this.data.canIUse){ // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 app.userInfoReadyCallback = res => { this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } } else { // 在没有 open-type=getUserInfo 版本的兼容处理 wx.getUserInfo({ success: res => { app.globalData.userInfo = res.userInfo this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) } }, getUserInfo: function(e) { console.log(e) app.globalData.userInfo = e.detail.userInfo this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) } })
Java后台处理代码:
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import cn.xsshome.mvcdo.util.AesCbcUtil;import cn.xsshome.mvcdo.util.PrintUtil;import cn.xsshome.mvcdo.util.WeChatConstant;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;/** * 微信小程序code换取微信用户信息 * @author 小帅丶 * */@Controller@RequestMapping(value="wcsp")public class WeChatSPController { private static Logger logger = LoggerFactory.getLogger(WeChatSPController.class); /** * 获取微信小程序用户openid等信息 * @param encryptedData 加密数据 * @param iv 加密算法初始向量 * @param code 微信小程序code码 * @param request HttpServletRequest * @param response HttpServletResponse * @return String * @throws Exception */ @RequestMapping(value="/oauth") public String wxOauth(String encryptedData,String iv,String code,HttpServletRequest request,HttpServletResponse response) throws Exception{ try { logger.info("请求的参数有:\n加密数据="+encryptedData+"\n加密算法初始向量="+iv+"\n微信小程序code="+code); //1.拼接code等参数换取私钥值 String param = "appid="+WeChatConstant.WCSP_APPID+"&secret="+WeChatConstant.WCSP_APPSECRET+"&grant_type="+WeChatConstant.GRANT_TYPE+"&js_code="+code; String result = cn.xsshome.mvcdo.util.HttpUtil.post(WeChatConstant.JSCODE2SESSION_URL, param); logger.info("=======接口返回的数据里面包含私钥值和openid:"+result); JSONObject jsonObject = JSON.parseObject(result); String session_key = jsonObject.get("session_key").toString(); logger.info("session_key私钥值===="+session_key); //2.使用私钥值 和 算法向量值 加密的数据进行解密 String userInfo = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8"); logger.info("解密后返回页面的数据==="+userInfo); PrintUtil.printJson(response, userInfo); } catch (Exception e) { logger.error("oauth===出错了"+e.getMessage()); return null; } return null; } }
返回session_key和openId
{ "session_key": "9EAwD4AYbo4sScCjEviHag==", "expires_in": 7200, "openid": "op5Hs0EYFmR7XvvWNrbsMFVn22Ks"}
通过session_key解密后的数据(微信用户信息)
{ "openId": "op5Hs0EYFmR7XvvWNrbsMFVn22Ks", "nickName": "小帅丶", "gender": 1, "language": "zh_CN", "city": "Haidian", "province": "Beijing", "country": "China", "avatarUrl": "https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLib098UOLAHuE1fDldajSPuwR0RcPf3rxCtVicwhvdKibYFE0JNibwMwGdiagRzibdAtkSTU1fYxiaz8CIQ/0", "watermark": { "timestamp": 1524633793, "appid": "wxe11111111111" } }
AES解密工具类(需要BC包支持文末给出)
package cn.xsshome.mvcdo.util;import org.apache.commons.codec.binary.Base64;import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import java.io.UnsupportedEncodingException;import java.security.*;import java.security.spec.InvalidParameterSpecException;/** * AES-128-CBC 加密方式 * 注: * AES-128-CBC可以自己定义“密钥”和“偏移量“。 * AES-128是jdk自动生成的“密钥”。 */public class AesCbcUtil { static { //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/ Security.addProvider(new BouncyCastleProvider()); } /** * AES解密 * @param data //密文,被加密的数据 * @param key //秘钥 * @param iv //偏移量 * @param encodingFormat //解密后的结果需要进行的编码 * @return * @throws Exception */ public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception { //被加密的数据 byte[] dataByte = Base64.decodeBase64(data); //加密秘钥 byte[] keyByte = Base64.decodeBase64(key); //偏移量 byte[] ivByte = Base64.decodeBase64(iv); try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); 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) { String result = new String(resultByte, encodingFormat); return result; } return null; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidParameterSpecException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } }
微信小程序index.wxml内容
<!--index.wxml--><view class="container"> <view class="userinfo"> <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button> <block wx:else> <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image> </block> </view> <view class="infos"> 用户昵称:<text class="userinfo-nickname">{{backUserInfo.data.nickName}}</text> </view> <view class="infos"> 用户性别:<text class="userinfo-nickname" wx:if="{{backUserInfo.data.gender}}==1">男</text> <text class="userinfo-nickname" wx:elif="{{backUserInfo.data.gender}}==0">女</text> <text class="userinfo-nickname" wx:else>未知</text> </view> <view class="infos"> 所在城市:<text class="userinfo-nickname">{{backUserInfo.data.city}}</text> </view> <view class="infos"> 所在省份:<text class="userinfo-nickname">{{backUserInfo.data.province}}</text> </view> <view class="infos"> 所在国家:<text class="userinfo-nickname">{{backUserInfo.data.country}}</text> </view> <view class="infos"> 用户的语言:<text class="userinfo-nickname">{{backUserInfo.data.language}}</text> </view></view>
所需要的jar包
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15</artifactId> <version>1.46</version> </dependency>
后台打印的日志
加密数据=X5Ib86RrR0DbekjW1qnfSDYjcQ2fZ2e9jEzcqiHS54nW/jDPa/qUEAJAXPjB7kDAvjSVoOQ9BGPn2BGruoGyMXssDQHWAsdw9u/dlTPVLuwrKmtiBArgEpeWmYy70+DU3vCrYTFHgXLsg5KWgvXpuhgkz7lcafCr9CBTeq3uIEZ40nNfXJiMeFiQrjT/vCvK8bLWrGv5qBF1LlxlA/7Cxx8oQuAHKjXPaIMjEq+r0/wOhBV13J6n1BZF1J7A0HrtXsy1uw56wAbcJXvWx0dvrS0+Kk//P9uYzOK3+DFHxsne2P2cd1KBqWVY+gg0VWZ8wvYt/FNq9l6zM1RehHCS0Zt3nAjQebHb5IaFSMHjA4qrL21jpjoAAX6SbfgXoLDnENG2cmppqPWBCLAJ6rizTSkAc67sOm9674s4KMz7z8LJr/RIsEnGOMeMhb7ylt3vH+fMtwAA7N9B0wjD908MgtGTPvUhoags/LoqXfpm8DI=加密算法初始向量=P5ZaAJxSuDBzV6IyxKyPhw== 微信小程序code=081hg8Ez1HvYBe0vDnEz1dwdEz1hg8Edresult:{"session_key":"JzWvgMpc9CoWVd7fUVhE0A==","expires_in":7200,"openid":"op5Hs0EYFmR7XvvWNrbsMFVn22Kk"} [cn.xsshome.mvcdo.controller.wechat.WeChatSPController] - =======接口返回的数据:{"session_key":"JzWvgMpc9CoWVd7fUVhE0A==","expires_in":7200,"openid":"op5Hs0EYFmR7XvvWNrbsMFVn22Kk"} [cn.xsshome.mvcdo.controller.wechat.WeChatSPController] - session_key私钥值====JzWvgMpc9CoWVd7fUVhE0A== [cn.xsshome.mvcdo.controller.wechat.WeChatSPController] - 解密后返回页面的数据==={"openId":"op5Hs0EYFmR7XvvWNrbs
作者:小帅帅
来源:https://my.oschina.net/xshuai/blog/1800393