1、介绍并配置微信公众平台信息
2、微信登录二维码制作
3、微信扫码获取用户信息
介绍并配置微信公众平台信息:
1.微信公众平台申请测试公众号
-
1.1 微信扫码登录的两种方式:微信开放平台、
微信开放平台:微信官方整合更多的第三方应用而搭建的平台,要求公司账号(公司资质+380认证审核费用)官网地址:https://open.weixin.qq.com/微信公众平台:通过扫码关注公众号实现登录,支持个人和公司官网地址:https://mp.weixin.qq.com/ -
1.2 微信公众平台上申请接口测试账号日申请地址:微信公众平台->账号分类(订阅号)->开始开发->接口测试号申请
- ->账号重要信息:appID、appsecret
- ->接口配置信息
- URL:用来和微信服务器通信的接口地址,该地址要求公网可访问!
- 内网穿透:https://natapp.cn/
- 客户端下载(Windows-64位)->解压缩,结果 natapp.exe
- NATAPP 1分钟快速新手图文教程
- 注册账号
- 实名(支付宝授权),否则无法获取隧道
- 购买免费隧道(域名/端口随机,且不定时强制更换),获取authtoken
- cmd进入natapp.exe所在目录,执行:natapp-authtoken=xxxxxx
- Token:Token可由开发者填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全关注测试公众号
- 内网穿透:https://natapp.cn/
- URL:用来和微信服务器通信的接口地址,该地址要求公网可访问!
- ->关注测试公众号
重要提示:必须关注测试公众号,否则无权限调用相关接口(1006) - ->JS接口安全域名
安全域名=内网穿透的域名(不带http://前置) - ->网页服务-网页账号
授权回调页面域名=内网穿透的域名(不带http://前置)
-
1.3 验证消息的确来自微信服务器
开发者提交信息后,出于安全方面考虑可以对接口进行测试,以求证是否微信公众号平台发出的请求;
内网穿透配置:
配置:
打开netapp,将token配置,之后打开,界面不要关闭
测试代码:
@RestController
@RequestMapping("/api")
public class WeixinLoginController {
@RequestMapping("/login")
public String login() {
return "success";
}
}
结果:
配置微信公众平台:
微信扫码关注公众号:
点击提交可能配置失败问题:
解决:
添加校验:
<!-- 如 MD5、SHA-1、SHA-256 等哈希算法。要在 Java 项目中使用 DigestUtils,需要引入 Apache Commons Codec 库。-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.17.0</version>
</dependency>
@Data
public class WeinxinRequest {
private String signature;
private String timestamp;
private String nonce;
private String echostr;
}
public class WebChatUtils {
private static String webChatToken="wxToken";
public static boolean checkWebToken(WeinxinRequest request){
// 将token、timestamp、nonce三个参数进行字典序排序
String [] array={webChatToken,request.getTimestamp(),request.getNonce()};
Arrays.sort(array);
//将三个参数字符串拼接成一个字符串进行sha1加密
String str = String.join("", array);
String sha1 = DigestUtils.sha1Hex(str);
System.out.println(sha1.equals(request.getSignature()));
return sha1.equals(request.getSignature());
}
}
@RestController
@RequestMapping("/api")
public class WeixinLoginController {
@GetMapping("/login")
public String login(WeinxinRequest request) {
if (WebChatUtils.checkWebToken(request)){
return request.getEchostr();
}
System.out.println(request.getSignature());
System.out.println(request.getNonce());
System.out.println(request.getTimestamp());
System.out.println("请求参数:"+request.getEchostr());
return "success";
}
}
重新提交 即可。
2.实现微信扫码登录
2.0 maven依赖
->web-starter、test-starter、lombok、spring-boot-devtools
->weixin-java-mp v4.6.0、hutool v5.8.27、fastjson2 v2.0.25、zxing v3.5.1(hutool的基础库)
2.1 生成登录二维码
https://open.weixin.qq.com/connect/oauth2/authorize?appid=your_appid&redirect_uri=your_redirect_uri&response_type=code&scope=snsapi_userinfo &state=123#wechat_redirect
说明:appid替换为【微信公众平台测试号】的appID;
redirect uri替换为【网页服务-网页账号】授权回调域名下某个处理扫码登录的controller地址;
scope代表授权作用域,微信公众平台仅提供2种:snsapi base和snsapi userinfo。
2.2 草料二维码
官网地址:https://cli.im/
2.3 hutool生成二维码
官网地址:https://hutool.cn/
接入说明文档:
pom:
<!-- 微信-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.23</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 如 MD5、SHA-1、SHA-256 等哈希算法。要在 Java 项目中使用 DigestUtils,需要引入 Apache Commons Codec 库。-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.17.0</version>
</dependency>
配置文件:
tencent:
webchat:
app-id: wx15d42538b1557ece
app-scret: 75aa843c82e39efc008e1d97d429a7db
domain: http://b4846s.natappfree.cc
rediret-uri: /api/toLogin
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(value = "tencent.webchat")
public class Account {
private String appId;
private String appScret;
private String domain;
private String rediretUri;
}
/**
* 生成二维码
* @return
*/
@GetMapping("/qryCode")
public String getQryCode() {
String content="https://open.weixin.qq.com/connect/oauth2/authorize?" +
"appid=your_appid&redirect_uri=your_redirect_uri&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";
System.out.println("account"+account);
String replace = content.replace("your_appid", account.getAppId())
//域名+回调地址
.replace("your_redirect_uri", account.getDomain() + account.getRediretUri());
System.out.println("content>>>>>>>>"+replace);
int width=500;
int height=500;
QrConfig qrConfig = new QrConfig(width, height);
//设置二维码中间的logo
qrConfig.setImg( FileUtil.file("D:\\maven_workplace\\BootProject_test\\boot-project-test\\weixinLogin\\src\\main\\resources\\mylogo.PNG"));
//生成二维码图片的base64字符串
String str = QrCodeUtil.generateAsBase64(replace, qrConfig, "png");
return str;
}
结果:
将base64 转成图片:
https://m.sukoutu.com/base64_img
3、微信扫码获取用户信息
获取授权码
3.4授权码解释:用户在扫描登录的二维码且同意授权之后,微信公众号平台自动向redirect-url发出get请求,请求中携带了授权码参数code。授权码是一个作为换取access token的临时令牌。
3.5获取access_token
access token:获取用户信息的访问令牌。持有该令牌,微信公众号平台认为可以将用户信息开放给开发者
https://api.weixin.qq.com/sns/oauth2/access_token?appid=your_appid&secret=your_appsecret&code=your_code&grant_type=authorization_code
如何获取用户信息
3.6
确保scope=snsapi_userinfo的前提下,获取用户信息的接口地址如下:https://api.weixin.qq.com/sns/userinfo?access token=your_accesstoken&openid=your_openid&lang=zh_CN
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Token {
private String access_token;
private String expires_in;
private String refresh_token;
private String openid;
private String scope;
private String is_snapshotuser;
private String unionid;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String openid;
private String nickname;
private String province;
private String city;
private String country;
private String headimgurl;
private String privilege;
private String unionid;
private Integer sex;
}
@GetMapping("/toLogin")
public void toLogin(String code,String state) {
String content="https://api.weixin.qq.com/sns/oauth2/access_token?" +
"appid=your_appid&secret=your_appsecret&code=your_code&grant_type=authorization_code";
System.out.println("account"+account);
String replace = content.replace("your_appid", account.getAppId())
.replace("your_appsecret", account.getAppScret())
.replace("your_code", code);
//通过http请求
HttpResponse httpResponse = HttpRequestUtil.httpRequest(replace);
HttpEntity entity = httpResponse.getEntity();
//将entity转成字符串的形式
try {
String str = EntityUtils.toString(entity);
//将字符串转换成对象
Token token = JSON.parseObject(str, Token.class);
String accessToken = token.getAccess_token();
String openid = token.getOpenid();
//第四步需要https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
content="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
String replace1 = content.replace("ACCESS_TOKEN", accessToken)
.replace("OPENID", openid);
//http get请求
HttpResponse httpResponse1 = HttpRequestUtil.httpRequest(replace1);
HttpEntity entity1 = httpResponse1.getEntity();
String str1 = EntityUtils.toString(entity1,"UTF-8");
System.out.println("用户信息:"+str1);
User user = JSON.parseObject(str1, User.class);
System.out.println("user信息:"+user);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
http请求工具类
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.IOException;
public class HttpRequestUtil {
//http请求客户端
public static HttpResponse httpRequest(String url) {
HttpClient httpClient= HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(url);
HttpResponse execute =null;
try {
execute = httpClient.execute(httpGet);
} catch (IOException e) {
throw new RuntimeException(e);
}
return execute;
}
}
使用手机微信扫码获得用户信息: