Commit bbe7f477 authored by 徐小光's avatar 徐小光

Merge branch 'middleOffice' into 'master'

Middle office

See merge request !48
parents 18ad952c f5a53405
......@@ -14,8 +14,6 @@ import cn.quantgroup.xyqb.util.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
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.Qualifier;
import org.springframework.beans.factory.annotation.Value;
......@@ -337,7 +335,7 @@ public class SmsController implements IBaseController {
return sendVerificationCode2New(phoneNo, randomCode, deviceId, true, appName, smsMerchant);
}
private String getRandomCode(int count) {
public String getRandomCode(int count) {
if(TechEnvironment.isPro()) {
return RandomStringUtils.random(count, RANDOM_CHARS);
}
......@@ -359,7 +357,7 @@ public class SmsController implements IBaseController {
* @param smsMerchant - 短信模板/类型
* @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)) {
return JsonResult.buildErrorStateResult("手机号格式有误", null);
}
......
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);
}
}
......@@ -26,8 +26,6 @@ public class CrosFilter implements Filter {
static {
DISALLOWED_METHOD.add("OPTIONS");
DISALLOWED_METHOD.add("PUT");
DISALLOWED_METHOD.add("DELETE");
}
@Value("${xyqb.filter.allowedOrigin}")
......@@ -46,7 +44,7 @@ public class CrosFilter implements Filter {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
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-Max-Age", "3600");
if (DISALLOWED_METHOD.contains(request.getMethod())) {
......
package cn.quantgroup.xyqb.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
......@@ -10,6 +11,7 @@ import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LoginProperties {
/**
* 维度
......
package cn.quantgroup.xyqb.service.register;
import java.util.List;
import cn.quantgroup.xyqb.entity.Address;
import cn.quantgroup.xyqb.entity.Contact;
import cn.quantgroup.xyqb.entity.User;
import java.util.List;
/**
* @author liqing
* @date 2017/12/4 0004
*/
public interface IUserRegisterService {
User register(Long registerFrom, String phoneNo);
/**
* 替换AppController.register
* /app/login,/app/login_super
......
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.entity.Address;
import cn.quantgroup.xyqb.entity.Contact;
......@@ -24,6 +9,17 @@ import cn.quantgroup.xyqb.model.UserRegisterParam;
import cn.quantgroup.xyqb.service.register.IUserRegisterService;
import cn.quantgroup.xyqb.service.user.IUserService;
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
......@@ -39,6 +35,22 @@ public class UserRegisterServiceImpl implements IUserRegisterService {
@Resource
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)
@Override
public User register(Long registerFrom, String phoneNo, String idNo, String name, Long channelId, Long btRegisterChannelId) {
......
......@@ -9,6 +9,7 @@ import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
import java.util.List;
/**
......@@ -29,11 +30,14 @@ public class AddressServiceImpl implements IAddressService {
@Override
@CacheEvict(value = "addresscache", key = "'address' + #addressObj.userId", cacheManager = "cacheManager")
public Address save(Address addressObj) {
Timestamp now = new Timestamp(System.currentTimeMillis());
/* 替换所有,UTF-8编码时4字节的Emoji表情字符 */
addressObj.setProvince(EmojiUtil.filterUnicode4(addressObj.getProvince()));
addressObj.setCity(EmojiUtil.filterUnicode4(addressObj.getCity()));
addressObj.setDistrict(EmojiUtil.filterUnicode4(addressObj.getDistrict()));
addressObj.setAddress(EmojiUtil.filterUnicode4(addressObj.getAddress()));
addressObj.setCreatedAt(now);
addressObj.setUpdateAt(now);
return addressRepository.save(addressObj);
}
......
......@@ -9,6 +9,8 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
/**
* Created by Miraculous on 2017/1/3.
*/
......@@ -28,6 +30,13 @@ public class UserExtInfoServiceImpl implements IUserExtInfoService {
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = "userextinfocache", key = "'extinfo' + #info.userId", cacheManager = "cacheManager")
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);
}
......
......@@ -7,6 +7,8 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* Created by Miraculous on 15/7/12.
*/
......@@ -120,4 +122,7 @@ public class ApplicationContextHolder implements ApplicationContextAware {
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
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