创建授权按钮,向后台获取unionid
<template>
<view style="margin-top: 60%;">
<!-- <button type="default" open-type="getUserInfo" @getuserinfo='getuserinfo'>微信授权</button> -->
<view style="text-align: center;">申请获取你的公开信息(昵称,头像等)</view>
<button
open-type="getUserInfo"
withCredentials="true"
class="mc btn-auth"
@getuserinfo="getUserInfo"
>
授权登录
</button>
</view>
</template>
<script>
export default {
data() {
return {
code:"",
next:"",
}
},
onLoad(e) {
this.next=e.next;
},
onReady() {
},
methods: {
getUserInfo() {
// let = {};
// var that= this
let _this = this;
uni.login({
provider: "weixin",
success: (res) => {
let code = res.code;
uni.getUserInfo({
provider: "weixin",
lang: "zh_CN",
success: function(res) {
uni.request({
url: getApp().globalData.url+'/wechat/login',
data: {
rawData:res.rawData,//用户信息
signature:"111",
code: code,
encryptedData:res.encryptedData,
iv:res.iv,
},
method:'POST',
header: {
'Content-Type': 'application/json',
},
success: (res) => {
if(res.data.status==200){
// 添加缓存
uni.setStorage({
key: 'unionId',
data: res.data.data.userInfo.unionId,
success: function () {
console.log('缓存unionId 成功');
}
});
uni.setStorage({
key: 'nickName',
data: res.data.data.userInfo.nickName,
success: function () {
console.log('缓存昵称 成功');
}
});
if(_this.next.length>0){
uni.redirectTo({//跳转页面
url:_this.next,
})
}else{
// 返回上一个页面
uni.navigateBack()
}
}else{
uni.showToast({
title:"授权失败,请重新在试"
})
}
}, fail: function(err) {
uni.showToast({
title:"授权失败,请重新在试"
})
},
})
},
fail: function(err) {
uni.showModal({
title: "提示",
content: "需要通过授权才能继续,请重新点击并授权!",
showCancel: false,
success: function (res) {
if (res.confirm) {
} else if (res.cancel) { return}
}
});
},
});
},
});
}
}
}
</script>
<style>
</style>
后台处理
/**
* 微信授权,获取微信服务器unionId等等信息
* @param loginDTO
* @return
*/
@PostMapping("/login")
public Object login(@RequestBody LoginDTO loginDTO){
Map map = new HashMap();
try{
//获取openid和session_key
SessionDTO sessionDTO=wechatAdapter.jscode2session(loginDTO.getCode());
try {
//对encryptedData加密数据进行AES解密
String result = AesCbcUtil.decrypt(loginDTO.getEncryptedData(), sessionDTO.getSessionKey() ,loginDTO.getIv(), "UTF-8");
// System.out.println(result);
if (null != result && result.length() > 0) {
map.put("status", 1);
map.put("msg", "解密成功");
JSONObject userInfoJSON = JSON.parseObject(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"));
// 解密unionId & openId;
userInfo.put("unionId", userInfoJSON.get("unionId"));
map.put("userInfo", userInfo);
} else {
map.put("status", 0);
map.put("msg", "解密失败");
}
} catch (Exception e) {
return ResultDTO.fail(CommonErrorCode.Wechat_SIGNATURE_ERROR);
}
return ResultDTO.ok(map);
}catch (ErrorCodeException e){
return ResultDTO.fail(e);
}catch (Exception e){
System.out.println(e.toString());
return ResultDTO.fail(CommonErrorCode.UNKOWN_ERROR);
}
}
获取openid和session_key
@Value("${wechat.appid}")
private String appid;
@Value("${wechat.secret}")
private String secret;
public SessionDTO jscode2session(String code) {
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.addHeader("content-type", "application/json")
.url(String.format(url, appid, secret, code))
.build();
try {
Response execute = okHttpClient.newCall(request).execute();
if (execute.isSuccessful()) {
SessionDTO sessionDTO = JSON.parseObject(execute.body().string(), SessionDTO.class);
return sessionDTO;
} else {
throw new ErrorCodeException(CommonErrorCode.OBTAIN_OPENID_ERROR);
}
} catch (IOException e) {
throw new ErrorCodeException(CommonErrorCode.OBTAIN_OPENID_ERROR);
}
}
解密类
package com.fusdom.utils;
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;
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 {
// initialize();
//被加密的数据
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;
}
}
LoginDTO 实体类
package com.fusdom.DTO;
/**
* Created by codedrinker on 2018/11/24.
*/
//这里的数据根据文档创建的
public class LoginDTO {
// 用户信息原始数据
private String rawData;
// 用于验证用户信息是否被篡改过
private String signature;
// 用户获取 session_key 的 code
private String code;
private String encryptedData;
private String iv;
public String getEncryptedData() {
return encryptedData;
}
public void setEncryptedData(String encryptedData) {
this.encryptedData = encryptedData;
}
public String getIv() {
return iv;
}
public void setIv(String iv) {
this.iv = iv;
}
public String getRawData() {
return rawData;
}
public void setRawData(String rawData) {
this.rawData = rawData;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
SessionDTO 实体类
package com.fusdom.DTO;
import com.alibaba.fastjson.annotation.JSONField;
/**
* Created by codedrinker on 2018/11/24.
*/
public class SessionDTO {
private String openid;
@JSONField(name = "session_key")
private String sessionKey;
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getSessionKey() {
return sessionKey;
}
public void setSessionKey(String sessionKey) {
this.sessionKey = sessionKey;
}
}