package com.mzl.flower.web.login; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.hutool.core.util.StrUtil; import com.mzl.flower.base.BaseController; import com.mzl.flower.base.R; import com.mzl.flower.base.ReturnDataDTO; import com.mzl.flower.base.cache.StringCacheClient; import com.mzl.flower.config.exception.BaseException; import com.mzl.flower.config.exception.ValidationException; import com.mzl.flower.config.security.SecurityUtils; import com.mzl.flower.config.security.token.PhoneAuthenticationToken; import com.mzl.flower.config.security.token.UserIdAuthenticationToken; import com.mzl.flower.config.security.token.WebAuthenticationToken; import com.mzl.flower.constant.Constants; import com.mzl.flower.dto.request.CreateWechatUserDTO; import com.mzl.flower.dto.request.UserLoginDTO; import com.mzl.flower.dto.request.UserPhoneLoginDTO; import com.mzl.flower.dto.response.customer.CustomerDTO; import com.mzl.flower.dto.response.wx.WxUserVO; import com.mzl.flower.dto.security.UserDTO; import com.mzl.flower.entity.customer.Customer; import com.mzl.flower.entity.system.User; import com.mzl.flower.mapper.customer.CustomerMapper; import com.mzl.flower.service.customer.CustomerService; import com.mzl.flower.service.impl.WechatUserDetailsService; import com.mzl.flower.service.login.LoginService; import com.mzl.flower.service.system.UserService; import com.mzl.flower.service.system.WeChatService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationDetailsSource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.validation.constraints.NotBlank; import java.util.Map; @Slf4j @RestController @RequestMapping("/api") @Api(value = "会员登录", tags = "会员登录") public class CustomerLoginController extends BaseController { private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); @Autowired private AuthenticationManager authenticationManager; @Autowired private LoginService loginService; @Autowired private StringCacheClient stringCacheClient; @Autowired private WeChatService weChatService; @Autowired private UserService userService; @Autowired private CustomerMapper customerMapper; @Autowired private CustomerService customerService; @Autowired private TokenStore tokenStore; public static final String SMS_CODE_KEY = "SMS-CODE-KEY"; public static final String TOKEN_KEY = "TOKEN-KEY"; public static final String SEPARATOR = ":"; @PostMapping("/login/wechat") @ApiOperation(value = "微信小程序登录", notes = "微信小程序登录") public ResponseEntity> loginWeChat( HttpServletRequest request,@RequestBody CreateWechatUserDTO dto) throws Exception { WxMaJscode2SessionResult session = weChatService.getWxMaSessionInfo(dto.getCode()); String openId = session.getOpenid(); String sessionKey = session.getSessionKey(); String unionId = session.getUnionid(); // 判断当前用户账号是否存在 dto.setOpenId(openId); dto.setSessionKey(sessionKey); dto.setUnionId(unionId); dto.setUserType(Constants.USER_TYPE.customer.name()); User existUserByOpenId = userService.getExistUserByOpenId(openId, sessionKey, unionId, Constants.USER_TYPE.customer.name()); if(ObjectUtils.isEmpty(existUserByOpenId)){ userService.registWxUser(dto); } User user = userService.findUserByOpenId(openId, sessionKey, unionId , dto.getImgUrl(), dto.getNickname(),Constants.USER_TYPE.customer.name()); String tokenCache = stringCacheClient.get(TOKEN_KEY + SEPARATOR + user.getId()); if (StringUtils.isNotBlank(tokenCache)) { //强制删除token,下线 removeToken(tokenCache,user.getId()); } try { UserIdAuthenticationToken authRequest = new UserIdAuthenticationToken(user.getId(), null); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); Authentication authentication = authenticationManager.authenticate(authRequest); OAuth2AccessToken token = loginService.getAccessToken(authentication, Constants.USER_TYPE.customer.name()); stringCacheClient.set(TOKEN_KEY + SEPARATOR + user.getId(),token.getValue()); return returnData(R.SUCCESS.getCode(), token); } catch (BadCredentialsException e) { throw new ValidationException("用户名或密码错误"); } catch (UsernameNotFoundException e) { throw new ValidationException("用户不存在"); } catch (Exception e) { log.error(e.getMessage(), e); throw new BaseException(R.RUNTIME_EXCEPTION.getCode(), "登录错误"); } } @PostMapping("/wx/getuserphonenumber") @ApiOperation(value = "获取当前授权的手机号") public ResponseEntity getuserphonenumber(@RequestBody CreateWechatUserDTO dto) throws Exception{ return returnData(R.SUCCESS.getCode(), weChatService.getuserphonenumber(dto)); } @PostMapping("/wx/getExistUserByOpenId") @ApiOperation(value = "查看当前微信号是否已经绑定了用户") public ResponseEntity getExistUserByOpenId(@RequestBody CreateWechatUserDTO dto) throws Exception{ WxMaJscode2SessionResult session = weChatService.getWxMaSessionInfo(dto.getCode()); String openId = session.getOpenid(); String sessionKey = session.getSessionKey(); String unionId = session.getUnionid(); User user=userService.getExistUserByOpenId(openId, sessionKey, unionId,dto.getUserType()); return returnData(R.SUCCESS.getCode(), new WxUserVO(openId,sessionKey,unionId,user)); } @GetMapping("/wx/jscode2session") @ApiOperation(value = "微信小程序授权") public ResponseEntity jscode2session(@NotBlank(message = "授权码不能为空") String jsCode,String userType) throws Exception{ return returnData(R.SUCCESS.getCode(), weChatService.getWechatOpenId(jsCode,userType)); } @PostMapping("/login/customer") @ApiOperation(value = "商户账号密码登录", notes = "商户账号密码登录") public ResponseEntity> loginPerson(HttpServletRequest request , @RequestBody UserLoginDTO loginDTO) { String username = loginDTO.getUsername(); String password = loginDTO.getPassword(); if (StringUtils.isBlank(username)) { throw new ValidationException("用户名不能为空"); } if (StringUtils.isBlank(password)) { throw new ValidationException("密码不能为空"); } User user = userService.findByTel(username, Constants.USER_TYPE.customer.name()); if(user == null){ throw new ValidationException("用户不存在"); } CustomerDTO currentCustomer = customerMapper.getCurrentCustomer(user.getId()); if (ObjectUtils.isEmpty(currentCustomer)) { throw new ValidationException("用户不存在"); } if (currentCustomer.getIsEnabled() == false) { throw new ValidationException("用户已禁用,请联系管理员"); } String tokenCache = stringCacheClient.get(TOKEN_KEY + SEPARATOR + user.getId()); if (StringUtils.isNotBlank(tokenCache)) { //强制删除token,下线 removeToken(tokenCache,user.getId()); } try { WebAuthenticationToken authRequest = new WebAuthenticationToken(username, password); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); Authentication authentication = authenticationManager.authenticate(authRequest); OAuth2AccessToken token = loginService.getAccessToken(authentication,Constants.USER_TYPE.customer.name()); stringCacheClient.set(TOKEN_KEY + SEPARATOR + user.getId(),token.getValue()); return returnData(R.SUCCESS.getCode(),token); }catch (BadCredentialsException e){ throw new ValidationException("用户名或密码错误"); }catch (UsernameNotFoundException e){ throw new ValidationException("用户不存在"); }catch (Exception e) { log.error(e.getMessage(), e); throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"登录错误"); } } @PostMapping("/login/customer/phone") @ApiOperation(value = "手机验证码登录系统", notes = "手机验证码登录系统") public ResponseEntity> loginPhone(HttpServletRequest request, @RequestBody UserLoginDTO loginDTO) { String tel = loginDTO.getUsername(); String smsCode = loginDTO.getSmsCode(); if (StringUtils.isBlank(tel)) { throw new ValidationException("手机号码不能为空"); } if (StringUtils.isBlank(smsCode)) { throw new ValidationException("手机验证码不能为空"); } //从缓存中获取验证码 String smsCacheCode = stringCacheClient.get(SMS_CODE_KEY + SEPARATOR + Constants.USER_TYPE.customer.name() + SEPARATOR + tel); if (!StringUtils.equals(smsCode, smsCacheCode)) { throw new ValidationException("手机验证码不正确"); } User user = userService.findByTel(tel, Constants.USER_TYPE.customer.name()); if(user == null){ throw new ValidationException("用户不存在"); } CustomerDTO currentCustomer = customerMapper.getCurrentCustomer(user.getId()); if (ObjectUtils.isEmpty(currentCustomer)) { throw new ValidationException("用户不存在"); } if (currentCustomer.getIsEnabled() == false) { throw new ValidationException("用户已禁用,请联系管理员"); } String tokenCache = stringCacheClient.get(TOKEN_KEY + SEPARATOR + user.getId()); if (StringUtils.isNotBlank(tokenCache)) { //强制删除token,下线 removeToken(tokenCache,user.getId()); } try { PhoneAuthenticationToken authRequest = new PhoneAuthenticationToken(tel, smsCode, Constants.USER_TYPE.customer.name()); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); Authentication authentication = authenticationManager.authenticate(authRequest); OAuth2AccessToken token = loginService.getAccessToken(authentication, Constants.USER_TYPE.customer.name()); //删除缓存中的验证码 stringCacheClient.delete(SMS_CODE_KEY + SEPARATOR + Constants.USER_TYPE.customer.name() + SEPARATOR + tel); stringCacheClient.set(TOKEN_KEY + SEPARATOR + user.getId(),token.getValue()); return returnData(R.SUCCESS.getCode(),token); }catch (UsernameNotFoundException e){ throw new ValidationException("手机号未注册"); }catch (Exception e) { log.error(e.getMessage(), e); throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"登录错误"); } } public void removeToken(String token,String userId) { if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(userId)) { stringCacheClient.delete(TOKEN_KEY + SEPARATOR + userId); String tokenValue = token.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim(); OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue); if (accessToken != null && StringUtils.isNotBlank(accessToken.getValue())) { tokenStore.removeAccessToken(accessToken); OAuth2RefreshToken refreshToken = accessToken.getRefreshToken(); tokenStore.removeRefreshToken(refreshToken); } } } @PostMapping("/login/customer/phone/v2") @ApiOperation(value = "手机验证码登录系统", notes = "手机验证码登录系统") public ResponseEntity> loginPhoneV2(HttpServletRequest request, @RequestBody UserPhoneLoginDTO loginDTO) { String tel = loginDTO.getUsername(); String smsCode = loginDTO.getSmsCode(); if (StringUtils.isBlank(tel)) { throw new ValidationException("手机号码不能为空"); } if (StringUtils.isBlank(smsCode)) { throw new ValidationException("手机验证码不能为空"); } //从缓存中获取验证码 String smsCacheCode = stringCacheClient.get(SMS_CODE_KEY + SEPARATOR + Constants.USER_TYPE.customer.name() + SEPARATOR + tel); if (!StringUtils.equals(smsCode, smsCacheCode)) { throw new ValidationException("手机验证码不正确"); } User user = userService.findByTel(tel, Constants.USER_TYPE.customer.name()); User user1 = null; String tokenCache =""; if(user == null){ loginDTO.setUserType(Constants.USER_TYPE.customer.name()); user1 = userService.registPhoneUser(loginDTO); if(org.springframework.util.StringUtils.isEmpty(user1)){ throw new ValidationException("注册用户信息报错"); } tokenCache = stringCacheClient.get(TOKEN_KEY + SEPARATOR + user1.getId()); CustomerDTO currentCustomer = customerMapper.getCurrentCustomer(user1.getId()); if (ObjectUtils.isEmpty(currentCustomer)) { throw new ValidationException("用户不存在"); } if (currentCustomer.getIsEnabled() == false) { throw new ValidationException("用户已禁用,请联系管理员"); } tokenCache = stringCacheClient.get(TOKEN_KEY + SEPARATOR + user1.getId()); if (StringUtils.isNotBlank(tokenCache)) { //强制删除token,下线 removeToken(tokenCache,user.getId()); } }else{ CustomerDTO currentCustomer = customerMapper.getCurrentCustomer(user.getId()); if (ObjectUtils.isEmpty(currentCustomer)) { throw new ValidationException("用户不存在"); } if (currentCustomer.getIsEnabled() == false) { throw new ValidationException("用户已禁用,请联系管理员"); } //验证邀请码 if (StringUtils.isNotEmpty(loginDTO.getIntevailCode())) { throw new ValidationException("非新用户注册无法填写邀请码,请删除后重新登陆"); } tokenCache = stringCacheClient.get(TOKEN_KEY + SEPARATOR + user.getId()); if (StringUtils.isNotBlank(tokenCache)) { //强制删除token,下线 removeToken(tokenCache,user.getId()); } } try { PhoneAuthenticationToken authRequest = new PhoneAuthenticationToken(tel, smsCode, Constants.USER_TYPE.customer.name()); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); Authentication authentication = authenticationManager.authenticate(authRequest); OAuth2AccessToken token = loginService.getAccessToken(authentication, Constants.USER_TYPE.customer.name()); //删除缓存中的验证码 stringCacheClient.delete(SMS_CODE_KEY + SEPARATOR + Constants.USER_TYPE.customer.name() + SEPARATOR + tel); if(user == null){ stringCacheClient.set(TOKEN_KEY + SEPARATOR + user1.getId(),token.getValue()); }else { stringCacheClient.set(TOKEN_KEY + SEPARATOR + user.getId(), token.getValue()); } return returnData(R.SUCCESS.getCode(),token); }catch (UsernameNotFoundException e){ throw new ValidationException("用户不存在"); }catch (Exception e) { log.error(e.getMessage(), e); throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"登录错误"); } } @PostMapping("/account/close") @ApiOperation(value = "账户注销", notes = "账户注销") public ResponseEntity> accountClose() { String userId = SecurityUtils.getUserId(); if(StringUtils.isNotBlank(userId)){ // CustomerDTO currentCustomer = customerMapper.getCurrentCustomer(userId); if(null==currentCustomer){ throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"用户不存在"); } currentCustomer.setIsClosed(true); User user=userService.getUserById(userId); if (StringUtils.isNotBlank(user.getLoginName())) { currentCustomer.setName("智信-" + user.getLoginName().substring(user.getLoginName().length() - 4)); } currentCustomer.setCover("https://hmy-flower.oss-cn-shanghai.aliyuncs.com/8f/8f205ea4618b4ce48d5bd204ae73f075tmp_f0c47a66148245dc17d74563c5939e764273ba583619664d.jpg"); Customer customer=new Customer(); BeanUtils.copyProperties(currentCustomer,customer); // 会员注销 customer.setIsMember(false); // 会员过期时间设置为空 customer.setMemberOvertime(null); customerMapper.updateById(customer); return returnData(R.SUCCESS.getCode(),true); }else{ throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"用户ID不能为空"); } } }