java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot UniApp对接微信OAuth2登录

SpringBoot + UniApp对接微信OAuth2登录的全过程

作者:z晨晨

现在小程序逐渐成为主流,常用的微信授权登录很重要很常见的一个功能,这篇文章主要介绍了使用SpringBoot + UniApp对接微信OAuth2登录的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

本文将手把手带你打通SpringBoot后端与UniApp前端的微信登录全流程,并分享那些官方文档没写的实战经验。

前期准备

在开始编码前,这些准备工作必须到位

特别注意:微信登录权限需要单独申请,通过审核后才能正常使用!

前端实战:Uniapp一键登录按钮

关键代码实现

<template>
  <view class="container">
    <button class="wechat-btn" open-type="getUserInfo" @click="handleWechatLogin">
      <uni-icons type="weixin" color="#fff" size="30"></uni-icons>
      微信一键登录
    </button>
  </view>
</template>

<script>
export default {
  methods: {
    async handleWechatLogin() {
      try {
        // 获取微信授权码
        const loginRes = await uni.login({
          provider: "weixin",
          onlyAuthorize: true, // 关键参数:仅授权不获取用户信息
        });
        
        // 调用后端登录接口
        const res = await uni.request({
          url: "你的后端地址/weChatLogin", // 记得换成你的实际地址!
          method: 'POST',
          data: { socialCode: loginRes.code }
        });
        
        if (res.data.token) {
          // 登录成功处理
          uni.showToast({ title: '登录成功!', icon: 'success' });
        } else {
          // 需要绑定手机号
          this.goToBindPhone();
        }
      } catch (error) {
        uni.showToast({ title: '登录失败,请重试', icon: 'none' });
      }
    }
  }
}
</script>

核心要点:

后端开发:Springboot接收与处理

后端的核心使命:安全验证 + 用户管理 + 令牌发放

@Tag(name = "微信登录")
@RestController
public class SysLoginController {
    
    @Autowired
    private SysLoginService loginService;
    
    @Operation(summary = "微信授权登录")
    @PostMapping("/weChatLogin")
    public AjaxResult weChatLogin(@RequestBody LoginBodyWeChat loginBody) {
        // 三步走:授权 -> 获取用户信息 -> 生成令牌
        Map<String, String> authResult = weiXinApiService.authorize(loginBody.getSocialCode());
        Map<String, String> userInfo = weiXinApiService.getUserInfo(
            authResult.get("access_token"), 
            authResult.get("openid")
        );
        
        String token = loginService.weChatLogin(userInfo);
        
        // 返回令牌给前端
        return AjaxResult.success()
            .put(Constants.TOKEN, token)
            .put("unionid", userInfo.get("unionid"));
    }
}
@Component
public class WeiXinApiService {
    
    public Map<String, String> authorize(String socialCode) {
        String url = String.format(
            "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", 
            appid, secret, socialCode
        );
        
        String response = HttpUtil.get(url);
        JSONObject jsonObject = JSONUtil.parseObj(response);
        
        // 错误处理绝不能少!
        if (jsonObject.containsKey("errcode")) {
            throw new ServiceException("微信登录失败:" + jsonObject.get("errmsg"));
        }
        
        // 返回access_token和openid
        return Map.of(
            "access_token", jsonObject.getStr("access_token"),
            "openid", jsonObject.getStr("openid")
        );
    }
    public Map<String, String> getUserInfo(String accessToken, String openId) {
        String url = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", 
        accessToken, openId);
        String response = HttpUtil.get(url);
        JSONObject jsonObject = JSONUtil.parseObj(response);
        if (jsonObject.containsKey("errcode")) {
            throw new ServiceException("获取微信用户信息失败:" + jsonObject.get("errmsg"));
        }
        Map<String, String> result = new HashMap<>();
        result.put("nickname", jsonObject.getStr("nickname"));
        result.put("sex", jsonObject.getStr("sex"));
        result.put("headimgurl", jsonObject.getStr("headimgurl"));
        result.put("unionid", jsonObject.getStr("unionid"));
        result.put("openid", jsonObject.getStr("openid"));
        return result;
    }
}
public String weChatLogin(Map<String, String> userInfo) {
    // 用unionid查询用户
    SysUser user = userService.selectUserByOpenId(userInfo.get("unionid"));//这里可以根据自己的业务框架来处理
    
    if (user == null) {
        // 新用户:自动注册
        user = createNewUser(userInfo);
        userService.insertUser(user);//这里可以根据自己的业务框架来处理
    }
    
    // 未绑定手机号?引导绑定
    if (StringUtils.isBlank(user.getPhonenumber())) {
        return ""; // 前端根据空token跳转绑定页面
    }
    
    // 执行登录,生成token
    return performLogin(user.getPhonenumber());//这里可以根据自己的业务框架来处理
}

核心概念解析:openid vs unionid

很多开发者在这里踩坑,其实很简单:

简单理解:openid是部门工号,unionid是公司工号

手机号绑定

重要提醒:微信官方已限制获取用户手机号!我们的解决方案:

  1. 自动检测:用户首次微信登录后,检测是否已绑定手机
  2. 友好引导:token为空时,前端跳转到绑定页面
  3. 简化流程:只需验证码即可完成绑定

参考代码:

@PostMapping("/bindPhoneNumber")
public AjaxResult bindPhoneNumber(@RequestBody LoginBodyBindPhone loginBody) {
    // 验证码校验 + 绑定手机号
    String token = loginService.bindPhoneNumber(loginBody);
    return AjaxResult.success().put(Constants.TOKEN, token);
}
@Data
public class LoginBodyBindPhone {

    @Schema(description = "手机号")
    private String phonenumber;
    @Schema(description = "微信用户统一标识")
    private String unionid;
    @Schema(description = "验证码")
    private String code;
}

微信登录对接就像搭积木——步骤固定,但细节决定成败。掌握核心流程(获取code → 换取token → 获取用户信息 → 业务处理),你就能应对各种场景。

总结

到此这篇关于SpringBoot + UniApp对接微信OAuth2登录的文章就介绍到这了,更多相关SpringBoot UniApp对接微信OAuth2登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

阅读全文