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);
}
}
上一篇: 20201213周回顾