parent
53b8c2d52f
commit
59dd76af7e
@ -0,0 +1,65 @@
|
||||
package com.luoo.user.controller;
|
||||
|
||||
import annotation.GlobalInterceptor;
|
||||
import annotation.VerifyParam;
|
||||
import api.Result;
|
||||
import api.StatusCode;
|
||||
import com.luoo.user.dto.request.WeChatBindReq;
|
||||
import com.luoo.user.dto.request.WeChatLoginReq;
|
||||
import com.luoo.user.dto.request.WeChatShareReq;
|
||||
import com.luoo.user.service.WeChatAouth2Service;
|
||||
import dto.UserLoginDto;
|
||||
import enums.RequestFrequencyTypeEnum;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import controller.BaseController;
|
||||
import util.JwtUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/21 10:05
|
||||
**/
|
||||
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/wechat")
|
||||
@Api(tags = "WechatLoginController")
|
||||
public class WeChatAouth2Controller extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private WeChatAouth2Service weChatAouth2Service;
|
||||
|
||||
@ApiOperation(value = "分享获取微信token", notes = "成功后返回token,不成功返回null")
|
||||
@PostMapping("/getShareAccessToken")
|
||||
public Result getShareAccessToken(@RequestBody WeChatShareReq weChatShareReq) {
|
||||
return weChatAouth2Service.getShareToken(weChatShareReq);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "微信登录/注册",notes = "微信登录/注册,成功后返回authorization")
|
||||
@PostMapping("/login")
|
||||
@GlobalInterceptor(frequencyType = RequestFrequencyTypeEnum.HOUR, requestFrequencyThreshold = 12)
|
||||
public Result<String> getLoginAccessToken(HttpServletRequest request,
|
||||
@RequestBody @VerifyParam WeChatLoginReq loginReq){
|
||||
return weChatAouth2Service.loginOrRegister(loginReq,getIpAddr(request));
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "绑定手机号",notes = "绑定手机号")
|
||||
@PostMapping("/bindPhoneNumber")
|
||||
@GlobalInterceptor(frequencyType = RequestFrequencyTypeEnum.HOUR, requestFrequencyThreshold = 12)
|
||||
public Result bindPhoneNumber(@RequestHeader(value = "Authorization", required = true) String authorization,
|
||||
@RequestBody @VerifyParam WeChatBindReq weChatBindReq){
|
||||
|
||||
UserLoginDto user = new JwtUtil().getUserLoginDto(authorization);
|
||||
if(user == null)
|
||||
return Result.failed(StatusCode.UNAUTHORIZED);
|
||||
|
||||
return weChatAouth2Service.bindPhoneNumber(user,weChatBindReq);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.luoo.user.dto.request;
|
||||
|
||||
import annotation.VerifyParam;
|
||||
import enums.VerifyRegexEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/25 17:56
|
||||
**/
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ApiModel
|
||||
public class WeChatBindReq implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(name = "mobile", value = "手机号", required = true)
|
||||
@VerifyParam(required = true, regex = VerifyRegexEnum.MOBILE)
|
||||
private String mobile;
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.luoo.user.dto.request;
|
||||
|
||||
import annotation.VerifyParam;
|
||||
import enums.VerifyRegexEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/25 17:26
|
||||
**/
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ApiModel
|
||||
public class WeChatLoginReq implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@ApiModelProperty(name = "code", value = "code码", required = true)
|
||||
@VerifyParam(required = true)
|
||||
String code;
|
||||
|
||||
@ApiModelProperty(name = "deviceId", value = "设备id", required = true)
|
||||
@VerifyParam(required = true)
|
||||
private String deviceId;
|
||||
|
||||
@ApiModelProperty(name = "deviceBrand", value = "设备品牌", required = false)
|
||||
String deviceBrand;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.luoo.user.dto.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/25 19:21
|
||||
**/
|
||||
|
||||
@Data
|
||||
public class WeChatShareReq {
|
||||
|
||||
private String code;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.luoo.user.dto.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/25 18:09
|
||||
**/
|
||||
|
||||
@Data
|
||||
public class Aouth2WeChatErrorResponse {
|
||||
|
||||
private Integer errcode;
|
||||
private String errmsg;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.luoo.user.dto.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/26 21:45
|
||||
**/
|
||||
|
||||
@Data
|
||||
public class Aouth2WeChatJSAPIResponse {
|
||||
|
||||
private Integer errcode;
|
||||
private String errmsg;
|
||||
private String ticket;
|
||||
private Integer expires_in;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.luoo.user.dto.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/21 10:15
|
||||
**/
|
||||
|
||||
@Data
|
||||
public class Aouth2WeChatTokenResponse {
|
||||
private String access_token;
|
||||
private Long expires_in;
|
||||
private String refresh_token;
|
||||
private String openid;
|
||||
private String scope;
|
||||
private String unionid;
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
package com.luoo.user.service;
|
||||
|
||||
import api.Result;
|
||||
import api.StatusCode;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.luoo.user.dto.response.Aouth2WeChatJSAPIResponse;
|
||||
import com.luoo.user.dto.request.WeChatBindReq;
|
||||
import com.luoo.user.dto.request.WeChatLoginReq;
|
||||
import com.luoo.user.dto.request.WeChatShareReq;
|
||||
import com.luoo.user.dto.response.Aouth2WeChatErrorResponse;
|
||||
import com.luoo.user.dto.response.Aouth2WeChatTokenResponse;
|
||||
import com.luoo.user.pojo.UserInfo;
|
||||
import constants.Constants;
|
||||
import dto.UserLoginDto;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Revers.
|
||||
* @date 2024/03/25 15:00
|
||||
**/
|
||||
|
||||
//{"openid":"o5arS6kwYVmRexHdhJgjir9toPdw",
|
||||
// "access_token":"78_VdzZCtUYiA83SDirkIUdir0SqWeb_LyUeX7A9CrszGUvHOd5AmWHFnWM1hEDoXpGQGOhzdQ1g478Z1ZDV8cmpyiKhSKgfJVSiEaVHWTO1vo",
|
||||
// "expires_in":7200,"refresh_token":"78__Vyvij1j4NBfeZ_KTVDaE6XvKnU2J-OtprQC8EfkSTJszq08E1lwI_Wa_dj48b30j4RxQdugRpu8RJ-6l42bJWl5XyoUuk-8J4UyF1nlfDg",
|
||||
// "scope":"snsapi_base"}
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WeChatAouth2Service {
|
||||
|
||||
@Value("${oauth2.weixin.appid}")
|
||||
private String appid;
|
||||
|
||||
@Value("${oauth2.weixin.secret}")
|
||||
private String secret;
|
||||
|
||||
@Autowired
|
||||
private UserInfoService userInfoService;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
public Result getShareToken(WeChatShareReq weChatShareReq){
|
||||
Aouth2WeChatTokenResponse accessToken = getAccessToken(weChatShareReq.getCode());
|
||||
if(accessToken == null || accessToken.getAccess_token() == null )
|
||||
return Result.failed("分享微信失败");
|
||||
|
||||
Aouth2WeChatJSAPIResponse aouth2WeChatJSAPIResponse = getjsapi(accessToken.getAccess_token());
|
||||
if(aouth2WeChatJSAPIResponse == null || aouth2WeChatJSAPIResponse.getTicket() == null)
|
||||
return Result.failed("分享微信失败");
|
||||
|
||||
return Result.success(aouth2WeChatJSAPIResponse.getTicket());
|
||||
}
|
||||
|
||||
public Result loginOrRegister(WeChatLoginReq loginReq,String ipAddress){
|
||||
|
||||
Aouth2WeChatTokenResponse accessToken = getAccessToken(loginReq.getCode());
|
||||
if(accessToken == null || accessToken.getAccess_token() == null){
|
||||
return Result.failed(StatusCode.WECHAT_lOGIN_FAILED);
|
||||
}
|
||||
|
||||
UserInfo loginUserInfo = new UserInfo();
|
||||
loginUserInfo.setWxId(accessToken.getOpenid());
|
||||
loginUserInfo.setLastUseDeviceId(loginReq.getDeviceId());
|
||||
loginUserInfo.setLastUseDeviceBrand(loginReq.getDeviceBrand());
|
||||
loginUserInfo.setLastLoginIp(ipAddress);
|
||||
String token = userInfoService.wechatloginOrRegister(loginUserInfo);
|
||||
return Result.success(token);
|
||||
}
|
||||
|
||||
|
||||
public Result bindPhoneNumber(UserLoginDto user, WeChatBindReq weChatBindReq){
|
||||
return userInfoService.setPhoneNumber(user.getUserId(),weChatBindReq.getMobile());
|
||||
}
|
||||
|
||||
public Aouth2WeChatTokenResponse getAccessToken(String code){
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(Constants.HTTPS_API_WEIXIN_QQ_COM_SNS_OAUTH2_ACCESS_TOKEN);
|
||||
url.append("?appid=").append(urlEncode(appid));
|
||||
url.append("&secret=").append(urlEncode(secret));
|
||||
url.append("&code=").append(urlEncode(code));
|
||||
url.append("&grant_type=authorization_code");
|
||||
String string = new String(get(url.toString()));
|
||||
|
||||
log.info("refreshAccessToken:" + string);
|
||||
Aouth2WeChatTokenResponse aouth2WeChatTokenResponse = JSON.parseObject(string, Aouth2WeChatTokenResponse.class);
|
||||
saveTokenToRedis(aouth2WeChatTokenResponse);
|
||||
|
||||
return aouth2WeChatTokenResponse;
|
||||
}
|
||||
|
||||
public Aouth2WeChatTokenResponse refreshAccessToken(String refresh_token) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(Constants.HTTPS_API_WEIXIN_QQ_COM_SNS_OAUTH2_REFRESH_TOKEN);
|
||||
url.append("?appid=").append(urlEncode(appid));
|
||||
url.append("&grant_type=").append("refresh_token");
|
||||
url.append("&refresh_token=").append(urlEncode(refresh_token));
|
||||
String string = new String(get(url.toString()));
|
||||
|
||||
log.info("refreshAccessToken:" + string);
|
||||
Aouth2WeChatTokenResponse aouth2WeChatTokenResponse = JSON.parseObject(string, Aouth2WeChatTokenResponse.class);
|
||||
saveTokenToRedis(aouth2WeChatTokenResponse);
|
||||
|
||||
return aouth2WeChatTokenResponse;
|
||||
}
|
||||
|
||||
public Boolean isValidAccessToken(String access_token,String openid) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(Constants.HTTPS_API_WEIXIN_QQ_COM_SNS_AUTH);
|
||||
url.append("?access_token=").append(urlEncode(access_token));
|
||||
url.append("&openid=").append(urlEncode(openid));
|
||||
String string = new String(get(url.toString()));
|
||||
log.info("validAccessToken:" + string);
|
||||
Aouth2WeChatErrorResponse dto = JSON.parseObject(string, Aouth2WeChatErrorResponse.class);
|
||||
if(dto.getErrcode() == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private Aouth2WeChatJSAPIResponse getjsapi(String access_token) {
|
||||
StringBuffer url = new StringBuffer();
|
||||
url.append(Constants.HTTPS_API_WEIXIN_QQ_JSAPI);
|
||||
url.append("?access_token=").append(urlEncode(access_token));
|
||||
url.append("&type=").append("jsapi");
|
||||
String string = new String(get(url.toString()));
|
||||
log.info("jsapi:" + string);
|
||||
Aouth2WeChatJSAPIResponse aouth2WeChatJSAPIResponse = JSON.parseObject(string, Aouth2WeChatJSAPIResponse.class);
|
||||
return aouth2WeChatJSAPIResponse;
|
||||
}
|
||||
|
||||
|
||||
private static String urlEncode(String str) {
|
||||
String result = null;
|
||||
try {
|
||||
result = URLEncoder.encode(str, Consts.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static byte[] get(String url) {
|
||||
byte[] res = null;
|
||||
try {
|
||||
HttpResponse response = new DefaultHttpClient().execute(new HttpGet(URI.create(url)));
|
||||
if (response.getStatusLine().getStatusCode() == 200) {
|
||||
HttpEntity entity = response.getEntity();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
|
||||
sb.append(temp);
|
||||
}
|
||||
res = sb.toString().trim().getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private void saveTokenToRedis(Aouth2WeChatTokenResponse aouth2WeChatTokenResponse){
|
||||
if(aouth2WeChatTokenResponse != null && aouth2WeChatTokenResponse.getOpenid() != null ){
|
||||
if(aouth2WeChatTokenResponse.getAccess_token() != null)
|
||||
redisTemplate.opsForValue().set(Constants.REDIS_KEY_WECHAT_TOKEN + aouth2WeChatTokenResponse.getOpenid(),aouth2WeChatTokenResponse.getAccess_token(),2, TimeUnit.HOURS);
|
||||
if(aouth2WeChatTokenResponse.getRefresh_token() != null)
|
||||
redisTemplate.opsForValue().set(Constants.REDIS_KEY_WECHAT_REFRESH_TOKEN + aouth2WeChatTokenResponse.getOpenid(),aouth2WeChatTokenResponse.getRefresh_token(),30, TimeUnit.DAYS);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue