一、准备工作
https://open.weixin.qq.com
1、注册
2、邮箱激活
3、完善开发者资料
4、开发者资质认证
准备营业执照,1-2个工作日审批、300元
5、创建网站应用
提交审核,7个工作日审批
6、熟悉微信登录流程
参考文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=e547653f995d8f402704d5cb2945177dc8aa4e7e&lang=zh_CN
获取access_token时序图
二、生成二维码
开发流程
扫描之后跳转规则
后端开发
Tip:直接请求微信提供的固定地址,向地址后面拼接参数。之后调用controller接口就可以显示登录二维码
1、添加配置
application.properties添加相关配置信息
# 微信开放平台 appid
wx.open.app_id=你的appid
# 微信开放平台 appsecret
wx.open.app_secret=你的appsecret
# 微信开放平台 重定向url
wx.open.redirect_url=http://你的服务器名称/api/ucenter/wx/callback
2、创建常量类
创建util包,创建ConstantPropertiesUtil.java常量类
package com.atguigu.educenter.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ConstantWxUtils implements InitializingBean {
@Value("${wx.open.app_id}")
private String appId;
@Value("${wx.open.app_secret}")
private String appSecret;
@Value("${wx.open.redirect_url}")
private String redirectUrl;
public static String WX_OPEN_APP_ID;
public static String WX_OPEN_APP_SECRET;
public static String WX_OPEN_REDIRECT_URL;
@Override
public void afterPropertiesSet() throws Exception {
WX_OPEN_APP_ID = appId;
WX_OPEN_APP_SECRET = appSecret;
WX_OPEN_REDIRECT_URL = redirectUrl;
}
}
3、创建controller
guli-microservice-ucenter微服务中创建api包
api包中创建WxApiController
//1 生成微信扫描二维码
@GetMapping("login")
public String getWxCode() {
//固定地址,后面拼接参数
// String url = "https://open.weixin.qq.com/" +
// "connect/qrconnect?appid="+ ConstantWxUtils.WX_OPEN_APP_ID+"&response_type=code";
// 微信开放平台授权baseUrl %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";
//对redirect_url进行URLEncoder编码
String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL;
try {
redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
}catch(Exception e) {
}
//设置%s里面值
String url = String.format(
baseUrl,
ConstantWxUtils.WX_OPEN_APP_ID,
redirectUrl,
"atguigu"
);
//重定向到请求微信地址里面
return "redirect:"+url;
}
授权url参数说明
4、测试
访问:http://localhost:8201/api/ucenter/wx/login
访问授权url后会得到一个微信登录二维码
用户扫描二维码会看到确认登录的页面
用户点击“确认登录”后,微信服务器会向谷粒学院的业务服务器发起回调,因此接下来我们需要开发回调controller
注意:如果没有正确的配置业务服务器的回调url,则会看到以下错误提示
三、获取扫描人信息
1、全局配置的跳转路径
# 微信开放平台 重定向url
wx.open.redirect_url=http://回调地址/api/ucenter/wx/callback
2、修改当前项目启动端口号为8150
3、测试回调是否可用
在WxApiController中添加方法
@GetMapping("callback")
public String callback(String code, String state, HttpSession session) {
//得到授权临时票据code
System.out.println("code = " + code);
System.out.println("state = " + state);
}
4、后端开发
(1)添加依赖
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!--commons-io-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!--gson-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
(2)创建httpclient工具类
把资料中的HttpClientUtils.java放入util包
HttpClientUtils.java
(3)创建回调controller方法
在WxApiController.java中添加如下方法
//2 获取扫描人信息,添加数据
@GetMapping("callback")
public String callback(String code, String state) {
try {
//1 获取code值,临时票据,类似于验证码
//2 拿着code请求 微信固定的地址,得到两个值 accsess_token 和 openid
String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=%s" +
"&secret=%s" +
"&code=%s" +
"&grant_type=authorization_code";
//拼接三个参数 :id 、秘钥 和 code值
String accessTokenUrl = String.format(
baseAccessTokenUrl,
ConstantWxUtils.WX_OPEN_APP_ID,
ConstantWxUtils.WX_OPEN_APP_SECRET,
code
);
//请求这个拼接好的地址,得到返回两个值 accsess_token 和 openid
//使用httpclient发送请求,得到返回结果
String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
//从accessTokenInfo字符串获取出来两个值 accsess_token 和 openid
//把accessTokenInfo字符串转换map集合,根据map里面key获取对应值
//使用json转换工具 Gson
Gson gson = new Gson();
HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);
String access_token = (String)mapAccessToken.get("access_token");
String openid = (String)mapAccessToken.get("openid");
//把扫描人信息添加数据库里面
//判断数据表里面是否存在相同微信信息,根据openid判断
UcenterMember member = memberService.getOpenIdMember(openid);
if(member == null) {//memeber是空,表没有相同微信数据,进行添加
//3 拿着得到accsess_token 和 openid,再去请求微信提供固定的地址,获取到扫描人信息
//访问微信的资源服务器,获取用户信息
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=%s" +
"&openid=%s";
//拼接两个参数
String userInfoUrl = String.format(
baseUserInfoUrl,
access_token,
openid
);
//发送请求
String userInfo = HttpClientUtils.get(userInfoUrl);
//获取返回userinfo字符串扫描人信息
HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
String nickname = (String)userInfoMap.get("nickname");//昵称
String headimgurl = (String)userInfoMap.get("headimgurl");//头像
member = new UcenterMember();
member.setOpenid(openid);
member.setNickname(nickname);
member.setAvatar(headimgurl);
memberService.save(member);
}
//使用jwt根据member对象生成token字符串
String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());
//最后:返回首页面,通过路径传递token字符串
return "redirect:http://localhost:3000?token="+jwtToken;
}catch(Exception e) {
throw new GuliException(20001,"登录失败");
}
}
业务层
业务接口:MemberService.java
Member getByOpenid(String openid);
业务实现:MemberServiceImpl.java
@Override
public Member getByOpenid(String openid) {
QueryWrapper<Member> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("openid", openid);
Member member = baseMapper.selectOne(queryWrapper);
return member;
}
四、整合JWT令牌
1、callback中生成jwt
在WxApiController.java的callback方法的最后添加如下代码
// 生成jwt
String token = JwtUtils.geneJsonWebToken(member.getId(),member.getNickName());
//存入cookie
//CookieUtils.setCookie(request, response, "guli_jwt_token", token);
//因为端口号不同存在跨域问题,cookie不能跨域,所以这里使用url重写
return "redirect:http://localhost:3000?token=" + token;
2、前端打印token
在layout/defaullt.vue中打印获取的token值
export default {
created() {
console.log(this.$route.query.token)
}
}
五、前端整合和显示用户登录信息
1、修改default.vue页面脚本
export default {
data() {
return {
token:'',
loginInfo: {
id: '',
age: '',
avatar: '',
mobile: '',
nickname: '',
sex: ''
}
}
},
created() {
// 获取路径里面token值
this.token = this.$route.query.token
if(this.token){ // 判断路径是否有token值
this.wxLogin()
}
this.showInfo()
},
methods:{
// 微信登录显示的方法
wxLogin(){
// 把token值放到cookie里面
cookie.set('guli_token', this.token, { domain: 'localhost' })
cookie.set('guli_ucenter', '', { domain: 'localhost' })
// 调用接口,根据token值获取用户信息
loginApi.getLoginUserInfo()
.then(response => {
this.loginInfo = response.data.data.userInfo
//将用户信息记录cookie
cookie.set('guli_ucenter', this.loginInfo, {domain: 'localhost'})
})
},
//创建方法,从cookie获取用户信息
showInfo() {
//从cookie获取用户信息
var userStr = cookie.get('guli_ucenter') //取到的值userStr的格式是“字符串”:var userStr = "{'name':'lucy','age':20}"
// 把字符串转换json对象(js对象):{'name':'lucy','age':20} 去掉双引号
if(userStr) {
this.loginInfo = JSON.parse(userStr)
}
},
// 退出登录
logout(){
//清空cookie值
cookie.set('guli_token','',{domain: 'localhost'})
cookie.set('guli_ucenter','',{domain: 'localhost'})
//回到首页面
window.location.href = "/";
}
}
};
2、测试
六、总结
首先定义生成二维码接口,扫描之后微信回调callback方法接口返回code(临时票据),拿着code值请求微信固定地址,得到两个值:access_token(访问凭证)和openid(微信唯一标识),你拿着这两个值再去请求微信固定的地址,得到微信扫描人信息(你如昵称,头像等等)。之后把用户信息加入数据库等业务,最后通过地址栏把token返回给前端。前端得到token后放到cookie中。
感谢您的阅读,希望能给您带来帮助
分享知识,让生活更美好!