记录下微信开发遇到的遇到的几种授权,待继续填充
一 开放平台-网站应用
详情阅读 官方文档
1.1 获取授权 access_token 以及标识 openid 。
method: get
param: appid = 应用唯一标识,secret = 应用秘钥,code = 调用 wx.login() 请求获取.
若请求正确,解析请求结果即可拿到 access_token (需要缓存,缓存时注意缓存时间,否则可能造成缓存数据与微信服务端数据不一致的情况)与 openid (最好缓存).要仔细检查 appid 与 secret 的是指否正确,还要注意的是 code 只能使用一次,多次使用会返回状态码 40029,提示无效的code.
1.2 通过授权 openid 获取用户信息,包含 unionid
method: get
url: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
param: 1步骤获取的对应值
若请求正确,解析请求结果即可拿到用户基本信息,包含 unionid .
需要理解的是 openid 是普通用户的标识,对当前开发者帐号唯一,而 unionid 是用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。但是要想获取 unionid,必须要求应用绑定微信开放平台.如果未绑定,会出现获取不到 unionid 的情况.
二 小程序
详情阅读 官方文档
2.1 获取标识 openid 以及会话秘钥 session_key
method: get
param: appid = 小程序appId,secret = 小程序appSecret,code = 调用 wx.login() 请求获取.
没有做云开发,忽略图中 5.6,若果满足图中条件 2,3,4, 若请求正确,解析请求结果不仅能拿到 openid 与 session_key,还能直接拿到 unionid.没有拿到,继续按照步骤 2.2 操作
2.2 解密获取unionid
在强调一次,一定要绑定开放平台才能够获取.
调用 wx.getUserInfo(Object object) ,获取到 userInfo,rawData, signature, encryptedData, iv, cloudID
通过获取到的部分信息进行解密,拿到 unionid,也可同时获取用户其他信息,具体的解密步骤可参考下面
2.2.1 编写 AES 对称解密工具类
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
public class AESutil {
public static boolean initialized = false;
/**
* AES对称解密工具类
*
* @param content 密文
* @return
* @throws InvalidAlgorithmParameterException
* @throws NoSuchProviderException
*/
public static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
initialize();
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
// 初始化
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void initialize() {
if (initialized){
return;
}
Security.addProvider(new BouncyCastleProvider());
initialized = true;
}
// 生成iv
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
}
2.2.2 解密
import com.alibaba.fastjson.JSONObject;
import com.yilaiyiwang.consultation.utils.AESutil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import java.nio.charset.StandardCharsets;
/**
* @param iv 加密算法的初始向量
* @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
* @param openId 用户此程序的唯一标识,2.1 步骤获取
* @param rawData 不包括敏感信息的原始数据字符串
* @param signature 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息
*/
public String getUnionId(String iv, String encryptedData, String openId, String rawData, String signature) {
// 获取2.1中的请求到sessionKey
String sessionKey = " 2.1 步骤获取的值";
// 本地加密后的数据
String sha = DigestUtils.sha1Hex(rawData + sessionKey);
// 检查本地加密后的数据是否与接收到的加密数据一致
if (!sha.equals(signature)) {
return "数据不一致";
}
byte[] dataByte = Base64.decodeBase64(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.decodeBase64(sessionKey);
// 偏移量
byte[] ivByte = Base64.decodeBase64(iv);
String userInfo;
String unionid = null;
try {
byte[] resultByte = AESutil.decrypt(dataByte, keyByte, ivByte);
if (null != resultByte && resultByte.length > 0) {
userInfo = new String(resultByte, StandardCharsets.UTF_8);
JSONObject jsonObject = JSONObject.parseObject(userInfo);
unionid = (String) jsonObject.get("unionId");
// 还可以获取其他用户信息,如昵称,头像等
return unionid;
}
} catch (Exception e) {
e.printStackTrace();
}
return "未获取到unionid";
}