本文主要总结微信小程序通过后台请求访问微信用户信息
创建一个微信小程序工程(自行百度)
微信小程序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=081hg8Ez1HvYBe0vDnEz1dwdEz1hg8Ed
result:{"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":"op5Hs0EYFmR7XvvWNrbsMFVn22Kk","nickName":"小帅丶","gender":1,"language":"zh_CN","city":"Haidian","province":"Beijing","country":"China","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLib098UOLAHuE1fDldajSPuwR0RcPf3rxCtVicwhvdKibYFE0JNibwMwGdiagRzibdAtkSTU1fYxiaz8CIQ/0","watermark":{"timestamp":1524554676,"appid":"wxe71f579c17281234"}}