|
|
|
|
package com.cyl.h5.service;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
|
|
import com.cyl.h5.pojo.request.BindOpenIdRequest;
|
|
|
|
|
import com.cyl.h5.pojo.request.H5AccountLoginRequest;
|
|
|
|
|
import com.cyl.h5.pojo.request.H5SmsLoginRequest;
|
|
|
|
|
import com.cyl.h5.pojo.request.RegisterRequest;
|
|
|
|
|
import com.cyl.h5.pojo.response.RegisterResponse;
|
|
|
|
|
import com.cyl.h5.pojo.response.ValidatePhoneResponse;
|
|
|
|
|
import com.cyl.h5.pojo.response.H5LoginResponse;
|
|
|
|
|
import com.cyl.manager.ums.domain.Member;
|
|
|
|
|
import com.cyl.manager.ums.domain.MemberLogininfor;
|
|
|
|
|
import com.cyl.manager.ums.domain.MemberWechat;
|
|
|
|
|
import com.cyl.manager.ums.mapper.MemberLogininforMapper;
|
|
|
|
|
import com.cyl.manager.ums.mapper.MemberMapper;
|
|
|
|
|
import com.cyl.manager.ums.mapper.MemberWechatMapper;
|
|
|
|
|
import com.cyl.manager.ums.pojo.vo.MemberVO;
|
|
|
|
|
import com.cyl.manager.ums.service.MemberLogininforService;
|
|
|
|
|
import com.cyl.wechat.WechatAuthService;
|
|
|
|
|
import com.cyl.wechat.response.WechatUserAuth;
|
|
|
|
|
import com.ruoyi.common.constant.Constants;
|
|
|
|
|
import com.ruoyi.common.core.domain.model.LoginMember;
|
|
|
|
|
import com.ruoyi.common.core.redis.RedisCache;
|
|
|
|
|
import com.ruoyi.common.utils.*;
|
|
|
|
|
import com.ruoyi.common.utils.ip.AddressUtils;
|
|
|
|
|
import com.ruoyi.common.utils.ip.IpUtils;
|
|
|
|
|
import com.ruoyi.framework.config.LocalDataUtil;
|
|
|
|
|
import com.ruoyi.framework.web.service.TokenService;
|
|
|
|
|
import eu.bitwalker.useragentutils.UserAgent;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import org.springframework.util.Base64Utils;
|
|
|
|
|
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.util.Base64;
|
|
|
|
|
|
|
|
|
|
@Service
|
|
|
|
|
@Slf4j
|
|
|
|
|
public class H5MemberService {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MemberMapper memberMapper;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private RedisCache redisCache;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private TokenService tokenService;
|
|
|
|
|
|
|
|
|
|
@Value("${aes.key}")
|
|
|
|
|
private String aesKey;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private WechatAuthService wechatAuthService;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MemberWechatMapper memberWechatMapper;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MemberLogininforService memberLogininforService;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private MemberLogininforMapper memberLogininforMapper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 注册
|
|
|
|
|
* @param request 注册请求体
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
|
|
|
|
@Transactional
|
|
|
|
|
public RegisterResponse register(RegisterRequest request){
|
|
|
|
|
LocalDateTime optDate = LocalDateTime.now();
|
|
|
|
|
RegisterResponse response = new RegisterResponse();
|
|
|
|
|
//校验验证码
|
|
|
|
|
this.validateVerifyCode(request.getUuid(), request.getMobile(), request.getCode());
|
|
|
|
|
//创建会员
|
|
|
|
|
Member member = new Member();
|
|
|
|
|
member.setPhoneEncrypted(AesCryptoUtils.encrypt(aesKey, request.getMobile()));
|
|
|
|
|
member.setPhoneHidden(PhoneUtils.hidePhone(request.getMobile()));
|
|
|
|
|
member.setPassword(SecurityUtils.encryptPassword(request.getPassword()));
|
|
|
|
|
member.setNickname("用户" + request.getMobile().substring(7,11));
|
|
|
|
|
member.setStatus(Constants.MEMBER_ACCOUNT_STATUS.NORMAL);
|
|
|
|
|
member.setGender(0);
|
|
|
|
|
member.setCreateTime(optDate);
|
|
|
|
|
int rows = memberMapper.insert(member);
|
|
|
|
|
if (rows < 1){
|
|
|
|
|
throw new RuntimeException("注册失败,请重试");
|
|
|
|
|
}
|
|
|
|
|
//调用微信授权业务拿到openId等
|
|
|
|
|
WechatUserAuth userToken = wechatAuthService.getUserToken(request.getWechatCode());
|
|
|
|
|
if (userToken == null){
|
|
|
|
|
throw new RuntimeException("授权失败,请重试");
|
|
|
|
|
}
|
|
|
|
|
MemberWechat memberWechat = new MemberWechat();
|
|
|
|
|
memberWechat.setMemberId(member.getId());
|
|
|
|
|
memberWechat.setOpenid(userToken.getOpenid());
|
|
|
|
|
memberWechat.setAccessToken(userToken.getAccess_token());
|
|
|
|
|
memberWechat.setExpiresIn(userToken.getExpires_in());
|
|
|
|
|
memberWechat.setRefreshToken(userToken.getRefresh_token());
|
|
|
|
|
memberWechat.setCreateTime(optDate);
|
|
|
|
|
memberWechat.setCreateBy(member.getId());
|
|
|
|
|
rows = memberWechatMapper.insert(memberWechat);
|
|
|
|
|
if (rows < 1){
|
|
|
|
|
throw new RuntimeException("注册失败,请重试");
|
|
|
|
|
}
|
|
|
|
|
//注册成功直接返回token了
|
|
|
|
|
H5LoginResponse loginResponse = getLoginResponse(member.getId());
|
|
|
|
|
response.setToken(loginResponse.getToken());
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ValidatePhoneResponse validate(String phone) {
|
|
|
|
|
ValidatePhoneResponse response = new ValidatePhoneResponse();
|
|
|
|
|
byte[] decodedBytes = Base64.getDecoder().decode(phone);
|
|
|
|
|
phone = new String(decodedBytes);
|
|
|
|
|
QueryWrapper<Member> qw = new QueryWrapper<>();
|
|
|
|
|
qw.eq("phone_encrypted", AesCryptoUtils.encrypt(aesKey, phone));
|
|
|
|
|
Member member = memberMapper.selectOne(qw);
|
|
|
|
|
if (member != null){
|
|
|
|
|
throw new RuntimeException("该手机号已被占用");
|
|
|
|
|
}
|
|
|
|
|
response.setIfSuccess(true);
|
|
|
|
|
response.setMessage("该手机号可用");
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 账号密码登录
|
|
|
|
|
* @param data
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public H5LoginResponse accountLogin(String data) {
|
|
|
|
|
if (StringUtils.isEmpty(data)){
|
|
|
|
|
throw new RuntimeException(Constants.LOGIN_INFO.WRONG);
|
|
|
|
|
}
|
|
|
|
|
// 解码 转 对象
|
|
|
|
|
H5AccountLoginRequest request = JSON.parseObject(new String(Base64Utils.decodeFromString(data)), H5AccountLoginRequest.class);
|
|
|
|
|
log.info("account login request:{}", JSONUtil.toJsonStr(request));
|
|
|
|
|
QueryWrapper<Member> qw = new QueryWrapper<>();
|
|
|
|
|
qw.eq("phone_encrypted", AesCryptoUtils.encrypt(aesKey, request.getMobile()));
|
|
|
|
|
Member member = memberMapper.selectOne(qw);
|
|
|
|
|
if (member == null){
|
|
|
|
|
throw new RuntimeException(Constants.LOGIN_INFO.WRONG);
|
|
|
|
|
}
|
|
|
|
|
validateMemberStatus(member);
|
|
|
|
|
//check 密码
|
|
|
|
|
if (!SecurityUtils.matchesPassword(request.getPassword(), member.getPassword())){
|
|
|
|
|
throw new RuntimeException(Constants.LOGIN_INFO.WRONG);
|
|
|
|
|
}
|
|
|
|
|
return getLoginResponse(member.getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public H5LoginResponse smsLogin(String data){
|
|
|
|
|
LocalDateTime optDate = LocalDateTime.now();
|
|
|
|
|
if (StringUtils.isEmpty(data)){
|
|
|
|
|
throw new RuntimeException(Constants.LOGIN_INFO.WRONG);
|
|
|
|
|
}
|
|
|
|
|
H5SmsLoginRequest request = JSON.parseObject(new String(Base64Utils.decodeFromString(data)), H5SmsLoginRequest.class);
|
|
|
|
|
//校验验证码
|
|
|
|
|
this.validateVerifyCode(request.getUuid(), request.getMobile(), request.getCode());
|
|
|
|
|
//查会员
|
|
|
|
|
QueryWrapper<Member> qw = new QueryWrapper<>();
|
|
|
|
|
qw.eq("phone_encrypted", AesCryptoUtils.encrypt(aesKey, request.getMobile()));
|
|
|
|
|
Member member = memberMapper.selectOne(qw);
|
|
|
|
|
if (member == null){
|
|
|
|
|
//新会员,注册并登录
|
|
|
|
|
member = new Member();
|
|
|
|
|
member.setPhoneEncrypted(AesCryptoUtils.encrypt(aesKey, request.getMobile()));
|
|
|
|
|
member.setPhoneHidden(PhoneUtils.hidePhone(request.getMobile()));
|
|
|
|
|
member.setNickname("用户" + request.getMobile().substring(7,11));
|
|
|
|
|
member.setStatus(Constants.MEMBER_ACCOUNT_STATUS.NORMAL);
|
|
|
|
|
member.setGender(0);
|
|
|
|
|
member.setCreateTime(optDate);
|
|
|
|
|
int rows = memberMapper.insert(member);
|
|
|
|
|
if (rows < 1){
|
|
|
|
|
throw new RuntimeException("注册失败,请重试");
|
|
|
|
|
}
|
|
|
|
|
MemberWechat memberWechat = new MemberWechat();
|
|
|
|
|
memberWechat.setMemberId(member.getId());
|
|
|
|
|
if (request.getAuthInfo() != null){
|
|
|
|
|
memberWechat.setOpenid(request.getAuthInfo().getOpenid());
|
|
|
|
|
memberWechat.setAccessToken(request.getAuthInfo().getAccess_token());
|
|
|
|
|
memberWechat.setExpiresIn(request.getAuthInfo().getExpires_in());
|
|
|
|
|
memberWechat.setRefreshToken(request.getAuthInfo().getRefresh_token());
|
|
|
|
|
}
|
|
|
|
|
memberWechat.setCreateTime(optDate);
|
|
|
|
|
memberWechat.setCreateBy(member.getId());
|
|
|
|
|
rows = memberWechatMapper.insert(memberWechat);
|
|
|
|
|
if (rows < 1){
|
|
|
|
|
throw new RuntimeException("注册失败,请重试");
|
|
|
|
|
}
|
|
|
|
|
}else {
|
|
|
|
|
//校验会员状态
|
|
|
|
|
validateMemberStatus(member);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return getLoginResponse(member.getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验会员状态
|
|
|
|
|
* @param member 会员信息
|
|
|
|
|
*/
|
|
|
|
|
private void validateMemberStatus(Member member) {
|
|
|
|
|
if (Constants.MEMBER_ACCOUNT_STATUS.FORBIDDEN == member.getStatus()){
|
|
|
|
|
throw new RuntimeException(Constants.LOGIN_INFO.FORBIDDEN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验验证码有效性
|
|
|
|
|
* @param uuid 唯一标识
|
|
|
|
|
* @param phone 手机号
|
|
|
|
|
* @param inputCode 输入的验证码
|
|
|
|
|
*/
|
|
|
|
|
private void validateVerifyCode(String uuid, String phone, String inputCode){
|
|
|
|
|
String key = uuid + "_" + phone;
|
|
|
|
|
String redisCode = redisCache.getCacheObject(key);
|
|
|
|
|
if (redisCode == null){
|
|
|
|
|
throw new RuntimeException(Constants.VERIFY_CODE_INFO.EXPIRED);
|
|
|
|
|
}else if (!redisCode.equals(inputCode)){
|
|
|
|
|
throw new RuntimeException(Constants.VERIFY_CODE_INFO.WRONG);
|
|
|
|
|
}
|
|
|
|
|
//删除缓存
|
|
|
|
|
redisCache.deleteObject(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 封装登录响应
|
|
|
|
|
* @param memberId 登录会员id
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
|
|
|
|
private H5LoginResponse getLoginResponse(Long memberId){
|
|
|
|
|
LoginMember loginMember = new LoginMember();
|
|
|
|
|
loginMember.setMemberId(memberId);
|
|
|
|
|
String token = tokenService.createMemberToken(loginMember);
|
|
|
|
|
//record登录
|
|
|
|
|
this.insert(memberId);
|
|
|
|
|
H5LoginResponse response = new H5LoginResponse();
|
|
|
|
|
response.setToken(token);
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public MemberVO getMemberInfo() {
|
|
|
|
|
Member member = (Member) LocalDataUtil.getVar(Constants.MEMBER_INFO);
|
|
|
|
|
MemberVO memberVO = new MemberVO();
|
|
|
|
|
BeanUtils.copyProperties(member, memberVO);
|
|
|
|
|
memberVO.setPhone(AesCryptoUtils.decrypt(aesKey, member.getPhoneEncrypted()));
|
|
|
|
|
QueryWrapper<MemberWechat> qw = new QueryWrapper<>();
|
|
|
|
|
qw.eq("member_id", member.getId());
|
|
|
|
|
MemberWechat memberWechat = memberWechatMapper.selectOne(qw);
|
|
|
|
|
memberVO.setOpenId(memberWechat.getOpenid());
|
|
|
|
|
return memberVO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public WechatUserAuth getWechatUserAuth(String data) {
|
|
|
|
|
BindOpenIdRequest request = JSON.parseObject(new String(Base64Utils.decodeFromString(data)), BindOpenIdRequest.class);
|
|
|
|
|
WechatUserAuth userToken = wechatAuthService.getUserToken(request.getCode());
|
|
|
|
|
if (userToken == null){
|
|
|
|
|
log.error("微信授权失败");
|
|
|
|
|
throw new RuntimeException("授权失败,请重试");
|
|
|
|
|
}
|
|
|
|
|
return userToken;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setWechatInfo(String data) {
|
|
|
|
|
WechatUserAuth authInfo = JSON.parseObject(new String(Base64Utils.decodeFromString(data)), WechatUserAuth.class);
|
|
|
|
|
Member member = (Member) LocalDataUtil.getVar(Constants.MEMBER_INFO);
|
|
|
|
|
UpdateWrapper<MemberWechat> wrapper = new UpdateWrapper<>();
|
|
|
|
|
wrapper.eq("member_id", member.getId());
|
|
|
|
|
wrapper.set("openid", authInfo.getOpenid());
|
|
|
|
|
wrapper.set("access_token", authInfo.getAccess_token());
|
|
|
|
|
wrapper.set("expires_in", authInfo.getExpires_in());
|
|
|
|
|
wrapper.set("refresh_token", authInfo.getRefresh_token());
|
|
|
|
|
wrapper.set("update_time", LocalDateTime.now());
|
|
|
|
|
wrapper.set("update_by", member.getId());
|
|
|
|
|
memberWechatMapper.update(null, wrapper);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 新增会员登录记录
|
|
|
|
|
*
|
|
|
|
|
* @param memberId 会员id
|
|
|
|
|
* @return 结果
|
|
|
|
|
*/
|
|
|
|
|
public void insert(Long memberId) {
|
|
|
|
|
Member member = memberMapper.selectById(memberId);
|
|
|
|
|
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
|
|
|
|
MemberLogininfor memberLogininfor = new MemberLogininfor();
|
|
|
|
|
memberLogininfor.setMemberId(memberId);
|
|
|
|
|
memberLogininfor.setPhone(member.getPhoneHidden());
|
|
|
|
|
memberLogininfor.setOs(userAgent.getOperatingSystem().getName());
|
|
|
|
|
memberLogininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
|
|
|
|
memberLogininfor.setBrowser(userAgent.getBrowser().getName());
|
|
|
|
|
memberLogininfor.setLoginLocation(AddressUtils.getRealAddressByIP(memberLogininfor.getIpaddr()));
|
|
|
|
|
memberLogininfor.setLoginTime(LocalDateTime.now());
|
|
|
|
|
memberLogininforMapper.insert(memberLogininfor);
|
|
|
|
|
}
|
|
|
|
|
}
|