微信小程序登陆,后端接口实现 - springboot

登录流程

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

wx.login

调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台帐号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台帐号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。

code,用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息。

  • openid:指的微信用户在微信的某个应用中的唯一标识。
  • unionid:指的微信用户的唯一标识。(相当于微信用户ID)
  • 微信某个应用:指的是 公众号、小程序、开放平台等。
  • 若要开发多个微信应用,应当获取微信用户的唯一标识 unionid。

目前小程序开发者可以通过 wx.login 接口直接获取用户的 openId 与 unionId 信息,实现微信身份登录。对许多小程序使用场景,用户无需提供头像昵称。如有必要场景需收集用户头像昵称,可在个人中心或设置等页面让用户完善个人资料。如业务需获取用户头像、昵称,可以使用「头像昵称填写能力」

wx.getUserProfile

获取用户信息。页面产生点击事件(例如 buttonbindtap 的回调中)后才可调用,每次请求都会弹出授权窗口,用户同意后返回 userInfo

属性类型说明最低版本
signaturestring使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息,详见 用户数据的签名验证和加解密2.10.4
encryptedDatastring包括敏感数据在内的完整用户信息的加密数据,详见 用户数据的签名验证和加解密2.10.4
ivstring加密算法的初始向量,详见 用户数据的签名验证和加解密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 等信息。

  • 在换取到openid/unionid后,查找用户表,若有匹配的用户则自动登录,否则自动注册一个账号再完成自动登录,返回token到前端。以实现微信小程序快速登录。
  • 现在无法通过解密encryptedData(wx.getUserProfile得到)获取用户的昵称、头像、性别、地区等数据,得提供一个类似“个人中心“的页面让用户自己完善(如果用户需要)。

springboot示例

配置文件

配置文件application.properties

# 微信小程序配置
wx.appId=wxd95.......de4cfe
wx.appSecret=76b497f2.........ea08645f8824
wx.online_people_url=https://api.weixin.qq.com/sns/jscode2session

登录微信公众平台获取小程序的AppID、AppSecret

Controller

@ApiOperation(value = "微信小程序自动登录/注册")
@GetMapping("/wxauth/signin/{code}")
public DataVo<String> doWxLogin(@PathVariable @ApiParam(value = "wx.login获取的登录凭证",required = true) String code){
    return authService.doWxLogin(code);
}

Service

使用注解@Value获取配置在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;
获取session_key等

访问 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息:

  • 封装方法getSessionKeyByWX,使用 code 换取 openid、session_key
  • getSessionKey,调用getSessionKeyByWX,获取session_key
/**
 * 微信登陆,通过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\"}";
    }
}


/**
 * 微信登陆,通过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);
    }
}
获取用户数据

使用 session_key 解密encryptedData数据,获取用户信息(已废弃,encryptedData中没有用户数据):调用getUserInfo前,先调用getSessionKey获取session_key。

/**
 * 微信登陆,解密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);
}
登录

doWxLogin,调用getSessionKeyByWX,获取openid,实现自动登录

/**
 * 微信小程序自动登录/注册
 * @param code wx.login获取的登录凭证
 */
public DataVo doWxLogin(String code){
    //使用登录凭证code获取openid
    JSONObject json = JSONUtil.parseObj(getSessionKeyByWX(code));
    if(json.getBool("isSuccess")) {
      // 通过 json.getStr("openid") 获取openid
      // 根据openid判断新用户还是老用户
      //   老用户,登录操作,返回token
      //   新用户,则随机注册一个账号(用户名、账号、用户ID),登录操作,返回token
      //...
      // return xxx(登陆成功)
    }else {
        // 记录日志
        log.error("获取sessionkey失败! code = "+code);
        return JSONResult.errorMsg("登录失败! 无法获取openid!");
    }
}

说明

本博客中的案例,使用的maven依赖如下:http请求、AES解密均使用的是hutool

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.2</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<!--        启用web支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--        hutool-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.10</version>
</dependency>



笔记摘自:CSDN-、楽.知乎-微信小程序获取用户unionId微信官方文档 • 小程序

  • 17
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
随着移动互联网技术的发展和用户需求的变化,【小程序名称】应运而生,以其轻量化、便捷化的设计理念为用户提供了一种全新的服务模式。作为一款无需下载安装即可使用的应用,【小程序名称】依托于微信庞大的生态系统,让用户在微信内就能轻松实现各种功能操作。 【小程序名称】的核心功能主要集中在【具体服务领域】,例如在线购物、本地生活服务、教育学习或健康管理等。它简化了传统APP繁琐的注册登录流程,支持微信一键授权登录,极大地提升了用户体验。用户通过搜索或扫描二维码,瞬间即可开启使用,享受快速加载、流畅运行的服务。 该小程序界面设计简洁明了,布局合理,易于上手。同时,其特色功能如实时更新的信息推送、个性化推荐以及社交分享功能,让用户能够及时获取所需信息,并方便地将优质内容分享至朋友圈或好友,实现信息的高效传播与互动。 【小程序名称】注重数据安全与隐私保护,严格遵守国家法律法规和微信平台的规定,确保用户数据的安全无虞。此外,其背后的开发团队持续迭代更新,根据用户反馈不断优化产品性能,提升服务质量,致力于打造一个贴近用户需求、充满活力的小程序生态。 总结来说,【小程序名称】凭借其小巧便携、快捷高效的特性,不仅节省了用户的手机存储空间,更为用户提供了无缝衔接的便利服务,是现代生活中不可或缺的一部分,真正实现了“触手可及”的智能生活新体验。只需轻点屏幕,无限精彩尽在掌握之中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值