微信扫码登录,需要在微信开放平台注册账号被认证为开发者才能接入官网地址:https://open.weixin.qq.com/
下图就是官网,我们点击注册,然后根据要求填写必要的信息,点击提交即可。


使用免费的内网穿透,官网地址:https://suidao.io/#/
先登录网站,然后注册账号。

注册完账号后,就可以登录了

先创建隧道。




下载解压后直接双击SuiDao.Client.exe运行即可

把它修改成内网穿透的地址即可,如图所示:

gitee地址:https://gitee.com/77jubao2015/springbootdemo
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.5.13version>
dependency>
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.3version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.51version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
打开数据库客户端创建数据库,如图说是:


修改为自己本地电脑的即可
代码如下所示:
wxcode:
appId: wx7aa745fb92387941
appSecret: xxxxxxxxxxxxxx
redirectUri: http://wxcode.sh1.k9s.run:2271/wechat/callback
frontUrl: http://localhost:8080/
代码如下所示:
package cn.xueden.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**微信开放平台配置文件
* @Auther:梁志杰
* @Date:2021/11/13
* @Description:cn.xueden.config
* @version:1.0
*/
@Configuration
@Data
@ConfigurationProperties(prefix = "wxcode")
public class WechatConfig {
private String appId;
private String appSecret;
private String redirectUri;
}
代码如下所示:
package cn.xueden.utils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
/**
* @Auther:梁志杰
* @Date:2021/11/13
* @Description:cn.xueden.utils
* @version:1.0
*/
public class WeChatHttpUtils {
public static CloseableHttpClient getClient(){
HttpClientBuilder builder = HttpClientBuilder.create();
return builder.build();
}
}
生成微信二维码,代码如下所示:
//1、生成微信二维码
@GetMapping("login")
public String getWxCode() {
//固定地址,拼接参数
//微信开放平台授权baseUrl 固定格式
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 = wechatConfig.getRedirectUri();
try {
//对URL进行utf-8的编码
URLEncoder.encode(redirectUrl, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String url = String.format( //向指定字符串中按顺序替换%s
baseUrl,
wechatConfig.getAppId(),
wechatConfig.getRedirectUri(),
"Xueden" //自定义(随意设置)
);
//请求微信地址
return "redirect:" + url;
}
通过code获取access_token 并把扫描人信息添加到数据库里
代码如下所示:
@GetMapping("callback")
//1、获取code值,临时票据、类似于验证码(该数据为扫码后跳转时微信方传来)
public String callback(String code,String state, Model model) {
//2、拿着code请求微信固定的地址,得到两个值access_token 和 openid
String baseAccessTokenUrl =
"https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=%s" +
"&secret=%s" +
"&code=%s" +
"&grant_type=authorization_code";
//3、拼接三个参数:id 密钥 code值
String accessTokenUrl = String.format(
baseAccessTokenUrl,
wechatConfig.getAppId(),
wechatConfig.getAppSecret(),
code
);
HttpGet httpGet = null;
CloseableHttpResponse response = null;
URIBuilder uriBuilder = null;
WxMember wxMember = new WxMember();
try {
//请求这个拼接好的地址,得到两个值access_token 和 openid
//使用httpClient发送请求,得到返回结果
httpGet = new HttpGet(accessTokenUrl);
response = WeChatHttpUtils.getClient().execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity()));
String access_token = jsonObject.getString("access_token");
String openid = jsonObject.getString("openid");
String unionid = jsonObject.getString("unionid");
// 获取扫码人信息
uriBuilder = new URIBuilder("https://api.weixin.qq.com/sns/userinfo");
uriBuilder.setParameter("access_token",access_token);
uriBuilder.setParameter("openid",openid);
uriBuilder.setParameter("lang","zh_CN");
httpGet.setHeader("Accept", "application/json");
httpGet.addHeader("Content-type","application/json; charset=utf-8");
httpGet = new HttpGet(uriBuilder.build());
response = WeChatHttpUtils.getClient().execute(httpGet);
JSONObject jsonUserinfo = JSON.parseObject(EntityUtils.toString(response.getEntity()));
log.info("access_token{},openid{},unionid{},获取信息{}",access_token, openid,unionid,jsonUserinfo);
wxMember.setCity(jsonUserinfo.getString("city"));
wxMember.setCountry(jsonUserinfo.getString("country"));
wxMember.setProvince(jsonUserinfo.getString("province"));
wxMember.setHeadimgurl(jsonUserinfo.getString("headimgurl"));
String nickname = new String(jsonUserinfo.getString("nickname").getBytes("ISO-8859-1"), "UTF-8");
wxMember.setNickname(nickname);
wxMember.setOpenid(openid);
wxMember.setUnionid(unionid);
wxMember.setSex(jsonUserinfo.getInteger("sex"));
wxMemberService.saveOrUpdate(wxMember);
} catch (Exception e) {
e.printStackTrace();
}
model.addAttribute("wxmember",wxMember);
model.addAttribute("frontUrl", wechatConfig.getFrontUrl());
return "result";
}
代码如下所示:
/**
* 带条件分页查询用户列表
*/
@GetMapping
public ResponseEntity<Object> getList(WxMemberQueryCriteria criteria, PageVo pageVo) throws Exception {
int pageNo = pageVo.getPageIndex()-1;
Pageable pageable = PageRequest.of( pageNo<0?0:pageNo, pageVo.getPageSize() , Sort.Direction.DESC, "id" );
return new ResponseEntity<>(wxMemberService.getList(criteria,pageable), HttpStatus.OK);
}
代码如下所示:
/**
*
* @param criteria
* @param pageable
* @return
*/
Object getList(WxMemberQueryCriteria criteria, Pageable pageable);
/**
* 根据条件分页获取系统管理员列表信息
* @param criteria 查询条件
* @param pageable 分页信息
* @return
*/
@Override
public Object getList(WxMemberQueryCriteria criteria, Pageable pageable) {
Page<WxMember> page = wxMemberRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page);
}
代码如下所示:
package cn.xueden.domain;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import javax.validation.constraints.NotNull;
import javax.persistence.*;
import java.sql.Timestamp;
/**
* @Auther:梁志杰
* @Date:2021/5/16
* @Description:cn.xueden
* @version:1.0
*/
@Data
@Entity
@Table(name="t_member")
@org.hibernate.annotations.Table(appliesTo = "t_member",comment="微信用户信息表")
public class WxMember {
/**
* 自增 id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@NotNull(groups = Update.class)
private Long id;
/**
* 用户openid
*/
private String openid;
/**
* 用户unionid
*/
private String unionid;
/**
* 用户昵称
*/
private String nickname;
/**
* 性别
*/
private Integer sex;
/**
* 用户所属省份
*/
private String province;
/**
* 用户所属城市
*/
private String city;
/**
* 用户所属国家
*/
private String country;
/**
* 用户头像
*/
private String headimgurl;
/**
* 创建时间
*/
@Column(name = "create_time",nullable = false)
@CreationTimestamp
private Timestamp createTime;
public @interface Update {}
}
代码如下所示:
package cn.xueden.dto;
import cn.xueden.annotation.EnableXuedenQuery;
import lombok.Data;
/**功能描述:查询条件
* @Auther:梁志杰
* @Date:2021/5/16
* @Description:cn.xueden.dto
* @version:1.0
*/
@Data
public class WxMemberQueryCriteria {
/**
* 根据性别查询
*/
@EnableXuedenQuery
private int sex;
/**
* 根据昵称模糊查询
*/
@EnableXuedenQuery(blurry = "nickname")
private String nickname;
}
在resources文件夹下新建一个名为templates文件夹,并在此文件夹下新建result.html页面
代码如下所示:
DOCTYPE html>
<html lang="ch" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
name="viewport">
<meta content="ie=edge" http-equiv="X-UA-Compatible">
<link rel="icon" th:href="@{resource/favicon.ico}" type="image/x-icon"/>
<title>登录跳转中title>
head>
<body>
登录中..
<script th:inline="javascript">
var response = [[${wxmember}]];
var frontUrl = [[${frontUrl}]];
window.onload = function () {
window.opener.postMessage(response, frontUrl);
window.close();
}
script>
body>
html>
gitee地址:https://gitee.com/77jubao2015/wxpaydemo
代码如下所示:
{{ scope.row.sex === 0
? '男性'
: (scope.row.sex === 1
? '女性'
: '未知') }}
代码如下所示:
export const getListApi = ({ params }: PropsData): any => {
return fetch({ url: '/wechat', method: 'get', params })
}
代码所示:
登录
登录
微信扫码登录
e’, resolveSocialLogin, false)
}
ElNotification({
title: '提示',
message: '账号 admin 为 前端 控制路由权限,账号 test 为 后端 控制路由权限。密码与账号相同',
duration: 60000
})
return {
loginForm,
loading, redirect, form, rules, page,
login,
wxlogin
}
}
})