欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java微信二维码第三方后台登陆实现 ( 二 )

程序员文章站 2022-07-10 17:36:52
...

二.后台实现微信登录
1.生成二维码
a.利用user微服务实现生成二维码功能
b.需要把user微服务端口号改为8150(看需求决定)
c.前端登录页面端口号地址也改为8150
d.把RestController变为Controller(因为前端展示的是二维码图片,不然就会生成json数据展示在页面)
2.用户扫描二维码 微信给客户端发送一个code
3.通过appid+appsecret+code获取access_token+openid
4.通过access_token+openid获取用户个人信息
5.把用户个人信息保存到数据库
6.返回一个token信息给前端

package com.atguigu.controller;

import com.atguigu.entity.MemberCenter;
import com.atguigu.service.MemberCenterService;
import com.atguigu.utils.HttpClientUtils;
import com.atguigu.utils.JwtUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;

//不能转化为json数据
@Controller
//前端需要跳转的页面
@RequestMapping("/api/ucenter/wx")
@CrossOrigin
public class WxApiController {
    //拿到配置文件里的数据
    @Value("${wx.open.app_id}")
    private String WX_OPEN_APP_ID;
    @Value("${wx.open.app_secret}")
    private String WX_OPEN_APP_SECRET;
    @Value("${wx.open.redirect_url}")
    private String WX_OPEN_REDIRECT_URL;

    @Autowired
    private MemberCenterService memberCenterService;

    //获取二维码
    @GetMapping("/login")
    public String qrCode() throws UnsupportedEncodingException {
        //%s表示占位符,需要我们设定值,其他则是固定式
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";
        //转化路径中的\\,符合微信二维码路径标准
        String redirectUrl = URLEncoder.encode(WX_OPEN_REDIRECT_URL, "UTF-8");
        //自己设置的
        String state = "zhuyonghaoshuai";
        //给上面路径中的%s占位符赋值
        String retUrl = String.format(baseUrl, WX_OPEN_APP_ID, redirectUrl, state);
        //将结果返回,就可以生成二维码
        return "redirect:" + retUrl;
    }

    @GetMapping("/callback")
    //编写callback回调方法
    //扫描二维码后微信会返回一个code
    public String callback(String code) throws Exception {
        //向认证服务器发送请求换取access_token和open_id
        String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                "?appid=%s" +
                "&secret=%s" +
                "&code=%s" +
                "&grant_type=authorization_code";
        //给上面路径中的%s占位符赋值
        String baseAccessTo = String.format(baseAccessTokenUrl, WX_OPEN_APP_ID, WX_OPEN_APP_SECRET, code);
        //模拟http请求
        String retUrl = HttpClientUtils.get(baseAccessTo);
        //将http请求转换为map,利用map的key-value取值。因为只需要拿到其中的access_token和open_id两个值,其他值看需求拿取
        Gson gson = new Gson();
        HashMap retMap = gson.fromJson(retUrl, HashMap.class);
        //转化为map后去除需要的属性
        String access_token = (String) retMap.get("access_token");
        String openid = (String) retMap.get("openid");
        //根据access_token和openid获取用户信息
        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                "?access_token=%s" +
                "&openid=%s";
        String userInfo = String.format(userInfoUrl, access_token, openid);
        //模拟http请求
        String userInfos = HttpClientUtils.get(userInfo);
        //将http请求转换为map,利用map的key-value取值。
        //注意这里是用户想要返回给我们的信息
        HashMap userInfoMap = gson.fromJson(userInfos, HashMap.class);
        //一般需要返回头像和昵称,openid是必须要返回的,其他看需求
        String nickname = (String) userInfoMap.get("nickname");
        String headimgurl = (String) userInfoMap.get("headimgurl");
        QueryWrapper<MemberCenter> wrapper = new QueryWrapper<>();
        wrapper.eq("openid", openid);
        //通过openid查询数据库是否有用户数据
        MemberCenter memberCenter = memberCenterService.getOne(wrapper);
        //如果没有就将用户返回的数据存储到数据库
        if (memberCenter == null) {
            //拿到用户信息后,需要保存到数据库
            memberCenter = new MemberCenter();
            //头像地址,昵称 和 openid
            memberCenter.setAvatar(headimgurl);
            memberCenter.setNickname(nickname);
            memberCenter.setOpenid(openid);
            memberCenterService.save(memberCenter);
        }
        //最后将加密的token返回给前端首页,具体返回到哪个页面看需求
        String token = JwtUtils.geneJsonWebToken(memberCenter);
        return "redirect:http://127.0.0.1:3000?token="+token;
    }
}

2.登陆后用户信息展示

  //通过token获取用户信息
    @GetMapping("queryUserInfoByToken/{token}")
    public RetVal queryUserInfoByToken(@PathVariable("token") String token) {
        //利用JWT另外一个方法获取用户信息
        Claims claims = JwtUtils.checkJWT(token);
        String id = (String) claims.get("id");
        String nickname = (String) claims.get("nickname");
        String avatar = (String) claims.get("avatar");
       // 创建一个MemberCenterVo,封装需要的数据返回,保证数据的安全性
        MemberCenterVo memberCenterVo = new MemberCenterVo();
        memberCenterVo.setId(id);
        memberCenterVo.setAvatar(avatar);
        memberCenterVo.setNickname(nickname);
        return RetVal.success().data("memberCenterVo",memberCenterVo);
    }
}