如果未关注公众号,调用wx.login接口是获取不到unionid的,只能返回openid和session_key,这种情况下,就需要微信前端调用wx.getUserInfo接口获取到加密数据encryptedData和iv传给后台,后台解密得到unionid。

微信小程序登录(包括获取不到unionid的情况)
微信小程序官方文档 wx.getUserInfo(OBJECT)
微信小程序之用户数据解密(七)
后台接口:
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ResponseObj<BindInfo> getUserInfo(@RequestParam String code/*, @RequestParam String tokenid, @RequestParam
String encryptedData, @RequestParam String iv*/) throws Exception {
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" +
"wx6c5536682a2fbb01&secret=95895e544ca1b8da98da582e483751d3&js_code=" +
code + "&grant_type=authorization_code";
//微信端登录code值
String wxCode = code;
//请求地址 https://api.weixin.qq.com/sns/jscode2session
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
Map<String, String> requestUrlParam = new HashMap<String, String>();
//开发者设置中的appId
requestUrlParam.put("appid", "wx6c5536682a2fbb01");
//开发者设置中的appSecret
requestUrlParam.put("secret", "95895e544ca1b8da98da582e483751d3");
//小程序调用wx.login返回的code
requestUrlParam.put("js_code", wxCode);
//默认参数
requestUrlParam.put("grant_type", "authorization_code");
//发送post请求读取调用微信 https://api.weixin.qq.com/sns/jscode2session 接口获取openid用户唯一标识
JSONObject jsonObject = JSONObject.fromObject(UrlUtil.sendPost(requestUrl, requestUrlParam));
String session_key = (String) jsonObject.get("session_key");
//解密encryptedData
JSONObject userInfos = getUserInfos(encryptedData, session_key, iv);
String openid = (String) userInfos.get("openid");
String unionId = (String) userInfos.get("unionId");
BindInfo bindInfo = bindInfoMapper.selectUserId(openid, unionId);
/**
* 获取信息
* getUserInfo前端获取加密数据encryptedData传给后台,后台解密
*/
public JSONObject getUserInfos(String encryptedData, String sessionkey, String iv) {
// 被加密的数据
byte[] dataByte = Base64.decodeBase64(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.decodeBase64(sessionkey);
// 偏移量
byte[] ivByte = Base64.decodeBase64(iv);
try {
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
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, "UTF-8");
return JSONObject.fromObject(result);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
return null;
}
完整control
package com.jsptpd.weixinserver.restcontrol;
import com.jsptpd.weixinserver.dao.TokenMapper;
import com.jsptpd.weixinserver.dao.UserMapper;
import com.jsptpd.weixinserver.dao2.BindInfoMapper;
import com.jsptpd.weixinserver.model.BindInfo;
import com.jsptpd.weixinserver.model.Token;
import com.jsptpd.weixinserver.util.UrlUtil;
import net.sf.json.JSONObject;
import org.apache.commons.net.util.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
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;
/**
* Created by HASEE on 2018/6/29 15:39
*/
@RestController
@RequestMapping("/weixin")
public class WeixinControl {
@Autowired
BindInfoMapper bindInfoMapper;
@Autowired
UserMapper userMapper;
@Autowired
TokenMapper tokenMapper;
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ResponseObj<BindInfo> getUserInfo(@RequestParam String code/*, @RequestParam String tokenid, @RequestParam
String encryptedData, @RequestParam String iv*/) throws Exception {
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" +
"wx6c5536682a2fbb01&secret=95895e544ca1b8da98da582e483751d3&js_code=" +
code + "&grant_type=authorization_code";
//微信端登录code值
String wxCode = code;
//请求地址 https://api.weixin.qq.com/sns/jscode2session
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
Map<String, String> requestUrlParam = new HashMap<String, String>();
//开发者设置中的appId
requestUrlParam.put("appid", "wx6c5536682a2fbb01");
//开发者设置中的appSecret
requestUrlParam.put("secret", "95895e544ca1b8da98da582e483751d3");
//小程序调用wx.login返回的code
requestUrlParam.put("js_code", wxCode);
//默认参数
requestUrlParam.put("grant_type", "authorization_code");
//发送post请求读取调用微信 https://api.weixin.qq.com/sns/jscode2session 接口获取openid用户唯一标识
JSONObject jsonObject = JSONObject.fromObject(UrlUtil.sendPost(requestUrl, requestUrlParam));
// String str = "{\"session_key\":\"wQC1GNJd1EKlpyd5RdsdhQ==\",\"openid\":\"oywxK1LR_7NvxDPWppj3fqcP9brQ\"," +
// "\"unionId\":\"oIu0Y0u8-7YOm7ll4bnFX034jYvU\"}";
// JSONObject jsonObject = JSONObject.fromObject(str);
String session_key = (String) jsonObject.get("session_key");
String openid = (String) jsonObject.get("openid");
String unionId = (String) jsonObject.get("unionId");
if (unionId != null && !"".equals(unionId)) { //微信login接口返回中无unionid
BindInfo bindInfo = bindInfoMapper.selectUserId(openid, unionId);
if (bindInfo != null) {
String uid = bindInfo.getUserId();
String clientid = "wechat";
if (uid == null || uid.equals("")) {
Error error = new Error();
error.errCode = Error.IllegalRequest;
error.errMessage = "";
return new ResponseObj<>(error);
} else {
Token token = tokenMapper.selectByUserId1(uid, clientid);
if (token != null) {
token.setUserId(uid);
token.setClientId(clientid);
token.setTokenId(UUID.randomUUID().toString());
token.setTokenCreateDate(new Date());
tokenMapper.deleteByUserId1(uid, clientid);
tokenMapper.insert(token);
bindInfo.setTokenId(token.getTokenId());
return new ResponseObj<>(bindInfo);
} else {
Token token1 = new Token();
token1.setUserId(uid);
token1.setClientId(clientid);
token1.setTokenId(UUID.randomUUID().toString());
token1.setTokenCreateDate(new Date());
tokenMapper.deleteByUserId1(uid, clientid);
tokenMapper.insert(token1);
bindInfo.setTokenId(token1.getTokenId());
return new ResponseObj<>(bindInfo);
}
}
} else {
Error error = new Error();
error.errCode = Error.IllegalRequest;
error.errMessage = "无此用户";
return new ResponseObj<>(error);
}
} else {
Error error = new Error();
error.errCode = Error.IllegalRequest;
error.errMessage = "请先绑定cpdat云终端";
return new ResponseObj<>(error);
}
// String str = "{\"session_key\":\"wQC1GNJd1EKlpyd5RdsdhQ==\",\"openid\":\"oywxK1Ehxj9X8AElEWdS2QcZ46qs\"," +
// "\"unionId\":\"oIu0Y0thYOJISZWzTIjTMDsqIZGo\"}";
// JSONObject jsonObject = JSONObject.fromObject(str);
// String session_key = (String) jsonObject.get("session_key");
// String openid = (String) jsonObject.get("openid");
// String unionId = (String) jsonObject.get("unionId");
// JSONObject userInfos = getUserInfos(encryptedData, session_key, iv);
// String openid = (String) userInfos.get("openid");
// String unionId = (String) userInfos.get("unionId");
// BindInfo bindInfo = bindInfoMapper.selectUserId(openid, unionId);
}
/**
* 获取信息
* getUserInfo前端获取加密数据encryptedData传给后台,后台解密
*/
public JSONObject getUserInfos(String encryptedData, String sessionkey, String iv) {
// 被加密的数据
byte[] dataByte = Base64.decodeBase64(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.decodeBase64(sessionkey);
// 偏移量
byte[] ivByte = Base64.decodeBase64(iv);
try {
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
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, "UTF-8");
return JSONObject.fromObject(result);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
return null;
}
}
网友评论