版权声明:版权有就有吧。 https://blog.csdn.net/m0_38044453/article/details/85249621
微信开放平台的官网https://open.weixin.qq.com/,
这里是文档,
这个图看着来,
1. 用户点击微信登录,这时请求我们自己的应用(一个借口,该接口给页面返回一个微信端的登录地址)。
其中的appid是在开放平台注册应用后获取的secret也是,redirect_uri 是告诉微信,用后授权后,微信需要对我们进行回调的接口(把临时授权code,返回这个接口)这个地址也要与注册的一致。state:我看视屏的时候,这个传你登录的页面,也就是登录成功后想到到的页面(官方解释:用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验)
2. 根据第一步获取的登录地址,页面请求加载微信的登录页面,然后进行确认。
3. 确认后微信会对我们自己的应用进行一个回调,并且给我们一个临时的授权code。
4.根据code+appid+appsecret 请求微信能获取用户信息的access_token。
5.微信返回access_token,我们进行解析,处理保存等。
感觉写的有点水,权当记录了,轻点喷……
package com.lpw.dbvideo.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* 微信配置类
*/
@Configuration
@PropertySource(value = "classpath:application.properties")
public class WeChatConfig {
/**
* 微信公众号AppId
*/
@Value("${wx.oa.appid}")
private String wxOAAppId;
/**
* 微信公众号AppSecret
*/
@Value("${wx.oa.appsecret}")
private String wxOAAppSecret;
/**
* 微信开放平台 openappid
*/
@Value("${wx.open.appid}")
private String wxOpenAppId;
/**
* 微信开放平台 openappsecret
*/
@Value("${wx.open.appsecret}")
private String wxOpenSecret;
/**
* 微信开放平台重定向地址
*/
@Value("${wx.open.redirecturl}")
private String wxOpenRedirectUrl;
/**
* 微信开放平台二维码地址
*/
// private static final String OPEN_QRCODE_URL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
private static final String OPEN_QRCODE_URL = "127.0.0.1:8081/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=SCOPE&state=%s#wechat_redirect";
/**
* 开放平台获取access_token 地址
*/
private static final String OPEN_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
/**
* 获取微信用户信息的接口
*/
private static final String OPEN_USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
public String getWxOAAppId() {
return wxOAAppId;
}
public void setWxOAAppId(String wxOAAppId) {
this.wxOAAppId = wxOAAppId;
}
public String getWxOAAppSecret() {
return wxOAAppSecret;
}
public void setWxOAAppSecret(String wxOAAppSecret) {
this.wxOAAppSecret = wxOAAppSecret;
}
public String getWxOpenAppId() {
return wxOpenAppId;
}
public void setWxOpenAppId(String wxOpenAppId) {
this.wxOpenAppId = wxOpenAppId;
}
public String getWxOpenSecret() {
return wxOpenSecret;
}
public void setWxOpenSecret(String wxOpenSecret) {
this.wxOpenSecret = wxOpenSecret;
}
public String getWxOpenRedirectUrl() {
return wxOpenRedirectUrl;
}
public void setWxOpenRedirectUrl(String wxOpenRedirectUrl) {
this.wxOpenRedirectUrl = wxOpenRedirectUrl;
}
public static String getOpenQrcodeUrl() {
return OPEN_QRCODE_URL;
}
public static String getOpenAccessTokenUrl() {
return OPEN_ACCESS_TOKEN_URL;
}
public static String getOpenUserInfoUrl() {
return OPEN_USER_INFO_URL;
}
}
package com.lpw.dbvideo.login.controller;
import com.lpw.dbvideo.config.WeChatConfig;
import com.lpw.dbvideo.user.service.UserService;
import com.lpw.dbvideo.utils.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* 第一步 用户前端请求进入(本项目中的)接口,接口请求微信平台,微信平台给(本项目中的)接口返回一个授权地址,(本项目中的)接口再给前端返回,前端展示;
* 第二步 用户前端进行确认(即扫码确认),接着微信平台会重定向到(本项目中的)接口,并且带上一个授权临时票据code;
* 第三步 根据code加上appid和appsecret 请求微信获取token,微信返回token结束。
*/
@Controller
@RequestMapping("/api/wechat")
public class WeChatController {
@Autowired
private WeChatConfig weChatConfig;
@Autowired
private UserService userService;
/**
* 微信扫一扫登录,获取微信二维码的地址
* @param state 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
* @return
* @throws UnsupportedEncodingException
*/
@RequestMapping("login")
@ResponseBody
@CrossOrigin
public JsonData loginUrl(@RequestParam(value = "state")String state) throws UnsupportedEncodingException {
String redirecrUrl = weChatConfig.getWxOpenRedirectUrl(); // 获取开放平台重定向地址
String callBackUrl = URLEncoder.encode(redirecrUrl,"UTF-8"); // 进行编码
String qrcodeUrl = String.format(WeChatConfig.getOpenQrcodeUrl(),weChatConfig.getWxOpenAppId(),callBackUrl,state);
return JsonData.success(qrcodeUrl);
}
/**
* 微信客户端的回调接口
* @param code 用户确认后,微信端重定向会这个接口,带上授权临时票据(code)
* @param state 上面我们给微信端传的state,微信端会继续返回给我们
* @param response HttpServletResponse
*/
@GetMapping("/user/callback")
public void wechatUserCallBack(String code, String state, HttpServletResponse response){
userService.saveWeChatUser(code);
}
}
package com.lpw.dbvideo.utils;
import com.google.gson.Gson;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.util.HashMap;
import java.util.Map;
/**
* 封装http get,post
*/
public class HttpUtils {
public static final Gson gson = new Gson();
/**
* get方法
* @param url
* @return
*/
public static Map<String, Object> doGet(String url){
Map<String, Object> map = new HashMap<String, Object>();
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig =RequestConfig.custom().setConnectTimeout(5000) // 连接超时
.setConnectionRequestTimeout(5000) // 请求超时
.setSocketTimeout(5000) // 连接socket超时
.setRedirectsEnabled(true) // 允许重定向
.build();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(requestConfig);
try{
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
String jsonResult = EntityUtils.toString(httpResponse.getEntity());
map = gson.fromJson(jsonResult, map.getClass());
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
httpClient.close();
}catch (Exception e){
e.printStackTrace(); }
}
return map;
}
/**
* 封装 post
* @param url 请求路径
* @param data 请求数据
* @param timeout 过期时间
* @return
*/
public static String doPost(String url, String data,int timeout ){
CloseableHttpClient httpClient = HttpClients.createDefault();
// 设置超时
RequestConfig requestConfig =RequestConfig.custom().setConnectTimeout(timeout) // 连接超时
.setConnectionRequestTimeout(timeout) // 请求超时
.setSocketTimeout(timeout) // 连接socket超时
.setRedirectsEnabled(true) // 允许重定向
.build();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-type", "text/html;charset=UTF-8");
if(data != null && data instanceof String){
StringEntity stringEntity = new StringEntity(data, "UTF-8");
httpPost.setEntity(stringEntity);
}
try{
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
if(httpResponse.getStatusLine().getStatusCode() == 200){
String jsonResult = EntityUtils.toString(httpEntity);
return jsonResult;
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
httpClient.close();
}catch (Exception e){
e.printStackTrace();
}
}
return null;
}
}
<!-- httpclient 相关-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
由于测试的时候没有开放平台的认证账号,所以只好自己写一个服务模拟测试(有出入谅解,毕竟不知道微信怎么做的)。附上码云地址。