1、通过调用wx.login获取登录凭证(code)
2、前端将code提交给服务器,springboot访问 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息。
3、完成登录操作,返回token给前端。
测试发现,个人小程序无法获取unionid
通过调用wx.login获取登录凭证(code)
示例:uni-app项目中,使用uni.login获取登录凭证(code)
// 微信小程序
// #ifdef MP-WEIXIN
uni.login({
provider: 'weixin',
success: function(loginRes) {
if (loginRes.errMsg == "login:ok") {
//提交code到服务器,完成登录操作
doWxLogin({
code: loginRes.code
}).then(res => {
console.log(res)
//。。。
})
}
}
});
// #endif
调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台帐号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台帐号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。
code,用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息。
目前小程序开发者可以通过 wx.login 接口直接获取用户的 openId 与 unionId 信息,实现微信身份登录。对许多小程序使用场景,用户无需提供头像昵称。如有必要场景需收集用户头像昵称,可在个人中心或设置等页面让用户完善个人资料。如业务需获取用户头像、昵称,可以使用「头像昵称填写能力」。
获取用户信息。页面产生点击事件(例如 button
上 bindtap
的回调中)后才可调用,每次请求都会弹出授权窗口,用户同意后返回 userInfo
。
属性 | 类型 | 说明 | 最低版本 |
---|---|---|---|
signature | string | 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息,详见 用户数据的签名验证和加解密 | 2.10.4 |
encryptedData | string | 包括敏感数据在内的完整用户信息的加密数据,详见 用户数据的签名验证和加解密 | 2.10.4 |
iv | string | 加密算法的初始向量,详见 用户数据的签名验证和加解密 | 2.10.4 |
自2022年11月8日24时起,已废弃。wx.getUserProfile,在uni-app中是uni.getUserProfile。若该方法未失效,可使用code换取的session_key将encryptedData解密,获取用户信息。
前端将code提交给服务器,springboot访问 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息。
配置在springboot配置文件中的参数:
//https://api.weixin.qq.com/sns/jscode2session
@Value("${wx.online_people_url}")
private String ONLINE_PEOPLE_URL;
//小程序的AppID
@Value("${wx.appId}")
private String APP_ID;
//小程序的AppSecret
@Value("${wx.appSecret}")
private String SECRET;
登录微信公众平台获取小程序的AppID、AppSecret
访问 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息:
/**
* 微信登陆,通过code获取session_key
* @param code 通过wx.login获取到的用户的code(登录凭证)
* @return 返回session_key,用于解密 前端wx.getUserProfile接口 返回的加密的用户数据(2022-11,微信已弃用该接口,已无法通过其获取用户信息)。
*/
public DataVo<String> getSessionKey(String code) {
//使用 hutool 解析json
JSONObject json = JSONUtil.parseObj(getSessionKeyByWX(code));
if(json.getBool("isSuccess")) {
log.info("isSuccess = true,成功获取到session_key。session_key = "+json.getStr("session_key"));
return JSONResult.ok(json.getStr("session_key"));
}else {
// 记录日志
log.error("获取sessionkey失败! code = "+code);
return JSONResult.errorMsg("获取sessionkey失败! code = "+code);
}
}
/**
* 微信登陆,通过code获取session_key、openid。
* session_key:用于解密 前端wx.getUserProfile(以前是wx.getUserInfo)接口 返回的加密的用户数据,头像、昵称、性别、地区等信息(2022-11,微信已弃用该接口,已无法通过其获取用户信息)。
* openid:用户的身份标识,每个用户在每个公众号或者小程序中都有一个唯一openid,跨公众号/小程序时openid不相同。若想在公众号、小程序、开放平台等地方使用不同账号,则使用openid作为用户标识。
*
* @param code 通过wx.login获取到的用户的code(登录凭证)
* @return 返回session_key、openid、isSuccess,通过isSuccess是否为true来判断是否成功获取到session_key、openid。
* 示例:{"session_key":"VtyIGnq9U2E8c95XUm2SeQ==","openid":"o60_YvksCvHRpajcmiLVAUYybXcM","isSuccess":"false"}
*/
public String getSessionKeyByWX(String code) {
String baseUrl = ONLINE_PEOPLE_URL + "?appid=" + APP_ID + "&secret=" + SECRET + "&js_code=" + code + "&grant_type=authorization_code";
log.info("---微信登陆,通过code获取sessionkey");
log.info("---baseUrl ="+baseUrl);
//使用 hutool 发起get请求
//基于JDK的HttpUrlConnection封装
String result = HttpUtil.get(baseUrl);
log.info("---拿到GET结果 ="+result);
//使用 hutool 解析json
JSONObject jsonObject = JSONUtil.parseObj(result);
if(!jsonObject.isNull("session_key")) {
//成功获取到session_key等数据
return result.substring(0,result.length()-1)+",\"isSuccess\":\"true\"}";
}else {
//失败,没获取到session_key等数据
return "{\"session_key\":\"\",\"openid\":\"\",\"isSuccess\":\"false\"}";
}
}
使用 session_key 解密encryptedData数据,获取用户信息(已废弃,encryptedData中没有用户数据):
/**
* 微信登陆,解密encryptedData数据。
* 但因为微信调整了用户信息权限,只能获取unionid,不能再获取头像、昵称、性别、地区等信息。
* unionid,微信用户的唯一标识(相当于微信用户ID),若想在公众号、小程序、开放平台等地方使用同一个账号,则使用unionid
* @param encryptedData 被加密的数据
* @param signature 加密秘钥(即getSessionKey方法返回的sessionKey)
* @param iv 偏移量
* @return 解密后的encryptedData(用户信息)
*/
public DataVo<String> getUserInfo(String encryptedData, String signature, String iv){
// 被加密的数据
byte[] dataByte = Base64.getDecoder().decode(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.getDecoder().decode(signature);
// 偏移量
byte[] ivByte = Base64.getDecoder().decode(iv);
log.error("被加密的数据 encryptedData= "+encryptedData);
log.error("加密秘钥 sessionKey= "+signature);
log.error("偏移量 iv= "+iv);
//hutool AES解密
AES aes = new AES("CBC","PKCS7Padding",keyByte,ivByte);
String res = aes.decryptStr(dataByte);
log.info("---解密后 ="+res);
// 解密并返回
return JSONResult.ok(res);
}
本博客中的案例,使用的maven依赖如下:http请求、AES解密均使用的是hutool
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.5.2version>
<relativePath/>
parent>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.8.10version>
dependency>
笔记摘自:CSDN-、楽. 、 知乎-微信小程序获取用户unionId 、 微信官方文档 • 小程序