feat(登录): 新增通过token快速登录功能
新增SsoLoginUserinfo类用于存储登录用户信息,并在WxLoginController中实现tokenLogin接口,支持通过token快速登录。同时优化了ShopController中的微信授权逻辑,支持传递token参数。
This commit is contained in:
parent
41dc6aee69
commit
ea22f44e41
|
@ -1,5 +1,7 @@
|
||||||
package com.agileboot.api.controller;
|
package com.agileboot.api.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.URLUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.agileboot.api.response.ShopGoodsResponse;
|
import com.agileboot.api.response.ShopGoodsResponse;
|
||||||
import com.agileboot.common.constant.WeixinConstants;
|
import com.agileboot.common.constant.WeixinConstants;
|
||||||
import com.agileboot.common.core.dto.ResponseDTO;
|
import com.agileboot.common.core.dto.ResponseDTO;
|
||||||
|
@ -10,15 +12,17 @@ import com.agileboot.domain.shop.goods.GoodsApplicationService;
|
||||||
import com.agileboot.domain.shop.goods.db.SearchGoodsWithCabinetDO;
|
import com.agileboot.domain.shop.goods.db.SearchGoodsWithCabinetDO;
|
||||||
import com.agileboot.domain.shop.goods.db.ShopGoodsEntity;
|
import com.agileboot.domain.shop.goods.db.ShopGoodsEntity;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.servlet.view.RedirectView;
|
import org.springframework.web.servlet.view.RedirectView;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
@ -26,6 +30,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/shop")
|
@RequestMapping("/api/shop")
|
||||||
@CrossOrigin(origins = "*", allowedHeaders = "*")
|
@CrossOrigin(origins = "*", allowedHeaders = "*")
|
||||||
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ShopController {
|
public class ShopController {
|
||||||
|
|
||||||
|
@ -62,18 +67,41 @@ public class ShopController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/wechatAuth")
|
@GetMapping("/wechatAuth")
|
||||||
public RedirectView wechatAuthRedirect() {
|
public RedirectView wechatAuthRedirect(HttpServletRequest request, @RequestParam String token) {
|
||||||
|
/*java.util.StringJoiner joiner = new java.util.StringJoiner("&");
|
||||||
|
request.getParameterMap().forEach((key, values) -> {
|
||||||
|
joiner.add(key + "=" + String.join(",", values));
|
||||||
|
});
|
||||||
|
log.info("wechatAuth 参数:{}", joiner.toString());*/
|
||||||
|
|
||||||
|
String state = "";
|
||||||
|
if (StringUtils.isNoneBlank(token)) {
|
||||||
|
state = "token_" + token;
|
||||||
|
}
|
||||||
|
/*try {
|
||||||
|
state = URLEncoder.encode(state, StandardCharsets.UTF_8.name());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
log.error("wechatAuth 编码失败", e);
|
||||||
|
}*/
|
||||||
|
|
||||||
String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"
|
String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"
|
||||||
+ "?appid=" + WeixinConstants.appid
|
+ "?appid=" + WeixinConstants.appid
|
||||||
+ "&redirect_uri=http%3A%2F%2Fwxshop.ab98.cn%2Fshop"
|
+ "&redirect_uri=http%3A%2F%2Fwxshop.ab98.cn%2Fshop"
|
||||||
+ "&response_type=code"
|
+ "&response_type=code"
|
||||||
+ "&scope=snsapi_base"
|
+ "&scope=snsapi_base"
|
||||||
+ "&state=STATE#wechat_redirect";
|
+ "&state=" + state
|
||||||
|
+ "#wechat_redirect";
|
||||||
return new RedirectView(authUrl);
|
return new RedirectView(authUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/qy/wechatAuth")
|
@GetMapping("/qy/wechatAuth")
|
||||||
public RedirectView qyWechatAuthRedirect() {
|
public RedirectView qyWechatAuthRedirect(HttpServletRequest request) {
|
||||||
|
/*java.util.StringJoiner joiner = new java.util.StringJoiner("&");
|
||||||
|
request.getParameterMap().forEach((key, values) -> {
|
||||||
|
joiner.add(key + "=" + String.join(",", values));
|
||||||
|
});
|
||||||
|
log.info("/qy/wechatAuth 参数:{}", joiner.toString());*/
|
||||||
|
|
||||||
String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"
|
String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"
|
||||||
+ "?appid=" + WeixinConstants.corpid
|
+ "?appid=" + WeixinConstants.corpid
|
||||||
+ "&redirect_uri=http%3A%2F%2Fwxshop.ab98.cn%2Fshop-api%2Fapi%2Fshop%2FapprovalRedirect"
|
+ "&redirect_uri=http%3A%2F%2Fwxshop.ab98.cn%2Fshop-api%2Fapi%2Fshop%2FapprovalRedirect"
|
||||||
|
@ -100,4 +128,9 @@ public class ShopController {
|
||||||
|
|
||||||
return new RedirectView(builder.build().encode().toUriString());
|
return new RedirectView(builder.build().encode().toUriString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws UnsupportedEncodingException {
|
||||||
|
String res = URLEncoder.encode("token=12312", StandardCharsets.UTF_8.name());
|
||||||
|
System.out.println(res);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,15 +2,19 @@ package com.agileboot.api.controller;
|
||||||
|
|
||||||
import com.agileboot.common.core.dto.ResponseDTO;
|
import com.agileboot.common.core.dto.ResponseDTO;
|
||||||
import com.agileboot.common.exception.ApiException;
|
import com.agileboot.common.exception.ApiException;
|
||||||
|
import com.agileboot.common.exception.error.ErrorCode;
|
||||||
|
import com.agileboot.domain.ab98.api.SsoLoginUserinfo;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import com.agileboot.domain.ab98.api.Ab98ApiUtil;
|
import com.agileboot.domain.ab98.api.Ab98ApiUtil;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/wx/login")
|
@RequestMapping("/api/wx/login")
|
||||||
@CrossOrigin(origins = "*", allowedHeaders = "*")
|
@CrossOrigin(origins = "*", allowedHeaders = "*")
|
||||||
|
@ -88,7 +92,28 @@ public class WxLoginController {
|
||||||
data.setTel(loginResponse.getOutputData().getTel());
|
data.setTel(loginResponse.getOutputData().getTel());
|
||||||
return ResponseDTO.ok(data);
|
return ResponseDTO.ok(data);
|
||||||
} catch (ApiException e) {
|
} catch (ApiException e) {
|
||||||
|
log.error("短信验证失败: {}", e.getMessage());
|
||||||
return ResponseDTO.fail(e);
|
return ResponseDTO.fail(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/tokenLogin")
|
||||||
|
@ApiOperation(value = "通过token登录", notes = "用于快速登录,无需验证码")
|
||||||
|
public ResponseDTO<Ab98ApiUtil.LoginData> tokenLogin(@RequestParam String token) {
|
||||||
|
SsoLoginUserinfo loginUserinfo = Ab98ApiUtil.getLoginUserInfoRemote("wxshop", "34164e41f0c6694be6bbbba0dc50c14a", token, "");
|
||||||
|
|
||||||
|
Ab98ApiUtil.LoginData data = new Ab98ApiUtil.LoginData();
|
||||||
|
if (loginUserinfo == null) {
|
||||||
|
return ResponseDTO.fail(new ApiException(ErrorCode.FAILED, "登录失败,请重新尝试"));
|
||||||
|
}
|
||||||
|
data.setFace_img(loginUserinfo.getFace());
|
||||||
|
data.setSuccess(true);
|
||||||
|
data.setSex(loginUserinfo.getSex());
|
||||||
|
data.setName(loginUserinfo.getName());
|
||||||
|
data.setUserid(String.valueOf(loginUserinfo.getId()));
|
||||||
|
data.setRegistered(true);
|
||||||
|
data.setTel(loginUserinfo.getPhone());
|
||||||
|
|
||||||
|
return ResponseDTO.ok(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
package com.agileboot.domain.ab98.api;
|
package com.agileboot.domain.ab98.api;
|
||||||
|
|
||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.agileboot.common.exception.ApiException;
|
import com.agileboot.common.exception.ApiException;
|
||||||
import com.agileboot.common.exception.error.ErrorCode;
|
import com.agileboot.common.exception.error.ErrorCode;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -22,9 +26,6 @@ public class Ab98ApiUtil {
|
||||||
* 发送短信验证码(短信登录)
|
* 发送短信验证码(短信登录)
|
||||||
* @param token 通过getToken获取的临时令牌(有效期5分钟)
|
* @param token 通过getToken获取的临时令牌(有效期5分钟)
|
||||||
* @param tel 接收验证码的手机号码(需符合格式:11位数字)
|
* @param tel 接收验证码的手机号码(需符合格式:11位数字)
|
||||||
* @param nobind "true"表示不绑定手机号(固定值)
|
|
||||||
* @param for_login "true"表示用于登录(固定值)
|
|
||||||
* @param from 来源渠道(固定值"jt")
|
|
||||||
*/
|
*/
|
||||||
public static SmsSendResponse sendLoginSms(String token, String tel) {
|
public static SmsSendResponse sendLoginSms(String token, String tel) {
|
||||||
String url = BASE_URL + "?code=doSendSms";
|
String url = BASE_URL + "?code=doSendSms";
|
||||||
|
@ -146,6 +147,38 @@ public class Ab98ApiUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录用户信息
|
||||||
|
* @param appname
|
||||||
|
* @param appsecret
|
||||||
|
* @param token
|
||||||
|
* @param companyName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static SsoLoginUserinfo getLoginUserInfoRemote(String appname,
|
||||||
|
String appsecret,
|
||||||
|
String token,
|
||||||
|
String companyName) {
|
||||||
|
String sign = DigestUtils.md5Hex(String.format("app=%s&token=%s%s", appname, token, appsecret));
|
||||||
|
String url = String.format("https://www.ab98.cn/api/getLoginUserInfo?token=%s&app=%s&company_name=%s&sign=%s"
|
||||||
|
,token
|
||||||
|
,appname
|
||||||
|
,""
|
||||||
|
,sign);
|
||||||
|
|
||||||
|
String res = HttpUtil.get(url);
|
||||||
|
try {
|
||||||
|
JSONObject o = JSONUtil.parseObj(res);
|
||||||
|
String state = o.getStr("state");
|
||||||
|
if (StringUtils.equalsIgnoreCase(state, "ok")) {
|
||||||
|
return o.get("data", SsoLoginUserinfo.class);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取登录用户信息失败", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// 基础响应对象
|
// 基础响应对象
|
||||||
@Data
|
@Data
|
||||||
public static class BaseResponse {
|
public static class BaseResponse {
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.agileboot.domain.ab98.api;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SsoLoginUserinfo {
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 缓存失效时间戳(秒)
|
||||||
|
*/
|
||||||
|
private Integer expire;
|
||||||
|
/**
|
||||||
|
* 账号状态状态:1-正常 2-冻结
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 姓名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 性别
|
||||||
|
*/
|
||||||
|
private String sex;
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
private String phone;
|
||||||
|
/**
|
||||||
|
* 微信昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
/**
|
||||||
|
* 微信openid
|
||||||
|
*/
|
||||||
|
private String openId;
|
||||||
|
/**
|
||||||
|
* 微信unionId
|
||||||
|
*/
|
||||||
|
private String unionId;
|
||||||
|
/**
|
||||||
|
* 微信头像
|
||||||
|
*/
|
||||||
|
private String headImage;
|
||||||
|
/**
|
||||||
|
* 人脸图像
|
||||||
|
*/
|
||||||
|
private String face;
|
||||||
|
/**
|
||||||
|
* 身份证号码
|
||||||
|
*/
|
||||||
|
private String idCardNo;
|
||||||
|
/**
|
||||||
|
* 身份证正面
|
||||||
|
*/
|
||||||
|
private String idCardFront;
|
||||||
|
/**
|
||||||
|
* 身份证背面
|
||||||
|
*/
|
||||||
|
private String idCardBack;
|
||||||
|
/**
|
||||||
|
* 身份证地址
|
||||||
|
*/
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原登录账号
|
||||||
|
*/
|
||||||
|
private String oldAccount;
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue