Commit 143b963a authored by xiaoguang.xu's avatar xiaoguang.xu

Merge remote-tracking branch 'origin' into baseEntity

parents 3399be45 6532c593
...@@ -172,7 +172,7 @@ public interface Constants { ...@@ -172,7 +172,7 @@ public interface Constants {
String USER_SESSION_CACHE = "user:session:"; String USER_SESSION_CACHE = "user:session:";
String USER_SESSION_ID_CACHE = "userid-sessionvalue:cache:"; String USER_SESSION_ID_CACHE = "userid-sessionvalue:cache:";
String USER_SESSION_KEY_SET = "userid-keys:set:"; String USER_SESSION_KEY_SET = "userid-keys:set:";
Long ONE_DAY = 24 * 60 * 60L; Long SESSION_VALID_TIME = 15 * 24 * 60 * 60L;
} }
interface UserAvatar { interface UserAvatar {
......
...@@ -87,6 +87,7 @@ public class RedisLockAspect { ...@@ -87,6 +87,7 @@ public class RedisLockAspect {
throw new ResubmissionException(); throw new ResubmissionException();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("获取锁失败:lockKey:{},exception:{}", lock.getLockKey(), e.getMessage()); log.warn("获取锁失败:lockKey:{},exception:{}", lock.getLockKey(), e.getMessage());
throw new ResubmissionException(); throw new ResubmissionException();
} finally { } finally {
......
...@@ -27,7 +27,6 @@ import cn.quantgroup.xyqb.service.user.UserCenterService; ...@@ -27,7 +27,6 @@ import cn.quantgroup.xyqb.service.user.UserCenterService;
import cn.quantgroup.xyqb.service.wechat.IWechatService; import cn.quantgroup.xyqb.service.wechat.IWechatService;
import cn.quantgroup.xyqb.session.XyqbSessionContextHolder; import cn.quantgroup.xyqb.session.XyqbSessionContextHolder;
import cn.quantgroup.xyqb.util.IpUtil; import cn.quantgroup.xyqb.util.IpUtil;
import cn.quantgroup.xyqb.util.MqUtils;
import cn.quantgroup.xyqb.util.PasswordUtil; import cn.quantgroup.xyqb.util.PasswordUtil;
import cn.quantgroup.xyqb.util.ValidationUtil; import cn.quantgroup.xyqb.util.ValidationUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
...@@ -185,25 +184,7 @@ public class UserController implements IBaseController { ...@@ -185,25 +184,7 @@ public class UserController implements IBaseController {
String verificationCode = successResult.getMsg(); String verificationCode = successResult.getMsg();
// 执行短信验证码检查 // 执行短信验证码检查
verifyPhoneAndCode(phoneNo, verificationCode); verifyPhoneAndCode(phoneNo, verificationCode);
User user = userService.findByPhoneWithCache(phoneNo); return userService.loginFast(channelId, appChannel, createdFrom, btRegisterChannelId, dimension, clickId, request, merchant, phoneNo);
if (user != null && !user.getEnable()) {
log.info("用户不存在,或者已经注销,phoneNo:{}", phoneNo);
return JsonResult.buildErrorStateResult("登录失败", null);
}
if (user == null) {
// Service层会负责发送注册消息到LoanVest
user = userRegisterService.register(phoneNo, channelId, createdFrom, appChannel, btRegisterChannelId, dimension);
if (user == null) {
throw new UserNotExistException("用户未找到");
}
//广点通转化注册 - 发送消息 - 方法内过滤
MqUtils.sendRegisterMessageForGdt(phoneNo, clickId);
}
if (!wechatRelateUserIfNecessary(user, request)) {
return JsonResult.buildErrorStateResult("登录时微信关联失败", null);
}
LoginProperties loginProperties = new LoginProperties("", 3, channelId, createdFrom, appChannel, merchant.getId(), merchant.getName());
return new JsonResult(sessionService.createSession(user, loginProperties));
} }
/** /**
......
...@@ -14,8 +14,6 @@ import cn.quantgroup.xyqb.util.ValidationUtil; ...@@ -14,8 +14,6 @@ import cn.quantgroup.xyqb.util.ValidationUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
...@@ -337,7 +335,7 @@ public class SmsController implements IBaseController { ...@@ -337,7 +335,7 @@ public class SmsController implements IBaseController {
return sendVerificationCode2New(phoneNo, randomCode, deviceId, true, appName, smsMerchant); return sendVerificationCode2New(phoneNo, randomCode, deviceId, true, appName, smsMerchant);
} }
private String getRandomCode(int count) { public String getRandomCode(int count) {
if(TechEnvironment.isPro()) { if(TechEnvironment.isPro()) {
return RandomStringUtils.random(count, RANDOM_CHARS); return RandomStringUtils.random(count, RANDOM_CHARS);
} }
...@@ -359,7 +357,7 @@ public class SmsController implements IBaseController { ...@@ -359,7 +357,7 @@ public class SmsController implements IBaseController {
* @param smsMerchant - 短信模板/类型 * @param smsMerchant - 短信模板/类型
* @return * @return
*/ */
private JsonResult sendVerificationCode2New(String phoneNo, String randomCode, String deviceId, boolean isApp, String appName, String smsMerchant) { public JsonResult sendVerificationCode2New(String phoneNo, String randomCode, String deviceId, boolean isApp, String appName, String smsMerchant) {
if (!ValidationUtil.validatePhoneNo(phoneNo)) { if (!ValidationUtil.validatePhoneNo(phoneNo)) {
return JsonResult.buildErrorStateResult("手机号格式有误", null); return JsonResult.buildErrorStateResult("手机号格式有误", null);
} }
......
...@@ -6,6 +6,7 @@ import cn.quantgroup.user.enums.*; ...@@ -6,6 +6,7 @@ import cn.quantgroup.user.enums.*;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.accessable.IpValidator; import cn.quantgroup.xyqb.aspect.accessable.IpValidator;
import cn.quantgroup.xyqb.controller.IBaseController; import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.controller.internal.user.resp.UserFullResp;
import cn.quantgroup.xyqb.entity.*; import cn.quantgroup.xyqb.entity.*;
import cn.quantgroup.xyqb.exception.UserNotExistException; import cn.quantgroup.xyqb.exception.UserNotExistException;
import cn.quantgroup.xyqb.model.*; import cn.quantgroup.xyqb.model.*;
...@@ -587,7 +588,7 @@ public class InnerController implements IBaseController { ...@@ -587,7 +588,7 @@ public class InnerController implements IBaseController {
* @param name - 姓名 * @param name - 姓名
* @param phoneNo - 手机号 * @param phoneNo - 手机号
* @param idNo - 身份证号 * @param idNo - 身份证号
* @return JsonResult<List < UserDetail>> * @return JsonResult<List < UserDetail>>
*/ */
@RequestMapping("/user_detail/search_list") @RequestMapping("/user_detail/search_list")
@ApiOperation(httpMethod = "POST", value = "按照姓名、份证号或手机号查询用户实名信息 - 精确查询,供客服用,不限制入参正确性") @ApiOperation(httpMethod = "POST", value = "按照姓名、份证号或手机号查询用户实名信息 - 精确查询,供客服用,不限制入参正确性")
...@@ -607,7 +608,7 @@ public class InnerController implements IBaseController { ...@@ -607,7 +608,7 @@ public class InnerController implements IBaseController {
* @param phoneNo - 手机号 * @param phoneNo - 手机号
* @param idNo - 身份证号 * @param idNo - 身份证号
* @param userName - 用户姓名 * @param userName - 用户姓名
* @return JsonResult<List < UserDetail>> * @return JsonResult<List < UserDetail>>
*/ */
@ApiOperation(httpMethod = "POST", value = "按照身份证号和手机号查询用户实名信息查询 - 模糊查询") @ApiOperation(httpMethod = "POST", value = "按照身份证号和手机号查询用户实名信息查询 - 模糊查询")
@RequestMapping("/user_detail/fuzzyQuery") @RequestMapping("/user_detail/fuzzyQuery")
...@@ -772,7 +773,7 @@ public class InnerController implements IBaseController { ...@@ -772,7 +773,7 @@ public class InnerController implements IBaseController {
} }
@ApiResponses({ @ApiResponses({
@ApiResponse(code = HttpStatus.SC_OK, message = "Nice!", responseContainer = "UserAssociationModel = {Long id, String uuid, String phoneNo, String idNo, String name, String gender, String marryStatus, String educationEnum, String occupationEnum, String qq, Long registerFrom, Long merchantId, List<AddressModel> addressList, List<ContactModel> contactList}"), @ApiResponse(code = HttpStatus.SC_OK, message = "Nice!", responseContainer = "UserAssociationModel = {Long id, String uuid, String phoneNo, String idNo, String name, String gender, String marryStatus, String educationEnum, String occupationEnum, String qq, Long registerFrom, Long merchantId, List<AddressModel> addressList, List<ContactModel> contactList}"),
@ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Invalid params supplied", response = cn.quantgroup.xyqb.model.ApiResponse.class), @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Invalid params supplied", response = cn.quantgroup.xyqb.model.ApiResponse.class),
@ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "User not found", response = cn.quantgroup.xyqb.model.ApiResponse.class) @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "User not found", response = cn.quantgroup.xyqb.model.ApiResponse.class)
}) })
...@@ -793,6 +794,17 @@ public class InnerController implements IBaseController { ...@@ -793,6 +794,17 @@ public class InnerController implements IBaseController {
return JsonResult.buildSuccessResult("", bean); return JsonResult.buildSuccessResult("", bean);
} }
/**
* 查询用户全量信息 for koala
*
* @param userId 用户id
* @return
*/
@GetMapping("/user-full/search/userId")
public JsonResult<UserFullResp> findUserFullSearchByUserId(@RequestParam Long userId) {
return JsonResult.buildSuccessResultGeneric(userService.findUserFullSearchByUserId(userId));
}
@RequestMapping("/user-association/search/phone") @RequestMapping("/user-association/search/phone")
public JsonResult findUserAssociationByPhone(String phoneNo) { public JsonResult findUserAssociationByPhone(String phoneNo) {
UserDetail userDetail = userDetailService.findByPhoneNo(phoneNo); UserDetail userDetail = userDetailService.findByPhoneNo(phoneNo);
...@@ -1090,7 +1102,8 @@ public class InnerController implements IBaseController { ...@@ -1090,7 +1102,8 @@ public class InnerController implements IBaseController {
List<Contact> contactList = null; List<Contact> contactList = null;
// 目前对空白字符串和null值容错,因是api调用,不考虑对非法格式容错(会阻断注册) // 目前对空白字符串和null值容错,因是api调用,不考虑对非法格式容错(会阻断注册)
if (StringUtils.isNotBlank(contacts)) { if (StringUtils.isNotBlank(contacts)) {
contactList = JSONObject.parseObject(contacts, new TypeReference<List<Contact>>() {}); contactList = JSONObject.parseObject(contacts, new TypeReference<List<Contact>>() {
});
for (Contact contact : contactList) { for (Contact contact : contactList) {
contact.setRelation(contact.getRelation() == null ? Relation.OTHER : contact.getRelation()); contact.setRelation(contact.getRelation() == null ? Relation.OTHER : contact.getRelation());
Tuple<String, Boolean> stringBooleanTuple = contact.validAndResult(); Tuple<String, Boolean> stringBooleanTuple = contact.validAndResult();
...@@ -1305,9 +1318,9 @@ public class InnerController implements IBaseController { ...@@ -1305,9 +1318,9 @@ public class InnerController implements IBaseController {
public JsonResult resetPassword(@RequestParam("phone") String phone, @RequestParam(required = false) String password) { public JsonResult resetPassword(@RequestParam("phone") String phone, @RequestParam(required = false) String password) {
if (ValidationUtil.validatePhoneNo(phone)) { if (ValidationUtil.validatePhoneNo(phone)) {
// 默认重置的密码是123456 // 默认重置的密码是123456
if(StringUtils.isBlank(password)){ if (StringUtils.isBlank(password)) {
password = PasswordUtil.PASSWORD_DEFAULT; password = PasswordUtil.PASSWORD_DEFAULT;
}else if (!ValidationUtil.validatePassword(password)) { } else if (!ValidationUtil.validatePassword(password)) {
return JsonResult.buildErrorStateResult(PasswordUtil.TOAST_MSG, null); return JsonResult.buildErrorStateResult(PasswordUtil.TOAST_MSG, null);
} }
try { try {
......
...@@ -66,8 +66,11 @@ public class UserApiController { ...@@ -66,8 +66,11 @@ public class UserApiController {
@ApiOperation(notes = "检查token是否有效,如果有效,可选择是否延续生命期(延续后有效期24Hour)", value = "Check token and then prolong session", nickname = "checkToken") @ApiOperation(notes = "检查token是否有效,如果有效,可选择是否延续生命期(延续后有效期24Hour)", value = "Check token and then prolong session", nickname = "checkToken")
@IpValidator @IpValidator
@RequestMapping(value = "/valid/{token}", method = RequestMethod.POST) @RequestMapping(value = "/valid/{token}", method = RequestMethod.POST)
public JsonResult checkToken(@ApiParam(value = "sid,session的id", required = true) @PathVariable("token") String token, public JsonResult checkToken(@ApiParam(value = "sid,session的id", required = true)
@ApiParam(value = "是否延续生命期,可选参数,默认为: false - 不延续") @RequestParam(name = "prolong", required = false, defaultValue = "false") Boolean prolong) { @PathVariable("token") String token,
@ApiParam(value = "是否延续生命期,可选参数,默认为: false - 不延续")
@RequestParam(name = "prolong", required = false, defaultValue = "false") Boolean prolong,
@RequestParam(name = "prolongTime", required = false, defaultValue = "86400") Long prolongTime) {
if (Objects.isNull(token) || !ValidationUtil.validateToken(token)) { if (Objects.isNull(token) || !ValidationUtil.validateToken(token)) {
return JsonResult.buildErrorStateResult("token invalid", token); return JsonResult.buildErrorStateResult("token invalid", token);
} }
...@@ -87,7 +90,7 @@ public class UserApiController { ...@@ -87,7 +90,7 @@ public class UserApiController {
} else { } else {
/* 延续session生命期 */ /* 延续session生命期 */
try { try {
sessionService.persistSession(sessionStruct.getSid(), sessionStruct.getValues()); sessionService.persistSession(sessionStruct.getSid(), sessionStruct.getValues(), prolongTime);
log.info("延续token:[{}]生命期,result:[{}]", token, true); log.info("延续token:[{}]生命期,result:[{}]", token, true);
} finally { } finally {
XyqbSessionContextHolder.releaseSession(); XyqbSessionContextHolder.releaseSession();
......
...@@ -6,10 +6,20 @@ import cn.quantgroup.user.enums.MaritalStatus; ...@@ -6,10 +6,20 @@ import cn.quantgroup.user.enums.MaritalStatus;
import cn.quantgroup.user.enums.OccupationEnum; import cn.quantgroup.user.enums.OccupationEnum;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.limit.PasswordFreeAccessValidator; import cn.quantgroup.xyqb.aspect.limit.PasswordFreeAccessValidator;
import cn.quantgroup.xyqb.entity.*;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.user.*;
import cn.quantgroup.xyqb.aspect.lock.RedisLock; import cn.quantgroup.xyqb.aspect.lock.RedisLock;
import cn.quantgroup.xyqb.entity.Address;
import cn.quantgroup.xyqb.entity.Contact;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.UserAttached;
import cn.quantgroup.xyqb.entity.UserDetail;
import cn.quantgroup.xyqb.entity.UserExtInfo;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.user.IAddressService;
import cn.quantgroup.xyqb.service.user.IContactService;
import cn.quantgroup.xyqb.service.user.IUserDetailService;
import cn.quantgroup.xyqb.service.user.IUserExtInfoService;
import cn.quantgroup.xyqb.service.user.IUserService;
import cn.quantgroup.xyqb.service.user.UserCenterService;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
...@@ -17,6 +27,9 @@ import lombok.extern.slf4j.Slf4j; ...@@ -17,6 +27,9 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
...@@ -46,6 +59,30 @@ public class UserCenterController { ...@@ -46,6 +59,30 @@ public class UserCenterController {
@Autowired @Autowired
private IUserService userService; private IUserService userService;
@GetMapping("/attach")
public JsonResult queryUserAttach(Long userId) {
if (userId == null) {
return JsonResult.buildErrorStateResult("用户 ID 不能为空", null);
}
UserAttached userAttached = userCenterService.searchUserAttachedByUserId(userId);
return JsonResult.buildSuccessResultGeneric(userAttached);
}
@PostMapping("/attach/list")
public JsonResult queryUserAttachList(@RequestBody List<Long> userIds) {
if (CollectionUtils.isEmpty(userIds)) {
return JsonResult.buildErrorStateResult("用户 ID 不能为空", null);
}
int size = 500;
if (userIds.size() > size) {
return JsonResult.buildErrorStateResult("超出最大条数限制" + size, null);
}
List<UserAttached> userAttachedList = userCenterService.searchUserAttachedListByUserId(userIds);
return JsonResult.buildSuccessResultGeneric(userAttachedList);
}
/** /**
* 根据用户手机号查询昵称. * 根据用户手机号查询昵称.
* *
......
package cn.quantgroup.xyqb.controller.internal.user.req;
import lombok.Data;
@Data
public class AttachListReq {
private String userIds;
}
package cn.quantgroup.xyqb.controller.internal.user.resp;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserFullResp {
/**
* userId : 1396263648485684
* gender : 2
* idType : 6
* idNo : aliqua esse
* name : sunt consectetur nisi
* phoneNo : non consectetur dolore ea
* uuid : qui dolor ipsum minim
* incomeRange : 1
* incomeType : 2
* qq : exercitation eu
* email : s
* hasSocialSecurity : 0
* hasCar : 1
* education : 3
* occupation : 7
* hasCreditCard : 1
* hasHouse : 1
* marryStatus : 1
*/
private Long userId;
private Integer gender;
private Integer idType;
private String idNo;
private String name;
private String phoneNo;
private String uuid;
private Integer incomeRange;
private Integer incomeType;
private String qq;
private String email;
private Integer hasSocialSecurity;
private Integer hasCar;
private Integer education;
private Integer occupation;
private Integer hasCreditCard;
private Integer hasHouse;
private Integer marryStatus;
/**
* districtCode : do adipisicing minim sit deserunt
* city : enim ipsum voluptate do
* cityCode : voluptate
* province : mollit
* provinceCode : sint culpa in laborum
* address : ut nostrud incididunt
* district : incididunt ullamco dolore in
*/
private Long districtCode;
private String city;
private Long cityCode;
private String province;
private Long provinceCode;
private String address;
private String district;
private List<Contact> contacts;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Contact {
/**
* userId : 4069695050527240
* name : ex reprehenderit dolore dol
* mobile : fugiat quis ad veniam dolor
* relation : 1
*/
private Long userId;
private String name;
private String mobile;
private Integer relation;
}
}
package cn.quantgroup.xyqb.controller.middleoffice;
public class UserBaseInfo {
private String channelId;
private String appChannel;
private String createdFrom;
}
package cn.quantgroup.xyqb.controller.middleoffice.common;
import cn.quantgroup.xyqb.entity.User;
import org.springframework.stereotype.Component;
/**
* 无验证策略
*/
@Component
public class FreeVerifyStrategy implements IVerifyStrategy {
@Override
public VerifyTypeEnum strategyName() {
return VerifyTypeEnum.free;
}
@Override
public void verify(User user, String verify) {
}
}
package cn.quantgroup.xyqb.controller.middleoffice.common;
import cn.quantgroup.xyqb.entity.User;
public interface IVerifyStrategy {
VerifyTypeEnum strategyName();
void verify(User user, String verify);
}
package cn.quantgroup.xyqb.controller.middleoffice.common;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.exception.DataException;
import cn.quantgroup.xyqb.util.PasswordUtil;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* 密码校验策略
*/
@Component
public class PwdVerifyStrategy implements IVerifyStrategy {
@Override
public VerifyTypeEnum strategyName() {
return VerifyTypeEnum.pwd;
}
@Override
public void verify(User user, String verify) {
String password = user.getPassword();
if (Objects.equals(password, PasswordUtil.MD5WithSalt(verify))) {
return;
}
//todo 自定义异常
throw new DataException("用户名或密码错误");
}
}
package cn.quantgroup.xyqb.controller.middleoffice.common;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.exception.VerificationCodeErrorException;
import cn.quantgroup.xyqb.service.sms.ISmsService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 基于短信策略的验证
*/
@Component
public class SmsVerifyStrategy implements IVerifyStrategy {
@Resource
private ISmsService smsService;
@Override
public VerifyTypeEnum strategyName() {
return VerifyTypeEnum.sms;
}
@Override
public void verify(User user, String verify) {
String phoneNo = user.getPhoneNo();
boolean smsValid = smsService.verifyPhoneAndCode(phoneNo, verify);
if (smsValid) {
return;
}
boolean needResend = smsService.needResendCode(phoneNo);
if (needResend) {
throw new VerificationCodeErrorException("短信验证码超时");
}
throw new VerificationCodeErrorException("短信验证码错误");
}
}
package cn.quantgroup.xyqb.controller.middleoffice.common;
import cn.quantgroup.xyqb.util.ApplicationContextHolder;
import java.util.HashMap;
import java.util.Map;
public class VerifyStrategyFactory {
private static final Map<VerifyTypeEnum, IVerifyStrategy> strategiesMap = new HashMap<>();
static {
//cache
Map<String, IVerifyStrategy> beansOfType = ApplicationContextHolder.getBeansOfType(IVerifyStrategy.class);
beansOfType.values().forEach(strategy -> strategiesMap.put(strategy.strategyName(), strategy));
}
public static IVerifyStrategy get(VerifyTypeEnum verifyTypeEnum) {
return strategiesMap.get(verifyTypeEnum);
}
}
package cn.quantgroup.xyqb.controller.middleoffice.common;
import lombok.Getter;
/**
* 验证类型
*/
@Getter
public enum VerifyTypeEnum {
sms("短信"),
pwd("密码"),
free("无认证");
private String desc;
VerifyTypeEnum(String desc) {
this.desc = desc;
}
}
package cn.quantgroup.xyqb.controller.middleoffice.common.image;
import cn.quantgroup.xyqb.model.ClientType;
import cn.quantgroup.xyqb.service.captcha.IGeetestCaptchaService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 极验验证码认证
*/
@Component
public class GeeVerifyStrategy implements IImageVerifyStrategy {
@Resource
private IGeetestCaptchaService geetestCaptchaService;
@Override
public ImageVerifyTypeEnum strategyName() {
return ImageVerifyTypeEnum.gt;
}
@Override
public boolean verify(ImageDTO image) {
//todo param valid
return geetestCaptchaService.validGeetestCaptcha(image.getUniqueKey(), image.getUserIp(),
ClientType.valueByName(image.getClientType()), image.getChallenge(),
image.getValidate(), image.getSeccode());
}
}
package cn.quantgroup.xyqb.controller.middleoffice.common.image;
public interface IImageVerifyStrategy {
ImageVerifyTypeEnum strategyName();
boolean verify(ImageDTO image);
}
package cn.quantgroup.xyqb.controller.middleoffice.common.image;
import lombok.Data;
@Data
public class ImageDTO {
private String challenge;
private String uniqueKey;
private String clientType;
private String validate;
private String seccode;
private String userIp;
private String captchaId;
private String captchaValue;
}
package cn.quantgroup.xyqb.controller.middleoffice.common.image;
import cn.quantgroup.xyqb.util.ApplicationContextHolder;
import java.util.HashMap;
import java.util.Map;
public class ImageVerifyStrategyFactory {
private static final Map<ImageVerifyTypeEnum, IImageVerifyStrategy> strategiesMap = new HashMap<>();
static {
//cache
Map<String, IImageVerifyStrategy> beansOfType = ApplicationContextHolder.getBeansOfType(IImageVerifyStrategy.class);
beansOfType.values().forEach(strategy -> strategiesMap.put(strategy.strategyName(), strategy));
}
public static IImageVerifyStrategy get(ImageVerifyTypeEnum verifyTypeEnum) {
return strategiesMap.get(verifyTypeEnum);
}
}
package cn.quantgroup.xyqb.controller.middleoffice.common.image;
public enum ImageVerifyTypeEnum {
gt,
qg
}
package cn.quantgroup.xyqb.controller.middleoffice.common.image;
import cn.quantgroup.xyqb.service.captcha.IQuantgroupCaptchaService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 量化派验证码认证
*/
@Component
public class QgVerifyStrategy implements IImageVerifyStrategy {
@Resource
private IQuantgroupCaptchaService quantgroupCaptchaService;
@Override
public ImageVerifyTypeEnum strategyName() {
return ImageVerifyTypeEnum.qg;
}
@Override
public boolean verify(ImageDTO image) {
return quantgroupCaptchaService.validQuantgroupCaptcha(image.getCaptchaId(), image.getCaptchaValue());
}
}
package cn.quantgroup.xyqb.controller.middleoffice.image;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.controller.middleoffice.common.image.ImageDTO;
import cn.quantgroup.xyqb.controller.middleoffice.common.image.ImageVerifyStrategyFactory;
import cn.quantgroup.xyqb.controller.middleoffice.common.image.ImageVerifyTypeEnum;
import cn.quantgroup.xyqb.model.ClientType;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.captcha.IGeetestCaptchaService;
import cn.quantgroup.xyqb.service.captcha.IQuantgroupCaptchaService;
import org.apache.commons.codec.digest.Md5Crypt;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
/**
* 图形验证码
*/
@RestController
@RequestMapping("/middle_office/image")
public class ImageController {
@Resource
private IGeetestCaptchaService geetestCaptchaService;
@Resource
private IQuantgroupCaptchaService quantgroupCaptchaService;
@Value("${geetest.close:false}")
private Boolean geetestClose;
@GetMapping
public JsonResult image(String userIp, String clientType, String phoneNo) {
Locale locale = Locale.CHINA;
String markId = Md5Crypt.md5Crypt(phoneNo.getBytes());
Map<String, String> data = new HashMap<>();
Map<String, String> imgMap = null;
// 优先获取极验
if (!geetestClose) {
imgMap = geetestCaptchaService.fetchGeetestCaptcha(markId, userIp, ClientType.valueByName(clientType));
data.put(Constants.VERIFY_PARAM, Constants.VERIFY_TYPE_GT);
}
// 备选方案:量化派图形验证码
if (Objects.isNull(imgMap) || imgMap.isEmpty()) {
imgMap = quantgroupCaptchaService.fetchQuantgroupCaptcha(locale);
data.put(Constants.VERIFY_PARAM, Constants.VERIFY_TYPE_QG);
}
// 返回结果
if (Objects.isNull(imgMap) || imgMap.isEmpty()) {
return JsonResult.buildErrorStateResult("获取验证码失败", "");
}
// 填充数据并返回
data.putAll(imgMap);
data.put(Constants.GT_UNIQUE_KEY, markId);
return JsonResult.buildSuccessResultGeneric(data);
}
/**
* 验证图形验证码
*
* @return
*/
@PostMapping("/verify/{type}")
public JsonResult verifyGT(@PathVariable ImageVerifyTypeEnum type, @RequestBody ImageDTO imageDTO) {
boolean verify = ImageVerifyStrategyFactory.get(type).verify(imageDTO);
if (verify) {
return JsonResult.buildSuccessResult();
}
return JsonResult.buildErrorStateResult("验证码错误", null);
}
}
package cn.quantgroup.xyqb.controller.middleoffice.image;
import lombok.Data;
@Data
public class ImageVo {
private String verifyType;
private String uniqueKey;
}
package cn.quantgroup.xyqb.controller.middleoffice.login;
import cn.quantgroup.xyqb.controller.middleoffice.common.VerifyTypeEnum;
public interface ILoginModule {
LoginVo login(VerifyTypeEnum type, Boolean reg,
Long channelId, String appChannel,
String wechatOpenId, String phoneNo,
String verify);
Boolean modifyPwd(VerifyTypeEnum type, String phoneNo, String password, String verify);
}
package cn.quantgroup.xyqb.controller.middleoffice.login;
import cn.quantgroup.xyqb.controller.middleoffice.common.VerifyTypeEnum;
import cn.quantgroup.xyqb.model.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 注册与登陆
*/
@Slf4j
@RestController
@RequestMapping("/middle_office/login")
public class LoginController {
@Resource
private ILoginModule loginModule;
@PostMapping("/{type}")
public JsonResult loginFreeAuto(@PathVariable VerifyTypeEnum type,
@RequestParam(required = false, defaultValue = "false") Boolean autoReg,
@RequestParam(required = false, defaultValue = "1") Long channelId,
@RequestParam(required = false) String appChannel,
@RequestParam(required = false) String wechatOpenId,
@RequestParam String phoneNo,
@RequestParam(required = false) String verify
) {
LoginVo login = loginModule.login(type, autoReg, channelId, appChannel, wechatOpenId, phoneNo, verify);
return JsonResult.buildSuccessResultGeneric(login);
}
@PatchMapping("/modify/pwd")
public JsonResult modifyByPwd(String phoneNo, String password, String passwordNew) {
loginModule.modifyPwd(VerifyTypeEnum.pwd, phoneNo, password, passwordNew);
return JsonResult.buildSuccessResult();
}
@PatchMapping("/modify/sms")
public JsonResult modifyBySms(String phoneNo, String password, String verificationCode) {
loginModule.modifyPwd(VerifyTypeEnum.sms, phoneNo, password, verificationCode);
return JsonResult.buildSuccessResult();
}
}
package cn.quantgroup.xyqb.controller.middleoffice.login;
import cn.quantgroup.xyqb.controller.middleoffice.common.VerifyStrategyFactory;
import cn.quantgroup.xyqb.controller.middleoffice.common.VerifyTypeEnum;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.exception.DataException;
import cn.quantgroup.xyqb.model.AuthBean;
import cn.quantgroup.xyqb.model.LoginProperties;
import cn.quantgroup.xyqb.service.register.IUserRegisterService;
import cn.quantgroup.xyqb.service.session.ISessionService;
import cn.quantgroup.xyqb.service.user.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 面向服务的聚合模块。
*/
@Slf4j
@Service
public class LoginModule implements ILoginModule {
@Resource
private IUserService userService;
@Resource
private IUserRegisterService userRegisterService;
@Resource
private ISessionService sessionService;
@Override
public LoginVo login(VerifyTypeEnum type, Boolean reg, Long channelId, String appChannel, String wechatOpenId, String phoneNo, String verify) {
User user = userService.findByPhoneInDb(phoneNo);
boolean autoReg = reg && type != VerifyTypeEnum.pwd;
//auto reg
if (user == null) {
if (autoReg) {
log.info("用户自动注册:{}", phoneNo);
user = userRegisterService.register(channelId, phoneNo);
} else {
//todo 自定义异常
throw new DataException("用户名或密码不正确");
}
}
if (!user.getEnable()) {
//用户不存在
log.info("用户尝试登录,已注销:{}", phoneNo);
//todo 自定义异常
throw new DataException("用户名或密码不正确");
}
//验证
VerifyStrategyFactory.get(type).verify(user, verify);
LoginProperties loginProperties = LoginProperties.builder()
.createdFrom(user.getRegisteredFrom())
.appChannel(appChannel)
.channelId(channelId)
.build();
AuthBean session = sessionService.createSession(user, loginProperties);
return LoginVo.builder()
.hasPassword(user.getHasPassword())
.phoneNo(phoneNo)
.token(session.getToken())
.userId(user.getId())
.uuid(user.getUuid()).build();
}
@Override
public Boolean modifyPwd(VerifyTypeEnum type, String phoneNo, String password, String verify) {
User user = userService.findByPhoneInDb(phoneNo);
if (user == null) {
//todo 自定义异常
throw new DataException("用户不存在");
}
VerifyStrategyFactory.get(type).verify(user, verify);
userService.resetPassword(phoneNo, password);
return true;
}
}
package cn.quantgroup.xyqb.controller.middleoffice.login;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class LoginVo {
private Long userId;
private String phoneNo;
private String token;
private String uuid;
private Boolean hasPassword;
}
/**
* 中台相关模块。
* login 注册登陆
* image 图形验证码
* sms 短信
* user 用户信息
* userdetail 用户实名信息
* wx 微信
*/
package cn.quantgroup.xyqb.controller.middleoffice;
\ No newline at end of file
package cn.quantgroup.xyqb.controller.middleoffice.sms;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.controller.middleoffice.common.image.ImageDTO;
import cn.quantgroup.xyqb.controller.middleoffice.common.image.ImageVerifyStrategyFactory;
import cn.quantgroup.xyqb.controller.middleoffice.common.image.ImageVerifyTypeEnum;
import cn.quantgroup.xyqb.model.JsonResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 短信
*/
@RestController("middleSmsController")
@RequestMapping("/middle_office/sms")
public class SmsController {
@Resource
private cn.quantgroup.xyqb.controller.external.sms.SmsController smsController;
@GetMapping
public JsonResult sms(SmsDTO sms,
ImageVerifyTypeEnum verifyType,
ImageDTO imageDTO) {
boolean verify = ImageVerifyStrategyFactory.get(verifyType).verify(imageDTO);
if (!verify) {
return JsonResult.buildErrorStateResult("验证码错误", null);
}
//todo service
String randomCode = smsController.getRandomCode(Constants.SMS_CODE_LEN_4);
return smsController.sendVerificationCode2New(
sms.getPhoneNo(), randomCode,
sms.getDeviceId(), false,
sms.getAppName(), sms.getSmsMerchant());
}
@PostMapping("/resetpwd")
public JsonResult resetpwd(SmsDTO sms,
ImageVerifyTypeEnum verifyType,
ImageDTO imageDTO) {
boolean verify = ImageVerifyStrategyFactory.get(verifyType).verify(imageDTO);
if (!verify) {
return JsonResult.buildErrorStateResult("验证码错误", null);
}
//todo 与 sms 不同的是,smsMerchant 不同,代表不同的模板。需要优化。。。
String randomCode = smsController.getRandomCode(Constants.SMS_CODE_LEN_4);
return smsController.sendVerificationCode2New(
sms.getPhoneNo(), randomCode,
sms.getDeviceId(), false,
sms.getAppName(), sms.getSmsMerchant());
}
}
package cn.quantgroup.xyqb.controller.middleoffice.sms;
import lombok.Data;
@Data
public class SmsDTO {
private String phoneNo;
private String deviceId;
private String appName;
private String smsMerchant;
}
package cn.quantgroup.xyqb.controller.middleoffice.user;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.user.IUserService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 用户信息
*/
@RestController("middleUserController")
@RequestMapping("/middle_office/user")
public class UserController {
@Resource
private IUserService userService;
@PutMapping("/enable/{userId}")
public JsonResult enable(@PathVariable Long userId) {
User user = userService.findById(userId);
if (user == null) {
//todo 用户不存在,怎么处理
return JsonResult.buildSuccessResult();
}
user.setEnable(true);
userService.saveUser(user);
return JsonResult.buildSuccessResult();
}
@PutMapping("/disable/{userId}")
public JsonResult disable(@PathVariable Long userId) {
User user = userService.findById(userId);
if (user == null) {
//todo 用户不存在,怎么处理
return JsonResult.buildSuccessResult();
}
user.setEnable(false);
//清理缓存
userService.saveUser(user);
return JsonResult.buildSuccessResult();
}
@GetMapping("/userId/{userId}")
public JsonResult user(@PathVariable Long userId) {
User user = userService.findById(userId);
//TODO convert to userVO
return JsonResult.buildSuccessResultGeneric(user);
}
@GetMapping("/phoneNo/{phoneNo}")
public JsonResult user(@PathVariable String phoneNo) {
User user = userService.findByPhoneInDb(phoneNo);
//TODO convert to userVO
return JsonResult.buildSuccessResultGeneric(user);
}
@GetMapping("/uuid/{uuid}")
public JsonResult uuid(@PathVariable String uuid) {
User user = userService.findByUuidWithCache(uuid);
//TODO convert to userVO
return JsonResult.buildSuccessResultGeneric(user);
}
}
package cn.quantgroup.xyqb.controller.middleoffice.userdetail;
import cn.quantgroup.xyqb.controller.middleoffice.userdetail.req.UserDetailReq;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.UserDetail;
import cn.quantgroup.xyqb.model.IdCardInfo;
import cn.quantgroup.xyqb.model.IdType;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.auth.IIdCardService;
import cn.quantgroup.xyqb.service.user.IUserDetailService;
import cn.quantgroup.xyqb.service.user.IUserService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.sql.Timestamp;
/**
* 用户实名信息
*/
@RestController("middleUserDetailController")
@RequestMapping("/middle_office/user_detail")
public class UserDetailController {
@Resource
private IUserDetailService userDetailService;
@Resource
private IUserService userService;
@Resource
private IIdCardService idCardService;
/**
* 修改用户实名信息
*
* @param userId
* @param userDetailReq
* @return
*/
@PutMapping("/{userId}")
public JsonResult update(@PathVariable Long userId,
@Valid @RequestBody UserDetailReq userDetailReq) {
UserDetail userDetail = userDetailService.findByUserId(userId);
if (userDetail == null) {
return save(userId, userDetailReq);
}
//更新
userDetail.setName(userDetailReq.getName());
userDetail.setIdNo(userDetailReq.getIdNo());
userDetail.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
userDetail = userDetailService.saveUserDetail(userDetail);
return JsonResult.buildSuccessResultGeneric(userDetail);
}
/**
* 保存用户实名信息
*
* @param userId
* @param userDetailReq
* @return
*/
@PostMapping("/{userId}")
public JsonResult save(@PathVariable Long userId,
@Valid @RequestBody UserDetailReq userDetailReq) {
UserDetail userDetail = userDetailService.findByUserId(userId);
if (userDetail != null) {
return JsonResult.buildSuccessResultGeneric(userDetail);
}
User user = userService.findById(userId);
IdCardInfo idCardInfo = idCardService.getIdCardInfo(userDetailReq.getIdNo());
Timestamp now = new Timestamp(System.currentTimeMillis());
userDetail = new UserDetail();
userDetail.setUserId(userId);
userDetail.setName(userDetailReq.getName());
userDetail.setPhoneNo(user.getPhoneNo());
userDetail.setIdNo(userDetailReq.getIdNo());
userDetail.setIdType(IdType.ID_CARD);
userDetail.setGender(idCardInfo.getGender());
userDetail.setCreatedAt(now);
userDetail.setUpdatedAt(now);
userDetail = userDetailService.saveUserDetail(userDetail);
return JsonResult.buildSuccessResultGeneric(userDetail);
}
/**
* 根据用户 ID,查询实名信息
*
* @param userId
* @return
*/
@GetMapping("/userId/{userId}")
public JsonResult query(@PathVariable Long userId) {
UserDetail userDetail = userDetailService.findByUserId(userId);
return JsonResult.buildSuccessResultGeneric(userDetail);
}
/**
* 根据手机号,查询实名信息
*
* @param phoneNo
* @return
*/
@GetMapping("/phoneNo/{phoneNo}")
public JsonResult query(@PathVariable String phoneNo) {
UserDetail userDetail = userDetailService.findByPhoneNo(phoneNo);
return JsonResult.buildSuccessResultGeneric(userDetail);
}
}
package cn.quantgroup.xyqb.controller.middleoffice.userdetail.req;
import cn.quantgroup.xyqb.validator.ChineseName;
import cn.quantgroup.xyqb.validator.IdCard;
import lombok.Data;
@Data
public class UserDetailReq {
@ChineseName
private String name;
@IdCard
private String idNo;
}
package cn.quantgroup.xyqb.controller.middleoffice.userext;
import cn.quantgroup.xyqb.controller.middleoffice.userext.req.UserExtReq;
import cn.quantgroup.xyqb.entity.Address;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.UserExtInfo;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.user.*;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
/**
* 用户扩展信息
*/
@RestController
@RequestMapping("/middle_office/user/ext")
public class UserExtController {
@Resource
private IUserExtInfoService userExtInfoService;
@Resource
private IContactService contactService;
@Resource
private IUserDetailService userDetailService;
@Resource
private IAddressService addressService;
@Resource
private IUserService userService;
//todo 保存失败的各种场景。
@PutMapping("/{userId}")
public JsonResult ext(@PathVariable Long userId, @RequestBody UserExtReq userExtReq) {
if (userExtReq.getEmail() != null) {
userDetailService.updateUserEmail(userId, userExtReq.getEmail());
}
if (userExtReq.getQq() != null) {
userDetailService.updateUserQq(userId, userExtReq.getQq());
}
if (CollectionUtils.isNotEmpty(userExtReq.getContacts())) {
contactService.save(userId, userExtReq.getContacts());
}
if (userExtReq.getAddress() != null) {
Address address = addressService.findByUserId(userId);
if (address != null) {
userExtReq.getAddress().setId(address.getId());
}
userExtReq.getAddress().setUserId(userId);
addressService.save(userExtReq.getAddress());
}
if (userExtReq.getExtInfo() != null) {
UserExtInfo extInfo = userExtInfoService.findByUserId(userId);
if (extInfo != null) {
Long id = extInfo.getId();
userExtReq.getExtInfo().setId(id);
}
userExtReq.getExtInfo().setUserId(userId);
userExtInfoService.save(userExtReq.getExtInfo());
}
return JsonResult.buildSuccessResult();
}
@GetMapping("/userId/{userId}")
public JsonResult query(@PathVariable Long userId,
@RequestParam(defaultValue = "false") Boolean address,
@RequestParam(defaultValue = "false") Boolean contacts,
@RequestParam(defaultValue = "false") Boolean extInfo) {
Map<String, Object> result = new HashMap<>();
if (address) {
result.put("address", addressService.findByUserId(userId));
}
if (contacts) {
result.put("contacts", contactService.findByUserId(userId, true));
}
if (extInfo) {
result.put("extInfo", userExtInfoService.findByUserId(userId));
}
return JsonResult.buildSuccessResultGeneric(result);
}
@GetMapping("/phoneNo/{phoneNo}")
public JsonResult query(@PathVariable String phoneNo,
@RequestParam(defaultValue = "false") Boolean address,
@RequestParam(defaultValue = "false") Boolean contacts,
@RequestParam(defaultValue = "false") Boolean extInfo) {
User user = userService.findByPhoneWithCache(phoneNo);
if (user == null) {
return JsonResult.buildSuccessResult();
}
Long userId = user.getId();
//todo duplicated
Map<String, Object> result = new HashMap<>();
if (address) {
result.put("address", addressService.findByUserId(userId));
}
if (contacts) {
result.put("contacts", contactService.findByUserId(userId, true));
}
if (extInfo) {
result.put("extInfo", userExtInfoService.findByUserId(userId));
}
return JsonResult.buildSuccessResultGeneric(result);
}
}
package cn.quantgroup.xyqb.controller.middleoffice.userext.req;
import cn.quantgroup.xyqb.entity.Address;
import cn.quantgroup.xyqb.entity.Contact;
import cn.quantgroup.xyqb.entity.UserExtInfo;
import lombok.Data;
import java.util.List;
@Data
public class UserExtReq {
private List<Contact> contacts;
private Address address;
private UserExtInfo extInfo;
private String email;
private String qq;
}
package cn.quantgroup.xyqb.controller.middleoffice.wx;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.service.wechat.IWechatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 微信
*/
@Slf4j
@RestController
@RequestMapping("/middle_office/wx")
public class WxController {
@Resource
private IWechatService wechatService;
@GetMapping("/userId/{userId}")
public JsonResult openId(@PathVariable Long userId) {
WechatUserInfo wechatUserInfo = wechatService.queryByUserId(userId);
if (wechatUserInfo == null) {
return JsonResult.buildSuccessResult();
}
return JsonResult.buildSuccessResultGeneric(wechatUserInfo.getOpenId());
}
@GetMapping("/phoneNo/{phoneNo}")
public JsonResult openId(@PathVariable String phoneNo) {
WechatUserInfo wechatUserInfo = wechatService.findWechatUserInfoByPhoneNo(phoneNo);
if (wechatUserInfo == null) {
return JsonResult.buildSuccessResult();
}
return JsonResult.buildSuccessResultGeneric(wechatUserInfo.getOpenId());
}
@RequestMapping("/code/{key}/{extdata}")
public void receiveCode(@PathVariable String key, @PathVariable String extdata) {
//todo
}
@PatchMapping("/forbidden/{userId}")
public JsonResult forbidden(@PathVariable Long userId, String reason) {
int res = wechatService.forbiddenUserWeChat(userId);
log.info("取消微信关联 userId:{},reason:{},结果:{}", userId, reason, res);
return JsonResult.buildSuccessResultGeneric(res);
}
}
package cn.quantgroup.xyqb.controller.phonenoidno;
import cn.quantgroup.xyqb.exception.DataException;
import cn.quantgroup.xyqb.exception.VerificationCodeErrorException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/v1/dummy")
public class DummyController {
// TODO: 2020/2/4 测试
@GetMapping
public void dummy() {
log.info("dummy rui测试.");
throw new VerificationCodeErrorException("rui测试.");
}
@GetMapping("/1")
public void dummy1() {
log.info("dummy1 rui测试.");
throw new DataException("rui测试.");
}
}
package cn.quantgroup.xyqb.controller.phonenoidno;
import cn.quantgroup.xyqb.entity.UserHashPhoneNoIdNoMapping;
import cn.quantgroup.xyqb.util.encrypt.Md5Util;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
* 同步xyqb_user.user_detail
* <p>
* Date: 2019/12/13
* Time: 上午10:42
*
* @author: yangrui
*/
@Slf4j
//@RestController
//@RequestMapping("/v1/phonenoidno")
public class UserHashPhoneNoIdNoMappingController {
private static final String SYNC_DATA_PHONE_NO_ID_NO = "syncdataphonenoidno";
private static final String SYNC_DATA_PHONE_NO_ID_NO_SWITCH = "switch";
private static final String SYNC_DATA_PHONE_NO_ID_NO_LAST_ID = "last_id";
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private JdbcTemplate jdbcTemplate;
/**
* md5(phone_no,id_no)
* 本地环境模拟-Xms3G -Xmx3G,单线程同步实际时间45分钟
*
* @return
*/
// @GetMapping("/sync/data")
public String syncData() {
log.info("start");
long start = System.currentTimeMillis();
long idStart = 0;
Object lastIdObj = stringRedisTemplate.opsForHash().get(SYNC_DATA_PHONE_NO_ID_NO, SYNC_DATA_PHONE_NO_ID_NO_LAST_ID);
if (lastIdObj != null) {
idStart = Long.valueOf(String.valueOf(lastIdObj));
}
final int limit = 5000;
long count = jdbcTemplate.queryForObject("select count(id) from user_detail where id > ?", Long.class, new Object[]{idStart});
if (count > 0) {
long page = count / limit + 1;
for (int i = 0; i < page; i++) {
Object state = stringRedisTemplate.opsForHash().get(SYNC_DATA_PHONE_NO_ID_NO, SYNC_DATA_PHONE_NO_ID_NO_SWITCH);
if (state == null || "on".equals(state)) {
List<UserHashPhoneNoIdNoMapping> userHashPhoneNoIdNoMappings = Lists.newArrayList();
jdbcTemplate.query("select id, user_id, phone_no, id_no" +
" from user_detail where id > ? limit ?", new Object[]{idStart, limit}, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
UserHashPhoneNoIdNoMapping userHashPhoneNoIdNoMapping = new UserHashPhoneNoIdNoMapping();
/* 暂存 */
userHashPhoneNoIdNoMapping.setId(rs.getLong("id"));
userHashPhoneNoIdNoMapping.setUserId(rs.getLong("user_id"));
String phoneNoIdNoMd5 = (rs.getString("phone_no") + rs.getString("id_no")).toUpperCase();
userHashPhoneNoIdNoMapping.setPhoneNoIdNoMd5(Md5Util.build(phoneNoIdNoMd5));
userHashPhoneNoIdNoMappings.add(userHashPhoneNoIdNoMapping);
}
});
if (CollectionUtils.isNotEmpty(userHashPhoneNoIdNoMappings)) {
jdbcTemplate.batchUpdate("insert ignore into user_hash_phone_no_id_no_mapping (user_id, phone_no_id_no_md5) values (?,?)", new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
UserHashPhoneNoIdNoMapping userHashPhoneNoIdNoMapping = userHashPhoneNoIdNoMappings.get(i);
ps.setLong(1, userHashPhoneNoIdNoMapping.getUserId());
ps.setString(2, userHashPhoneNoIdNoMapping.getPhoneNoIdNoMd5());
}
@Override
public int getBatchSize() {
return userHashPhoneNoIdNoMappings.size();
}
});
idStart = userHashPhoneNoIdNoMappings.get(userHashPhoneNoIdNoMappings.size() - 1).getId();
stringRedisTemplate.opsForHash().put(SYNC_DATA_PHONE_NO_ID_NO, SYNC_DATA_PHONE_NO_ID_NO_LAST_ID, String.valueOf(idStart));
}
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
log.info("done cost time = 【{}】", System.currentTimeMillis() - start);
return "SUCCESS";
}
// @GetMapping("/sync/data/stop")
public String syncDataStop() {
stringRedisTemplate.opsForHash().put(SYNC_DATA_PHONE_NO_ID_NO, SYNC_DATA_PHONE_NO_ID_NO_SWITCH, "off");
return "SUCCESS";
}
// @GetMapping("/sync/data/open/switch")
public String syncDataOpenSwitch() {
stringRedisTemplate.opsForHash().put(SYNC_DATA_PHONE_NO_ID_NO, SYNC_DATA_PHONE_NO_ID_NO_SWITCH, "on");
return "SUCCESS";
}
}
...@@ -26,8 +26,6 @@ public class CrosFilter implements Filter { ...@@ -26,8 +26,6 @@ public class CrosFilter implements Filter {
static { static {
DISALLOWED_METHOD.add("OPTIONS"); DISALLOWED_METHOD.add("OPTIONS");
DISALLOWED_METHOD.add("PUT");
DISALLOWED_METHOD.add("DELETE");
} }
@Value("${xyqb.filter.allowedOrigin}") @Value("${xyqb.filter.allowedOrigin}")
...@@ -46,7 +44,7 @@ public class CrosFilter implements Filter { ...@@ -46,7 +44,7 @@ public class CrosFilter implements Filter {
HttpServletResponse response = (HttpServletResponse) servletResponse; HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", allowedOrigin); response.setHeader("Access-Control-Allow-Origin", allowedOrigin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, PATCH");
response.setHeader("Access-Control-Allow-Headers", allowedHeaders); response.setHeader("Access-Control-Allow-Headers", allowedHeaders);
response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Max-Age", "3600");
if (DISALLOWED_METHOD.contains(request.getMethod())) { if (DISALLOWED_METHOD.contains(request.getMethod())) {
......
package cn.quantgroup.xyqb.model; package cn.quantgroup.xyqb.model;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
...@@ -10,6 +11,7 @@ import lombok.NoArgsConstructor; ...@@ -10,6 +11,7 @@ import lombok.NoArgsConstructor;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Builder
public class LoginProperties { public class LoginProperties {
/** /**
* 维度 * 维度
......
...@@ -3,9 +3,13 @@ package cn.quantgroup.xyqb.repository; ...@@ -3,9 +3,13 @@ package cn.quantgroup.xyqb.repository;
import cn.quantgroup.xyqb.entity.UserAttached; import cn.quantgroup.xyqb.entity.UserAttached;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/** /**
* Created by 11 on 2017/3/22. * Created by 11 on 2017/3/22.
*/ */
public interface IUserAttachedRepository extends JpaRepository<UserAttached, Long> { public interface IUserAttachedRepository extends JpaRepository<UserAttached, Long> {
UserAttached findByUserId(Long userId); UserAttached findByUserId(Long userId);
List<UserAttached> findByUserIdIn(List<Long> userId);
} }
package cn.quantgroup.xyqb.service.register; package cn.quantgroup.xyqb.service.register;
import java.util.List;
import cn.quantgroup.xyqb.entity.Address; import cn.quantgroup.xyqb.entity.Address;
import cn.quantgroup.xyqb.entity.Contact; import cn.quantgroup.xyqb.entity.Contact;
import cn.quantgroup.xyqb.entity.User; import cn.quantgroup.xyqb.entity.User;
import java.util.List;
/** /**
* @author liqing * @author liqing
* @date 2017/12/4 0004 * @date 2017/12/4 0004
*/ */
public interface IUserRegisterService { public interface IUserRegisterService {
User register(Long registerFrom, String phoneNo);
/** /**
* 替换AppController.register * 替换AppController.register
* /app/login,/app/login_super * /app/login,/app/login_super
......
package cn.quantgroup.xyqb.service.register.impl; package cn.quantgroup.xyqb.service.register.impl;
import java.sql.Timestamp;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.entity.Address; import cn.quantgroup.xyqb.entity.Address;
import cn.quantgroup.xyqb.entity.Contact; import cn.quantgroup.xyqb.entity.Contact;
...@@ -24,6 +9,17 @@ import cn.quantgroup.xyqb.model.UserRegisterParam; ...@@ -24,6 +9,17 @@ import cn.quantgroup.xyqb.model.UserRegisterParam;
import cn.quantgroup.xyqb.service.register.IUserRegisterService; import cn.quantgroup.xyqb.service.register.IUserRegisterService;
import cn.quantgroup.xyqb.service.user.IUserService; import cn.quantgroup.xyqb.service.user.IUserService;
import cn.quantgroup.xyqb.util.PasswordUtil; import cn.quantgroup.xyqb.util.PasswordUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
/** /**
* @author liqing * @author liqing
...@@ -39,6 +35,22 @@ public class UserRegisterServiceImpl implements IUserRegisterService { ...@@ -39,6 +35,22 @@ public class UserRegisterServiceImpl implements IUserRegisterService {
@Resource @Resource
private IUserService userService; private IUserService userService;
@Transactional(rollbackFor = Exception.class)
@Override
public User register(Long registerFrom, String phoneNo) {
UserRegisterParam userRegisterParam = UserRegisterParam.builder()
.registerFrom(registerFrom)
.phoneNo(phoneNo)
.channelId(registerFrom)
.sendSuccessSms(true)
.sendAppSms(true)
.sendSuccessMq(true)
.build();
User user = saveUser(userRegisterParam);
applicationEventPublisher.publishEvent(new RegisterEvent(this, userRegisterParam));
return user;
}
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public User register(Long registerFrom, String phoneNo, String idNo, String name, Long channelId, Long btRegisterChannelId) { public User register(Long registerFrom, String phoneNo, String idNo, String name, Long channelId, Long btRegisterChannelId) {
......
...@@ -27,6 +27,7 @@ public interface ISessionService { ...@@ -27,6 +27,7 @@ public interface ISessionService {
SessionStruct createSessionAndPersist(User user, LoginProperties loginProperties); SessionStruct createSessionAndPersist(User user, LoginProperties loginProperties);
void persistSession(String token, SessionValue sessionValue); void persistSession(String token, SessionValue sessionValue);
void persistSession(String token, SessionValue sessionValue,Long time);
void deleteByUserId(long userId); void deleteByUserId(long userId);
......
...@@ -136,16 +136,20 @@ public class SessionServiceImpl implements ISessionService { ...@@ -136,16 +136,20 @@ public class SessionServiceImpl implements ISessionService {
@Override @Override
@UserBtRegisterFill @UserBtRegisterFill
public void persistSession(String token, SessionValue sessionValue) { public void persistSession(String token, SessionValue sessionValue) {
persistSession(token, sessionValue, Constants.Session.SESSION_VALID_TIME);
}
@Override
public void persistSession(String token, SessionValue sessionValue, Long time) {
Timestamp current = new Timestamp(System.currentTimeMillis()); Timestamp current = new Timestamp(System.currentTimeMillis());
sessionValue.setLastAccessTime(current); sessionValue.setLastAccessTime(current);
String json = JSON.toJSONString(sessionValue); String json = JSON.toJSONString(sessionValue);
stringRedisTemplate.opsForValue().set(Constants.Session.USER_SESSION_CACHE + token, json, stringRedisTemplate.opsForValue().set(Constants.Session.USER_SESSION_CACHE + token, json,
Constants.Session.ONE_DAY, TimeUnit.SECONDS); time, TimeUnit.SECONDS);
String key = generateLoginPropertiesKey(sessionValue.getUser().getId(), sessionValue.getLoginProperties()); String key = generateLoginPropertiesKey(sessionValue.getUser().getId(), sessionValue.getLoginProperties());
stringRedisTemplate.opsForValue().set(key, token, Constants.Session.ONE_DAY, TimeUnit.SECONDS); stringRedisTemplate.opsForValue().set(key, token, time, TimeUnit.SECONDS);
log.info("[Session生命期延续],token:{},有效期:[24Hour]", token); log.info("[Session生命期延续],token:{},有效期:[24Hour]", token);
setUserIdTokenKeys(sessionValue.getUser().getId(), key); setUserIdTokenKeys(sessionValue.getUser().getId(), key);
} }
/** /**
...@@ -159,7 +163,7 @@ public class SessionServiceImpl implements ISessionService { ...@@ -159,7 +163,7 @@ public class SessionServiceImpl implements ISessionService {
String setKey = getUserSessionSetKey(userId); String setKey = getUserSessionSetKey(userId);
try { try {
stringRedisTemplate.opsForSet().add(setKey, key); stringRedisTemplate.opsForSet().add(setKey, key);
stringRedisTemplate.expire(setKey, Constants.Session.ONE_DAY, TimeUnit.SECONDS); stringRedisTemplate.expire(setKey, Constants.Session.SESSION_VALID_TIME, TimeUnit.SECONDS);
} catch (Exception e) { } catch (Exception e) {
log.error("存储用户注销件失败,userId:{},Exception:{}", userId, e); log.error("存储用户注销件失败,userId:{},Exception:{}", userId, e);
} }
......
package cn.quantgroup.xyqb.service.user; package cn.quantgroup.xyqb.service.user;
import cn.quantgroup.xyqb.controller.internal.user.resp.UserFullResp;
import cn.quantgroup.xyqb.entity.Merchant;
import cn.quantgroup.xyqb.entity.User; import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.UserInfo; import cn.quantgroup.xyqb.model.UserInfo;
import javax.servlet.http.HttpServletRequest;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -55,6 +59,7 @@ public interface IUserService { ...@@ -55,6 +59,7 @@ public interface IUserService {
/** /**
* 修改手机号码. * 修改手机号码.
*
* @param oldPhoneNo 旧手机号 * @param oldPhoneNo 旧手机号
* @param newPhoneNo 新手机号 * @param newPhoneNo 新手机号
* @return 返回用户信息 * @return 返回用户信息
...@@ -63,8 +68,21 @@ public interface IUserService { ...@@ -63,8 +68,21 @@ public interface IUserService {
/** /**
* 删除这个用户相关缓存 * 删除这个用户相关缓存
* @param uuid 根据 uuid *
* @param uuid 根据 uuid
* @param phoneNo 根据手机号 * @param phoneNo 根据手机号
*/ */
void userCacheEvict(String uuid, String phoneNo); void userCacheEvict(String uuid, String phoneNo);
JsonResult loginFast(Long channelId, String appChannel, Long createdFrom, Long btRegisterChannelId,
String dimension, String clickId, HttpServletRequest request, Merchant merchant,
String phoneNo);
/**
* 查询用户全量信息
*
* @param userId 用户id
* @return
*/
UserFullResp findUserFullSearchByUserId(Long userId);
} }
...@@ -2,19 +2,30 @@ package cn.quantgroup.xyqb.service.user; ...@@ -2,19 +2,30 @@ package cn.quantgroup.xyqb.service.user;
import cn.quantgroup.xyqb.entity.UserAttached; import cn.quantgroup.xyqb.entity.UserAttached;
import java.util.List;
/** /**
* Created by 11 on 2017/3/22. * Created by 11 on 2017/3/22.
*/ */
public interface UserCenterService { public interface UserCenterService {
/** /**
* 查询用户附加信息 * 查询用户附加信息
*
* @param userId * @param userId
* @return * @return
*/ */
UserAttached searchUserAttachedByUserId(long userId); UserAttached searchUserAttachedByUserId(long userId);
/**
* 查询用户附加信息
* @param userIds
* @return
*/
List<UserAttached> searchUserAttachedListByUserId(List<Long> userIds);
/** /**
* 保存用户头像 * 保存用户头像
*
* @param userId - 用户主键 * @param userId - 用户主键
* @param avatar - 头像url地址 * @param avatar - 头像url地址
* @return * @return
...@@ -23,8 +34,9 @@ public interface UserCenterService { ...@@ -23,8 +34,9 @@ public interface UserCenterService {
/** /**
* 保存用户昵称 * 保存用户昵称
*
* @param userId - 用户主键 * @param userId - 用户主键
* @param nick - 昵称 * @param nick - 昵称
* @return * @return
*/ */
UserAttached saveUserNick(long userId, String nick); UserAttached saveUserNick(long userId, String nick);
......
...@@ -9,6 +9,7 @@ import org.springframework.cache.annotation.CacheEvict; ...@@ -9,6 +9,7 @@ import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.Timestamp;
import java.util.List; import java.util.List;
/** /**
...@@ -29,11 +30,14 @@ public class AddressServiceImpl implements IAddressService { ...@@ -29,11 +30,14 @@ public class AddressServiceImpl implements IAddressService {
@Override @Override
@CacheEvict(value = "addresscache", key = "'address' + #addressObj.userId", cacheManager = "cacheManager") @CacheEvict(value = "addresscache", key = "'address' + #addressObj.userId", cacheManager = "cacheManager")
public Address save(Address addressObj) { public Address save(Address addressObj) {
Timestamp now = new Timestamp(System.currentTimeMillis());
/* 替换所有,UTF-8编码时4字节的Emoji表情字符 */ /* 替换所有,UTF-8编码时4字节的Emoji表情字符 */
addressObj.setProvince(EmojiUtil.filterUnicode4(addressObj.getProvince())); addressObj.setProvince(EmojiUtil.filterUnicode4(addressObj.getProvince()));
addressObj.setCity(EmojiUtil.filterUnicode4(addressObj.getCity())); addressObj.setCity(EmojiUtil.filterUnicode4(addressObj.getCity()));
addressObj.setDistrict(EmojiUtil.filterUnicode4(addressObj.getDistrict())); addressObj.setDistrict(EmojiUtil.filterUnicode4(addressObj.getDistrict()));
addressObj.setAddress(EmojiUtil.filterUnicode4(addressObj.getAddress())); addressObj.setAddress(EmojiUtil.filterUnicode4(addressObj.getAddress()));
addressObj.setCreatedAt(now);
addressObj.setUpdateAt(now);
return addressRepository.save(addressObj); return addressRepository.save(addressObj);
} }
......
...@@ -13,6 +13,7 @@ import org.springframework.cache.annotation.Cacheable; ...@@ -13,6 +13,7 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
...@@ -32,6 +33,11 @@ public class UserCenterServiceImpl implements UserCenterService { ...@@ -32,6 +33,11 @@ public class UserCenterServiceImpl implements UserCenterService {
return userAttachedRepository.findByUserId(userId); return userAttachedRepository.findByUserId(userId);
} }
@Override
public List<UserAttached> searchUserAttachedListByUserId(List<Long> userIds) {
return userAttachedRepository.findByUserIdIn(userIds);
}
@Override @Override
@CacheEvict(value = "userAttachedCache", key = "'xyqbUserAttached' + #userId", cacheManager = "cacheManager") @CacheEvict(value = "userAttachedCache", key = "'xyqbUserAttached' + #userId", cacheManager = "cacheManager")
public UserAttached saveUserAvatar(long userId, String avatar) { public UserAttached saveUserAvatar(long userId, String avatar) {
......
...@@ -9,6 +9,8 @@ import org.springframework.cache.annotation.Cacheable; ...@@ -9,6 +9,8 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
/** /**
* Created by Miraculous on 2017/1/3. * Created by Miraculous on 2017/1/3.
*/ */
...@@ -28,6 +30,13 @@ public class UserExtInfoServiceImpl implements IUserExtInfoService { ...@@ -28,6 +30,13 @@ public class UserExtInfoServiceImpl implements IUserExtInfoService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@CacheEvict(value = "userextinfocache", key = "'extinfo' + #info.userId", cacheManager = "cacheManager") @CacheEvict(value = "userextinfocache", key = "'extinfo' + #info.userId", cacheManager = "cacheManager")
public UserExtInfo save(UserExtInfo info) { public UserExtInfo save(UserExtInfo info) {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
if (info.getCreatedAt() == null) {
info.setCreatedAt(timestamp);
}
if (info.getUpdateAt() == null) {
info.setUpdateAt(timestamp);
}
return userExtInfoRepository.save(info); return userExtInfoRepository.save(info);
} }
......
package cn.quantgroup.xyqb.service.user.impl; package cn.quantgroup.xyqb.service.user.impl;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.entity.User; import cn.quantgroup.xyqb.aspect.lock.RedisLock;
import cn.quantgroup.xyqb.entity.UserDetail; import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.entity.UserHashMapping; import cn.quantgroup.xyqb.controller.internal.user.resp.UserFullResp;
import cn.quantgroup.xyqb.entity.UserHashPhoneNoIdNoMapping; import cn.quantgroup.xyqb.entity.*;
import cn.quantgroup.xyqb.event.PhoneNoUpdateEvent; import cn.quantgroup.xyqb.event.PhoneNoUpdateEvent;
import cn.quantgroup.xyqb.exception.DataException; import cn.quantgroup.xyqb.exception.DataException;
import cn.quantgroup.xyqb.exception.UserNotExistException;
import cn.quantgroup.xyqb.model.FindByMd5Enum; import cn.quantgroup.xyqb.model.FindByMd5Enum;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.LoginProperties;
import cn.quantgroup.xyqb.model.UserInfo; import cn.quantgroup.xyqb.model.UserInfo;
import cn.quantgroup.xyqb.repository.IUserHashMappingRepository; import cn.quantgroup.xyqb.repository.IUserHashMappingRepository;
import cn.quantgroup.xyqb.repository.IUserHashPhoneNoIdNoMappingRepository; import cn.quantgroup.xyqb.repository.IUserHashPhoneNoIdNoMappingRepository;
import cn.quantgroup.xyqb.repository.IUserRepository; import cn.quantgroup.xyqb.repository.IUserRepository;
import cn.quantgroup.xyqb.service.user.IUserDetailService; import cn.quantgroup.xyqb.service.register.IUserRegisterService;
import cn.quantgroup.xyqb.service.user.IUserService; import cn.quantgroup.xyqb.service.session.ISessionService;
import cn.quantgroup.xyqb.util.HashUtil; import cn.quantgroup.xyqb.service.user.*;
import cn.quantgroup.xyqb.util.PasswordUtil; import cn.quantgroup.xyqb.service.wechat.IWechatService;
import cn.quantgroup.xyqb.util.ValidationUtil; import cn.quantgroup.xyqb.util.*;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -32,11 +36,9 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -32,11 +36,9 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
...@@ -44,7 +46,7 @@ import java.util.concurrent.TimeUnit; ...@@ -44,7 +46,7 @@ import java.util.concurrent.TimeUnit;
*/ */
@Service @Service
@Slf4j @Slf4j
public class UserServiceImpl implements IUserService { public class UserServiceImpl implements IUserService, IBaseController {
@Autowired @Autowired
private RedisTemplate<String, String> stringRedisTemplate; private RedisTemplate<String, String> stringRedisTemplate;
...@@ -63,6 +65,21 @@ public class UserServiceImpl implements IUserService { ...@@ -63,6 +65,21 @@ public class UserServiceImpl implements IUserService {
@Autowired @Autowired
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
@Resource
private IUserRegisterService userRegisterService;
@Autowired
private IWechatService wechatService;
@Autowired
private ISessionService sessionService;
@Resource
private IUserExtInfoService userExtInfoService;
@Resource
private IAddressService addressService;
@Resource
private IContactService contactService;
@Override @Override
@Cacheable(value = "usercache", key = "'xyqbuser' + #phone", unless = "#result == null", cacheManager = "cacheManager") @Cacheable(value = "usercache", key = "'xyqbuser' + #phone", unless = "#result == null", cacheManager = "cacheManager")
...@@ -261,4 +278,116 @@ public class UserServiceImpl implements IUserService { ...@@ -261,4 +278,116 @@ public class UserServiceImpl implements IUserService {
log.info("清理用户缓存成功,uuid:{},phoneNo:{}", uuid, phoneNo); log.info("清理用户缓存成功,uuid:{},phoneNo:{}", uuid, phoneNo);
} }
@Override
@RedisLock(prefix = "lock:login:fast:", key = "#this[8]")
public JsonResult loginFast(Long channelId, String appChannel, Long createdFrom, Long btRegisterChannelId,
String dimension, String clickId, HttpServletRequest request, Merchant merchant, String phoneNo) {
User user = findByPhoneWithCache(phoneNo);
if (user != null && !user.getEnable()) {
log.info("用户不存在,或者已经注销,phoneNo:{}", phoneNo);
return JsonResult.buildErrorStateResult("登录失败", null);
}
if (user == null) {
// Service层会负责发送注册消息到LoanVest
user = userRegisterService.register(phoneNo, channelId, createdFrom, appChannel, btRegisterChannelId, dimension);
if (user == null) {
throw new UserNotExistException("用户未找到");
}
//广点通转化注册 - 发送消息 - 方法内过滤
MqUtils.sendRegisterMessageForGdt(phoneNo, clickId);
}
if (!wechatRelateUserIfNecessary(user, request)) {
return JsonResult.buildErrorStateResult("登录时微信关联失败", null);
}
LoginProperties loginProperties = new LoginProperties("", 3, channelId, createdFrom, appChannel, merchant.getId(), merchant.getName());
return new JsonResult(sessionService.createSession(user, loginProperties));
}
/**
* 如果必要的话,关联用户和微信
*
* @param user - 用户标识
* @param request - 当前请求
* @return true - 继续登录,false - 微信关联失败,重新登录
*/
private boolean wechatRelateUserIfNecessary(User user, HttpServletRequest request) {
Objects.requireNonNull(request, "无效请求");
String clientIp = IpUtil.getRemoteIP(request);
Set<String> paramKeys = request.getParameterMap().keySet();
boolean ready = paramKeys.contains(Constants.WECHAT_OPEN_ID);
if (!ready) {
return true;
} else if (Objects.isNull(user) || Objects.isNull(user.getId()) || StringUtils.isBlank(request.getParameter(Constants.WECHAT_OPEN_ID))) {
log.warn("微信关联失败,user:{}, request-Header:{}", user, JSON.toJSONString(getRequestHeaderMap(request)));
return false;
}
Long userId = user.getId();
String phoneNo = user.getPhoneNo();
try {
int rows = wechatService.relateUser(userId, phoneNo, request.getParameter(Constants.WECHAT_OPEN_ID));
return rows > 0;
} catch (Exception e) {
log.error("微信关联失败,user:{}, request-Header:{}", user, JSON.toJSONString(getRequestHeaderMap(request)), e);
}
return false;
}
/**
* 查询用户全量信息
*
* @param userId 用户id
* @return
*/
@Override
public UserFullResp findUserFullSearchByUserId(Long userId) {
User user = userRepository.findById(userId);
UserDetail userDetail = userDetailService.findByUserId(userId);
UserExtInfo userExtInfo = userExtInfoService.findByUserId(userId);
Address address = addressService.findByUserId(userId);
UserFullResp userFullResp = UserFullResp.builder().userId(userId).build();
if (user != null) {
userFullResp.setUuid(user.getUuid());
}
if (userDetail != null) {
userFullResp.setPhoneNo(userDetail.getPhoneNo());
userFullResp.setName(userDetail.getName());
userFullResp.setIdNo(userDetail.getIdNo());
userFullResp.setIdType(userDetail.getIdType().ordinal());
userFullResp.setGender(userDetail.getGender().ordinal());
userFullResp.setEmail(userDetail.getEmail());
userFullResp.setQq(userDetail.getQq());
}
if (userExtInfo != null) {
userFullResp.setIncomeType(userExtInfo.getIncomeEnum().ordinal());
userFullResp.setIncomeRange(userExtInfo.getIncomeRangeEnum().ordinal());
userFullResp.setOccupation(userExtInfo.getOccupationEnum().ordinal());
userFullResp.setEducation(userExtInfo.getEducationEnum().ordinal());
userFullResp.setHasCar(userExtInfo.getHasCar() ? 1 : 0);
userFullResp.setHasSocialSecurity(userExtInfo.getHasSocialSecurity() ? 1 : 0);
userFullResp.setHasHouse(userExtInfo.getHasHouse() ? 1 : 0);
userFullResp.setHasCreditCard(userExtInfo.getHasCreditCard() ? 1 : 0);
userFullResp.setMarryStatus(userExtInfo.getMarryStatus().ordinal());
}
if (address != null) {
userFullResp.setProvinceCode(address.getProvinceCode());
userFullResp.setProvince(address.getProvince());
userFullResp.setCityCode(address.getCityCode());
userFullResp.setCity(address.getCity());
userFullResp.setDistrictCode(address.getDistrictCode());
userFullResp.setDistrict(address.getDistrict());
userFullResp.setAddress(address.getAddress());
}
List<UserFullResp.Contact> contacts = Lists.newArrayList();
contactService.findByUserId(userId, true).forEach(contact -> {
contacts.add(UserFullResp.Contact.builder()
.userId(userId)
.name(contact.getName())
.mobile(contact.getPhoneNo())
.relation(contact.getRelation().ordinal())
.build());
});
userFullResp.setContacts(contacts);
return userFullResp;
}
} }
...@@ -7,6 +7,8 @@ import org.springframework.context.ApplicationContext; ...@@ -7,6 +7,8 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Map;
/** /**
* Created by Miraculous on 15/7/12. * Created by Miraculous on 15/7/12.
*/ */
...@@ -120,4 +122,7 @@ public class ApplicationContextHolder implements ApplicationContextAware { ...@@ -120,4 +122,7 @@ public class ApplicationContextHolder implements ApplicationContextAware {
return applicationContext.getAliases(name); return applicationContext.getAliases(name);
} }
public static <T> Map<String, T> getBeansOfType(Class<T> requiredType) throws BeansException {
return applicationContext.getBeansOfType(requiredType);
}
} }
\ No newline at end of file
...@@ -34,7 +34,7 @@ public class IpUtil { ...@@ -34,7 +34,7 @@ public class IpUtil {
public static final String IO_IP = "139.198."; public static final String IO_IP = "139.198.";
static { static {
String[] ips = {"172.16.", "172.18.", "172.20.", "172.21.", "172.30.", "172.41.", "192.168.3.", "192.168.4."}; String[] ips = {"10.", "172.", "192.168.3.", "192.168.4."};
WHITE_ADDRESS.addAll(Arrays.asList(ips)); WHITE_ADDRESS.addAll(Arrays.asList(ips));
//系统环境 //系统环境
if (!TechEnvironment.isPro()) { if (!TechEnvironment.isPro()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment