添加用户表单相关操作
parent
26d1a24460
commit
cab4585959
@ -0,0 +1,31 @@
|
||||
package com.baiye.manager;
|
||||
|
||||
|
||||
import com.baiye.util.JwtHelper;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* 维护用户token
|
||||
*/
|
||||
public class UserTokenManager {
|
||||
|
||||
public static String generateToken(Long id) {
|
||||
JwtHelper jwtHelper = new JwtHelper();
|
||||
return jwtHelper.createToken(id);
|
||||
}
|
||||
|
||||
|
||||
public static Long getUserId(String token) {
|
||||
JwtHelper jwtHelper = new JwtHelper();
|
||||
|
||||
Long userId = jwtHelper.verifyTokenAndGetUserId(token);
|
||||
if(userId == null || userId == 0){
|
||||
return null;
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.baiye.util;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTCreationException;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.Claim;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.baiye.constant.DefaultNumberConstants;
|
||||
import com.baiye.exception.BadRequestException;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Enz
|
||||
*/
|
||||
public class JwtHelper {
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*/
|
||||
static final String SECRET = "WX-MALL-TOKEN";
|
||||
|
||||
/**
|
||||
* 签名是有谁生成
|
||||
*/
|
||||
static final String USER = "ENZO";
|
||||
|
||||
/**
|
||||
* 签名的主题
|
||||
*/
|
||||
static final String SUBJECT = "USER-FORM-TOKEN";
|
||||
|
||||
/**
|
||||
* 签名的观众
|
||||
*/
|
||||
static final String AUDIENCE = "USER-FORM-USER";
|
||||
|
||||
|
||||
public String createToken(Long userId) {
|
||||
try {
|
||||
Algorithm algorithm = Algorithm.HMAC256(SECRET);
|
||||
Map<String, Object> map = new HashMap<>(DefaultNumberConstants.SIXTEEN_NUMBER);
|
||||
Date nowDate = new Date();
|
||||
map.put("alg", "HS256");
|
||||
map.put("typ", "JWT");
|
||||
return JWT.create()
|
||||
// 设置头部信息 Header
|
||||
.withHeader(map)
|
||||
// 设置 载荷 Payload
|
||||
.withClaim("userId", userId)
|
||||
.withIssuer(USER)
|
||||
.withSubject(SUBJECT)
|
||||
.withAudience(AUDIENCE)
|
||||
// 生成签名的时间
|
||||
.withIssuedAt(nowDate)
|
||||
// 签名过期的时间
|
||||
//.withExpiresAt(expireDate)
|
||||
// 签名 Signature
|
||||
.sign(algorithm);
|
||||
} catch (JWTCreationException exception) {
|
||||
throw new BadRequestException("生成token失败");
|
||||
}
|
||||
}
|
||||
|
||||
public Long verifyTokenAndGetUserId(String token) {
|
||||
try {
|
||||
Algorithm algorithm = Algorithm.HMAC256(SECRET);
|
||||
JWTVerifier verifier = JWT.require(algorithm)
|
||||
.withIssuer(USER)
|
||||
.build();
|
||||
DecodedJWT jwt = verifier.verify(token);
|
||||
Map<String, Claim> claims = jwt.getClaims();
|
||||
Claim claim = claims.get("userId");
|
||||
return claim.asLong();
|
||||
} catch (JWTVerificationException exception) {
|
||||
throw new BadRequestException("校验失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Date getAfterDate(Date date, int year, int month, int day, int hour, int minute, int second) {
|
||||
if (date == null) {
|
||||
date = new Date();
|
||||
}
|
||||
|
||||
Calendar cal = new GregorianCalendar();
|
||||
|
||||
cal.setTime(date);
|
||||
if (year != 0) {
|
||||
cal.add(Calendar.YEAR, year);
|
||||
}
|
||||
if (month != 0) {
|
||||
cal.add(Calendar.MONTH, month);
|
||||
}
|
||||
if (day != 0) {
|
||||
cal.add(Calendar.DATE, day);
|
||||
}
|
||||
if (hour != 0) {
|
||||
cal.add(Calendar.HOUR_OF_DAY, hour);
|
||||
}
|
||||
if (minute != 0) {
|
||||
cal.add(Calendar.MINUTE, minute);
|
||||
}
|
||||
if (second != 0) {
|
||||
cal.add(Calendar.SECOND, second);
|
||||
}
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.baiye.modules.system.domain;
|
||||
|
||||
import com.baiye.model.base.BaseEntity;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date : 2022/4/18
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name="tb_user_form")
|
||||
public class FormUser extends BaseEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7676856944264681235L;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@NotNull(groups = BaseEntity.Update.class)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "phone")
|
||||
@ApiModelProperty(value = "手机号码")
|
||||
private String phone;
|
||||
|
||||
@Column(name = "qr_code_path")
|
||||
@ApiModelProperty(value = "二维码地址")
|
||||
private String qrCodePath;
|
||||
|
||||
@Column(name = "invitation_nums")
|
||||
@ApiModelProperty(value = "邀请数量")
|
||||
private String invitationNums;
|
||||
|
||||
@Column(name = "last_login_time")
|
||||
@ApiModelProperty(value = "最后登录时间")
|
||||
private Date lastLoginTime;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
|
||||
package com.baiye.modules.system.repository;
|
||||
|
||||
import com.baiye.modules.system.domain.FormUser;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date 2022-4-18
|
||||
*/
|
||||
public interface FormUserRepository extends JpaRepository<FormUser, Long>, JpaSpecificationExecutor<FormUser> {
|
||||
|
||||
|
||||
/**
|
||||
* 手机号码查询
|
||||
* @param phoneNumber
|
||||
* @return
|
||||
*/
|
||||
FormUser findByPhone(String phoneNumber);
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.baiye.modules.system.rest;
|
||||
|
||||
import com.baiye.http.CommonResponse;
|
||||
import com.baiye.modules.system.service.FormUserService;
|
||||
import com.baiye.modules.system.service.dto.UserLoginDTO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date : 2022/4/18
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "用户授权")
|
||||
@RequestMapping("/api/form/user")
|
||||
public class FormUserController {
|
||||
|
||||
private final FormUserService formUserService;
|
||||
|
||||
|
||||
@GetMapping("/verifyCode")
|
||||
@ApiOperation("更改手机号码发送验证码")
|
||||
public CommonResponse<String> getVerifyCode(@NotNull(message = "不能为空") String phone) {
|
||||
return formUserService.createRandomCodeByPhone(phone);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/login")
|
||||
@ApiOperation("账号登录")
|
||||
public CommonResponse<String> login(@Validated @RequestBody UserLoginDTO loginDTO) {
|
||||
return formUserService.userLogin(loginDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/userInfo")
|
||||
@ApiOperation("获取用户详情")
|
||||
public CommonResponse<Map<String, Object>> userInfo(@NotNull(message = "不能为空") String userToken) {
|
||||
return formUserService.getUserDetail(userToken);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.baiye.modules.system.service;
|
||||
|
||||
import com.baiye.http.CommonResponse;
|
||||
import com.baiye.modules.system.domain.FormUser;
|
||||
import com.baiye.modules.system.service.dto.UserLoginDTO;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date : 2022/4/18
|
||||
*/
|
||||
public interface FormUserService {
|
||||
/**
|
||||
* 手机号码生成验证码
|
||||
* @param phone
|
||||
* @return
|
||||
*/
|
||||
CommonResponse<String> createRandomCodeByPhone(String phone);
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param loginDTO
|
||||
* @return
|
||||
*/
|
||||
CommonResponse<String> userLogin(UserLoginDTO loginDTO);
|
||||
|
||||
/**
|
||||
* 获取用户详情
|
||||
* @param userToken
|
||||
* @return
|
||||
*/
|
||||
CommonResponse<Map<String, Object>> getUserDetail(String userToken);
|
||||
|
||||
|
||||
/**
|
||||
* id查找用户
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
FormUser findUserById(Long userId);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.baiye.modules.system.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date : 2022/4/18
|
||||
*/
|
||||
@Data
|
||||
public class DebtQueryResult {
|
||||
private String date;
|
||||
|
||||
private Integer num;
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baiye.modules.system.service.dto;
|
||||
|
||||
import com.baiye.model.base.BaseDTO;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @date 2019-03-29
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class FormUserDto extends BaseDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2035716596706011470L;
|
||||
|
||||
@ApiModelProperty(value = "id")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value = "二维码地址")
|
||||
private String qrCodePath;
|
||||
|
||||
@ApiModelProperty(value = "手机号码")
|
||||
private String phone;
|
||||
|
||||
@ApiModelProperty(value = "最后登录时间")
|
||||
private Date lastLoginTime;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.baiye.modules.system.service.dto;
|
||||
|
||||
import com.baiye.constant.DefaultNumberConstants;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date : 2022/4/18
|
||||
*/
|
||||
@Data
|
||||
public class UserLoginDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5500739143732174543L;
|
||||
|
||||
@NotNull(message = "手机号码不能为空")
|
||||
@Length(min = DefaultNumberConstants.ELEVEN_NUMBER,max = DefaultNumberConstants.ELEVEN_NUMBER)
|
||||
@ApiModelProperty("手机号码")
|
||||
private String phone;
|
||||
|
||||
|
||||
@NotNull(message = "验证码不能为空")
|
||||
@ApiModelProperty("验证码")
|
||||
private Integer verificationCode;
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package com.baiye.modules.system.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.baiye.constant.DefaultNumberConstants;
|
||||
import com.baiye.http.CommonResponse;
|
||||
import com.baiye.manager.UserTokenManager;
|
||||
import com.baiye.model.enums.ResponseCode;
|
||||
import com.baiye.modules.system.domain.FormUser;
|
||||
import com.baiye.modules.system.repository.DebtFormRepository;
|
||||
import com.baiye.modules.system.repository.FormUserRepository;
|
||||
import com.baiye.modules.system.service.FormUserService;
|
||||
import com.baiye.modules.system.service.dto.DebtQueryResult;
|
||||
import com.baiye.modules.system.service.dto.UserLoginDTO;
|
||||
import com.baiye.util.MobileUtil;
|
||||
import com.baiye.util.SmsUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date : 2022/4/18
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FormUserServiceImpl implements FormUserService {
|
||||
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
private final FormUserRepository formUserRepository;
|
||||
|
||||
private final DebtFormRepository debtFormRepository;
|
||||
|
||||
private final SmsUtil smsUtil;
|
||||
|
||||
|
||||
@Override
|
||||
public CommonResponse<String> createRandomCodeByPhone(String phone) {
|
||||
if (!MobileUtil.checkPhone(phone)) {
|
||||
return CommonResponse.createByErrorMessage(ResponseCode.PHONE_NUMBER_IS_INCORRECT.getDesc());
|
||||
}
|
||||
int randomNum = RandomUtil.randomInt
|
||||
(DefaultNumberConstants.ONE_HUNDRED_THOUSAND, DefaultNumberConstants.LESS_THAN_ONE_MILLION);
|
||||
smsUtil.sendAliYunSms(phone, "{\"code\":\"" + randomNum + "\"}");
|
||||
redisTemplate.opsForValue().set(phone, String.valueOf(randomNum), 300, TimeUnit.SECONDS);
|
||||
return CommonResponse.createBySuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public CommonResponse<String> userLogin(UserLoginDTO loginDTO) {
|
||||
|
||||
if (!NumberUtils.isParsable(loginDTO.getVerificationCode().toString())) {
|
||||
return CommonResponse.createByErrorMessage(ResponseCode.VERIFICATION_CODE_PARAMETER_ERROR.getDesc());
|
||||
}
|
||||
Integer verifyCode = loginDTO.getVerificationCode();
|
||||
String phone = loginDTO.getPhone();
|
||||
|
||||
String phoneVerifyCode = redisTemplate.opsForValue().get(phone);
|
||||
if (phoneVerifyCode == null || !phoneVerifyCode.equalsIgnoreCase(verifyCode.toString())) {
|
||||
return CommonResponse.createByErrorMessage(ResponseCode.VERIFICATION_NOT_EXIST_HAS_EXPIRED.getDesc());
|
||||
}
|
||||
// 删除验证码
|
||||
redisTemplate.delete(phone);
|
||||
FormUser formUser = formUserRepository.findByPhone(phone);
|
||||
// 已存在用户
|
||||
if (ObjectUtil.isNotNull(formUser)) {
|
||||
formUser.setLastLoginTime(DateUtil.date());
|
||||
// token
|
||||
String userToken =
|
||||
UserTokenManager.generateToken(formUser.getId());
|
||||
formUserRepository.save(formUser);
|
||||
return CommonResponse.createBySuccess(userToken);
|
||||
}
|
||||
// TODO 生成二维码
|
||||
formUser = new FormUser();
|
||||
formUser.setPhone(phone);
|
||||
formUser.setQrCodePath("");
|
||||
formUser.setLastLoginTime(DateUtil.date());
|
||||
FormUser user = formUserRepository.save(formUser);
|
||||
// token
|
||||
String userToken =
|
||||
UserTokenManager.generateToken(user.getId());
|
||||
return CommonResponse.createBySuccess(userToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Map<String, Object>> getUserDetail(String userToken) {
|
||||
Map<String, Object> map = new HashMap<>(DefaultNumberConstants.SIXTEEN_NUMBER);
|
||||
Long userId = UserTokenManager.getUserId(userToken);
|
||||
Date now = DateUtil.date();
|
||||
if (userId == null) {
|
||||
return CommonResponse.createByErrorMessage(ResponseCode.DECRYPTION_FAILED.getDesc());
|
||||
}
|
||||
FormUser formUser = findUserById(userId);
|
||||
if (formUser == null || StringUtils.isBlank(formUser.getQrCodePath())) {
|
||||
return CommonResponse.createByErrorMessage(ResponseCode.USER_INFORMATION_ERROR.getDesc());
|
||||
}
|
||||
|
||||
map.put("qrCode", formUser.getQrCodePath());
|
||||
// 提前一周
|
||||
Date dateTime = DateUtil.offsetWeek(now, DefaultNumberConstants.MINUS_ONE_NUMBER);
|
||||
String formatDate = DateUtil.formatDate(dateTime);
|
||||
Map<String, Object> debtFormRepositoryByDate =
|
||||
debtFormRepository.findByDate(formatDate, dateTime, now, userId);
|
||||
if (CollUtil.isNotEmpty(debtFormRepositoryByDate)) {
|
||||
List<DebtQueryResult> debtQueryResults = Convert.toList(DebtQueryResult.class, debtFormRepositoryByDate);
|
||||
map.put("dateResult", debtQueryResults);
|
||||
}
|
||||
return CommonResponse.createBySuccess(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormUser findUserById(Long userId) {
|
||||
return formUserRepository.findById(userId).orElseGet(FormUser::new);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
|
||||
package com.baiye.modules.system.service.mapstruct;
|
||||
|
||||
import com.baiye.model.base.BaseMapper;
|
||||
import com.baiye.modules.system.domain.FormUser;
|
||||
import com.baiye.modules.system.service.dto.FormUserDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* @author Enzo
|
||||
* @date 2022-4-18
|
||||
*/
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface FormUserMapper extends BaseMapper<FormUserDto, FormUser> {
|
||||
}
|
Loading…
Reference in New Issue