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;
|
||||
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.agileboot.api.response.ShopGoodsResponse;
|
||||
import com.agileboot.common.constant.WeixinConstants;
|
||||
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.ShopGoodsEntity;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
@ -26,6 +30,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
|||
@RestController
|
||||
@RequestMapping("/api/shop")
|
||||
@CrossOrigin(origins = "*", allowedHeaders = "*")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ShopController {
|
||||
|
||||
|
@ -62,18 +67,41 @@ public class ShopController {
|
|||
}
|
||||
|
||||
@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"
|
||||
+ "?appid=" + WeixinConstants.appid
|
||||
+ "&redirect_uri=http%3A%2F%2Fwxshop.ab98.cn%2Fshop"
|
||||
+ "&response_type=code"
|
||||
+ "&scope=snsapi_base"
|
||||
+ "&state=STATE#wechat_redirect";
|
||||
+ "&state=" + state
|
||||
+ "#wechat_redirect";
|
||||
return new RedirectView(authUrl);
|
||||
}
|
||||
|
||||
@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"
|
||||
+ "?appid=" + WeixinConstants.corpid
|
||||
+ "&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());
|
||||
}
|
||||
|
||||
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.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.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.agileboot.domain.ab98.api.Ab98ApiUtil;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/wx/login")
|
||||
@CrossOrigin(origins = "*", allowedHeaders = "*")
|
||||
|
@ -88,7 +92,28 @@ public class WxLoginController {
|
|||
data.setTel(loginResponse.getOutputData().getTel());
|
||||
return ResponseDTO.ok(data);
|
||||
} catch (ApiException e) {
|
||||
log.error("短信验证失败: {}", e.getMessage());
|
||||
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;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.agileboot.common.exception.ApiException;
|
||||
import com.agileboot.common.exception.error.ErrorCode;
|
||||
import lombok.Data;
|
||||
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.Map;
|
||||
|
||||
|
@ -22,9 +26,6 @@ public class Ab98ApiUtil {
|
|||
* 发送短信验证码(短信登录)
|
||||
* @param token 通过getToken获取的临时令牌(有效期5分钟)
|
||||
* @param tel 接收验证码的手机号码(需符合格式:11位数字)
|
||||
* @param nobind "true"表示不绑定手机号(固定值)
|
||||
* @param for_login "true"表示用于登录(固定值)
|
||||
* @param from 来源渠道(固定值"jt")
|
||||
*/
|
||||
public static SmsSendResponse sendLoginSms(String token, String tel) {
|
||||
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
|
||||
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