目录
1 申请测试账号
1.1 登录测试平台
1.2 配置接口配置信息
编辑
1.3 配置JS接口安全域名
1.4 配置网页授权获取用户基本信息
2:接口代码
2.1 微信登录流程
2.2 依赖导入:
2.2.1 工具类:
2.3 创建微信用户实体类
2.4 接口功能
3 测试
1 申请测试账号
1.1 登录测试平台
链接: 微信公众平台测试
1.2 配置接口配置信息
在这一步,需要拥有能接入公网的服务器,或者利用内网穿透将自己的接口暴漏给微信,让微信的回调能成功访问到我们的接口
在可以将我们的接口暴漏在公网的前提下,我们可以书写接口配置接口配置信息的URL:(注意:这里只是简单配置URL,未添加验证微信服务器流程,详细配置请参考:点击进入)
java">import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/weChat")
public class WeChatController{
@GetMapping("/verifyToken")
public String verifyToken(HttpServletRequest request) {
return request.getParameter("echostr");
}
}
比如我们的服务器地址是 119.3.248.100 ,上述服务部署在了该服务器8080端口上,那么按照上述代码的路径,URL就可配置为:http://119.3.248.100:8080/weChat/verifyToken (有域名使用域名即可)
1.3 配置JS接口安全域名
在测试公众号中,可以使用 IP + 端口 的形式设置安全域名,这里的域名填写上述服务你所部署的服务器地址即可
1.4 配置网页授权获取用户基本信息
这里的授权回调页面域名和JS接口安全域名保持一致即可
2:接口代码
2.1 微信登录流程
微信客户端发送登录请求 -> 访问微信授权接口 -> 微信回调,j将授权code发送到我们的服务器 -> 通过code,appid,appsecret获取微信针对该用户的a***sess_token,openid等信息-> 通过a***sess_token,openid获取用户信息
2.2 依赖导入:
在下叙代码中使用到了hutool的工具类,swagger的工具类,通过maven的pom文件导入:(注:实体类使用了一些mybatis-plus的注解,如无用删除即可)
<!-- hutool工具依赖-->
<dependency>
<groupId>***.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
<!-- Swagger3 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.***/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.***/artifact/***.github.xiaoymin/knife4j-spring-boot-starter -->
<dependency>
<groupId>***.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
2.2.1 工具类:
import ***.hutool.http.HttpUtil;
import ***.alibaba.fastjson2.JSONObject;
import java.io.UnsupportedEncodingException;
import java.***.URLEncoder;
import java.util.Map;
/**
* 微信登录工具类
*
* @author
* @date 2023/11/1 15:28
*/
public class WeiXinUtil {
private static final String appId = "xxxx";
private static final String appsecret = "xxxx";
private static final String getCodeUrl = "https://open.weixin.qq.***/connect/oauth2/authorize";
private static final String redirectUrl = "http://xxxxx/v1/login/getA***essToken";
private static final String getA***essTokenUrl = "https://api.weixin.qq.***/sns/oauth2/a***ess_token";
private static final String refreshTokenUrl = "https://api.weixin.qq.***/sns/oauth2/refresh_token";
private static final String getUserInfo = "https://api.weixin.qq.***/sns/userinfo";
/**
* 获取微信授权code
* @param state 附加信息
* @return
*/
public static String getCode(String state) {
try {
StringBuffer url = new StringBuffer();
url.append("redirect:")
.append(getCodeUrl)
.append("?appid=")
.append(appId)
.append("&redirect_uri=")
.append(URLEncoder.encode(redirectUrl, "UTF-8"))
.append("&response_type=code&scope=snsapi_userinfo&state=")
.append(state)
.append("#wechat_redirect");
return url.toString();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("URL格式化异常");
}
}
/**
* 获取微信A***essToken
* @param code 用户code
* @return
*/
public static Map<?, ?> getA***essToken(String code) {
StringBuffer url = new StringBuffer();
url.append(getA***essTokenUrl)
.append("?appid=")
.append(appId)
.append("&secret=")
.append(appsecret)
.append("&code=")
.append(code)
.append("&grant_type=authorization_code");
String rs = HttpUtil.get(url.toString());
Map map = JSONObject.parseObject(rs, Map.class);
if (null == map.get("errcode")) {
return map;
} else {
throw new RuntimeException("获取a***ess_token出错");
}
}
/**
* 刷新A***essToken
* @param refreshToken
* @return
*/
public static Map refreshToken(String refreshToken) {
StringBuffer url = new StringBuffer();
url.append(refreshTokenUrl)
.append("?appid=")
.append(appId)
.append("&grant_type=refresh_token&refresh_token=")
.append(refreshToken);
String rs = HttpUtil.get(url.toString());
Map map = JSONObject.parseObject(rs, Map.class);
if (null == map.get("errcode")) {
return map;
} else {
throw new RuntimeException("刷新a***ess_token出错");
}
}
/**
* 获取用户信息
* @param a***essToken
* @param openid
* @return
*/
public static String getUserInfo(String a***essToken, String openid) {
StringBuffer url = new StringBuffer();
url.append(getUserInfo)
.append("?a***ess_token=")
.append(a***essToken)
.append("&openid=")
.append(openid)
.append("&lang=zh_***");
String rs = HttpUtil.get(url.toString());
return rs;
}
}
2.3 创建微信用户实体类
import ***.baomidou.mybatisplus.annotation.IdType;
import ***.baomidou.mybatisplus.annotation.TableId;
import ***.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
*
* 微信用户信息
* @author
* @date 2023/11/1 16:20
*/
@TableName(value = "wx_user")
@Data
public class WXUser implements Serializable {
private static final long serialVersionUID = -40356785423868312L;
@TableId(type = IdType.AUTO)
private Long id;
/**
* 系统用户id
*/
private Long userId;
/**
* 用户的唯一标识
*/
private String openid;
/**
* a***ess_token
*/
private String a***essToken;
/**
* refresh_token
*/
private String refreshToken;
/**
* 用户昵称
*/
private String nickname;
/**
* 性别(0未知,1男性,2女性)
*/
private String sex;
/**
* 用户个人资料填写的省份
*/
private String province;
/**
* 普通用户个人资料填写的城市
*/
private String city;
/**
* 国家,如中国为***
*/
private String country;
/**
* 用户头像
*/
private String headimgurl;
/**
* 用户特权信息,json 数组
*/
private String privilege;
/**
*
*/
private String unionid;
private Date createTime;
private Date updateTime;
private Long createBy;
private Long updateBy;
}
2.4 接口功能
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("/weChat")
public class WeChatController{
@ResponseBody
@GetMapping("/verifyToken")
@ApiOperation("微信Token验证")
public String verifyToken(HttpServletRequest request) {
return request.getParameter("echostr");
}
@GetMapping("/getCode")
@ApiOperation("获取微信code")
public String weiXinLogin(@RequestParam(defaultValue = "123") String state) {
return WeiXinUtil.getCode(state);
}
@ResponseBody
@GetMapping("/getA***essToken")
@ApiOperation("获取token")
public String getA***essToken(@RequestParam String code) {
Map result = WeiXinUtil.getA***essToken(code);
String a***essToken = result.get("a***ess_token").toString();
String refreshToken = result.get("refresh_token").toString();
String openid = result.get("openid").toString();
WXUser wxUser = new WXUser();
wxUser.setA***essToken(a***essToken);
wxUser.setRefreshToken(refreshToken);
wxUser.setCreateTime(new Date());
wxUser.setUserId(1L);
wxUser.setOpenid(openid);
wxUserService.save(wxUser);
return "<h1>看样子成功了,没你事了退下吧</h1>";
}
@ResponseBody
@GetMapping("/refreshToken")
@ApiOperation("刷新token")
public R refreshToken() {
Long userId = 1L;
WXUser wxUser = wxUserService.getOne(new LambdaUpdateWrapper<WXUser>().eq(WXUser::getUserId, userId));
Map result = WeiXinUtil.refreshToken(wxUser.getRefreshToken());
String a***essToken = result.get("a***ess_token").toString();
String refreshToken = result.get("refresh_token").toString();
WXUser wxUserUpdate = new WXUser();
wxUserUpdate.setId(wxUser.getId());
wxUserUpdate.setA***essToken(a***essToken);
wxUserUpdate.setRefreshToken(refreshToken);
wxUserUpdate.setUpdateTime(new Date());
wxUserService.updateById(wxUserUpdate);
return R.data(a***essToken);
}
@ResponseBody
@GetMapping("/getUserInfo")
@ApiOperation("获取用户信息")
public R getUserInfo() {
Long userId = 1L;
WXUser wxUser = wxUserService.getOne(new LambdaUpdateWrapper<WXUser>().eq(WXUser::getUserId, userId));
String a***essToken = wxUser.getA***essToken();
String openid = wxUser.getOpenid();
String userInfoJsom = WeiXinUtil.getUserInfo(a***essToken, openid);
WXUser userInfo = JSONObject.parseObject(userInfoJsom, WXUser.class);
userInfo.setId(wxUser.getId());
userInfo.setUpdateTime(new Date());
wxUserService.updateById(userInfo);
return R.data(userInfo);
}
}
3 测试
微信扫码关注测试公众号
生成一个二维码调用获取code的接口,百度搜索 将获取code的URL路径填入码,手机微信扫码即可 : 草料文本二维码生成器,微信通过此入口即可访问获取code的页面, 注意:一定要使用手机微信客户端扫码二维码
流程:
获取code中的 redirect_uri 参数可以配置为我们的微信登录接口,这里为了演示功能,配置成了获取a***ess_token 的接口
1. 通过获取code的接口,微信会通过我们配置的redirect_uri参数回调我们的接口,并会携带上code参数,同时注意此接口不要添加@ResponseBody 的注解
2. 微信回调获取a***ess_token的接口,我们可以获取到a***ess_token,refresh_token,openid这三个重要参数,这也是获取用户个人信息的关键
3. 刷新a***ess_token的步骤可省略,有需要时可以调用此功能
4. 获取用户信息,这里获取用户信息的前提是我们在获取code的接口中,参数中的授权范围参数写为snsapi_userinfo