|
@@ -0,0 +1,376 @@
|
|
|
+package cn.aid.apiweb.service.user;
|
|
|
+
|
|
|
+import cn.aid.apiweb.code.ApiWebCode;
|
|
|
+import cn.aid.apiweb.service.product.ProductClient;
|
|
|
+import cn.aid.apiweb.utils.SecurityManager;
|
|
|
+import cn.aid.common.utils.api.model.APIResult;
|
|
|
+import cn.aid.common.utils.api.model.BaseCode;
|
|
|
+import cn.aid.common.utils.api.page.Page;
|
|
|
+import cn.aid.common.utils.constant.PlatForm;
|
|
|
+import cn.aid.common.utils.constant.RedisKey;
|
|
|
+import cn.aid.common.utils.service.RedisService;
|
|
|
+import cn.aid.data.api.app.dto.LoginInfoDTO;
|
|
|
+import cn.aid.data.api.app.vo.DeviceUserVo;
|
|
|
+import cn.aid.data.api.app.vo.UserInfoVo;
|
|
|
+import cn.aid.data.api.user.dto.TerminalDeviceDTO;
|
|
|
+import cn.aid.data.api.user.dto.UserDeviceDTO;
|
|
|
+import cn.aid.data.api.user.vo.TerminalDeviceVo;
|
|
|
+import cn.aid.data.api.user.vo.TerminalUserVo;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.commons.lang3.time.DateUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.data.domain.Sort;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class UserService
|
|
|
+{
|
|
|
+
|
|
|
+ public final static String USER_FORMAT_KEY = RedisKey.USER_FORMAT_KEY;
|
|
|
+
|
|
|
+ @Value(value = "${token.expiration:604800}")
|
|
|
+ private int expiration;
|
|
|
+
|
|
|
+ @Value(value = "${login.web.force.interval:2400}")
|
|
|
+ private int forceLoginInterval;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private UserClient userClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ProductClient productClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisService redisService;
|
|
|
+
|
|
|
+ public APIResult<UserInfoVo> login(LoginInfoDTO loginInfoDTO)
|
|
|
+ {
|
|
|
+ String deviceCode = loginInfoDTO.getDeviceCode();
|
|
|
+ String deviceModel = loginInfoDTO.getDeviceModel();
|
|
|
+ String deviceMfrs = loginInfoDTO.getDeviceMfrs();
|
|
|
+ String deviceName = loginInfoDTO.getDeviceName();
|
|
|
+ String deviceType = loginInfoDTO.getDeviceType();
|
|
|
+
|
|
|
+ String merchant = loginInfoDTO.getMerchant();
|
|
|
+ String eid = loginInfoDTO.getEid();
|
|
|
+ String loginPassword = loginInfoDTO.getPassword();
|
|
|
+ log.info("user login start, user={}", JSON.toJSONString(loginInfoDTO));
|
|
|
+
|
|
|
+ APIResult<TerminalUserVo> userVoAPIResult = userClient.loadUserByEid(eid);
|
|
|
+ TerminalUserVo userVo = userVoAPIResult.getData();
|
|
|
+ if (!userVoAPIResult.getSuccess())
|
|
|
+ {
|
|
|
+ log.error("load user api error");
|
|
|
+ return APIResult.error(ApiWebCode.LOGIN_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ //操作用户登录设备信息
|
|
|
+ if (deviceName != null && !"".equals(deviceName.trim()))
|
|
|
+ {
|
|
|
+ String uid = userVo.getId();
|
|
|
+ UserDeviceDTO dto = new UserDeviceDTO();
|
|
|
+ dto.setDeviceCode(deviceCode);
|
|
|
+ dto.setDeviceModel(deviceModel);
|
|
|
+ dto.setDeviceType(deviceType);
|
|
|
+ dto.setDeviceMfrs(deviceMfrs);
|
|
|
+ dto.setDeviceName(deviceName);
|
|
|
+
|
|
|
+ int opRet = userClient.opUserDevice(uid,dto);
|
|
|
+ if (opRet == 0)
|
|
|
+ {
|
|
|
+ log.error("Failed to operated user device with[uid={},deviceCode={},deviceModel={},deviceName={}]", uid, deviceCode, deviceModel, deviceName);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ log.info("Succeed to operating user device with[uid={},deviceCode={},deviceModel={},deviceName={}]", uid, deviceCode, deviceModel, deviceName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String storePassword = userVo.getPassword();
|
|
|
+ if (!SecurityManager.validate(loginPassword, storePassword))
|
|
|
+ {
|
|
|
+ log.error("密码校验错误, loginPassword={}, storePassword={}", loginPassword, storePassword);
|
|
|
+ return APIResult.error(ApiWebCode.PASSWORD_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+/* if(StringUtils.isNotBlank(merchant) && !merchant.equals(userVo.getMerchantSimple())){
|
|
|
+ log.error("渠道校验错误, requestMerchant={}, userMerchant={}", merchant, userVo.getMerchantSimple());
|
|
|
+ return APIResult.error(ApiWebCode.LOGIN_ERROR);
|
|
|
+ }*/
|
|
|
+
|
|
|
+ String userId = userVo.getId();
|
|
|
+ String ip = loginInfoDTO.getIp();
|
|
|
+ String terminal = loginInfoDTO.getTerminal();
|
|
|
+
|
|
|
+ // 网页端登陆在40分钟后可以踢掉对方网页登陆
|
|
|
+ if (PlatForm.WEB.equals(terminal))
|
|
|
+ {
|
|
|
+ String key = getUserFormatKey(userId);
|
|
|
+ DeviceUserVo deviceUserVo = (DeviceUserVo) redisService.get(key);
|
|
|
+ if (deviceUserVo != null)
|
|
|
+ {
|
|
|
+ Date refreshAt = deviceUserVo.getRefreshAt();
|
|
|
+ String lastTerminal = deviceUserVo.getTerminal();
|
|
|
+ if (DateUtils.addSeconds(refreshAt, forceLoginInterval).before(new Date()) && PlatForm.WEB.equals(lastTerminal))
|
|
|
+ {
|
|
|
+ log.info("网页端强制登陆, deviceCode={}, eid={}", deviceCode, eid);
|
|
|
+ APIResult<Boolean> forceLogoutResult = this.logout(userId);
|
|
|
+ if (!forceLogoutResult.getSuccess())
|
|
|
+ {
|
|
|
+ return APIResult.error(new BaseCode(forceLogoutResult.getCode(), forceLogoutResult.getMessage()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ TerminalDeviceVo deviceVo = this.bind(userId, deviceCode, merchant, ip, terminal);
|
|
|
+ if (deviceVo == null)
|
|
|
+ {
|
|
|
+ return APIResult.error(ApiWebCode.DEVICE_BOUND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ // assembly device and use info
|
|
|
+ DeviceUserVo deviceUserVo = toDeviceUserVo(userVo, deviceVo);
|
|
|
+ // 保存至缓存
|
|
|
+ this.save(deviceUserVo);
|
|
|
+
|
|
|
+ UserInfoVo userInfoVo = toUserInfoVo(deviceUserVo, true);
|
|
|
+ log.info("user={} login success, userInfo={}", eid, JSON.toJSONString(userInfoVo));
|
|
|
+
|
|
|
+ return APIResult.ok(userInfoVo);
|
|
|
+ }
|
|
|
+
|
|
|
+ public APIResult<Boolean> logout(String userId)
|
|
|
+ {
|
|
|
+ APIResult<Boolean> unbindResult = userClient.deviceUnbind(userId);
|
|
|
+ if (!unbindResult.getSuccess())
|
|
|
+ {
|
|
|
+ return APIResult.error(ApiWebCode.LOGOUT_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ String key = getUserFormatKey(userId);
|
|
|
+ redisService.delete(key);
|
|
|
+
|
|
|
+ return APIResult.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ public TerminalDeviceVo bind(String userId, String deviceCode, String merchant, String ip, String terminal)
|
|
|
+ {
|
|
|
+ TerminalDeviceDTO deviceDTO = new TerminalDeviceDTO();
|
|
|
+ deviceDTO.setUserId(userId);
|
|
|
+ deviceDTO.setDeviceCode(deviceCode);
|
|
|
+ deviceDTO.setMerchant(merchant);
|
|
|
+ deviceDTO.setIp(ip);
|
|
|
+ deviceDTO.setTerminal(terminal);
|
|
|
+ APIResult<TerminalDeviceVo> apiResult = userClient.deviceBind(deviceDTO);
|
|
|
+ if (!apiResult.getSuccess())
|
|
|
+ {
|
|
|
+ log.error("bind user api error");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return apiResult.getData();
|
|
|
+ }
|
|
|
+
|
|
|
+ // load user and device info
|
|
|
+ public DeviceUserVo load(String uid)
|
|
|
+ {
|
|
|
+ String key = getUserFormatKey(uid);
|
|
|
+ DeviceUserVo deviceUserVo = (DeviceUserVo) redisService.get(key);
|
|
|
+ if (deviceUserVo == null)
|
|
|
+ {
|
|
|
+ deviceUserVo = getDeviceUserVo(uid);
|
|
|
+ }
|
|
|
+ if (deviceUserVo != null)
|
|
|
+ {
|
|
|
+ this.save(deviceUserVo);
|
|
|
+ }
|
|
|
+ return deviceUserVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ public UserInfoVo getUserInfo(String uid)
|
|
|
+ {
|
|
|
+ DeviceUserVo deviceUserVo = this.load(uid);
|
|
|
+ return toUserInfoVo(deviceUserVo, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ public DeviceUserVo getDeviceUserVo(String uid)
|
|
|
+ {
|
|
|
+ APIResult<TerminalDeviceVo> deviceAPIResult = userClient.findDeviceByUid(uid);
|
|
|
+ if (!deviceAPIResult.getSuccess())
|
|
|
+ {
|
|
|
+ log.error("load device api error, {}", deviceAPIResult.getMessage());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ TerminalDeviceVo deviceVo = deviceAPIResult.getData();
|
|
|
+ // load user info
|
|
|
+ APIResult<TerminalUserVo> userAPIResult = userClient.findUserById(uid);
|
|
|
+ if (!userAPIResult.getSuccess())
|
|
|
+ {
|
|
|
+ log.error("load user api error, {}", userAPIResult.getMessage());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ TerminalUserVo userVo = userAPIResult.getData();
|
|
|
+
|
|
|
+ return toDeviceUserVo(userVo, deviceVo);
|
|
|
+ }
|
|
|
+
|
|
|
+ public APIResult<UserInfoVo> refresh(String deviceCode, String merchant, Boolean force)
|
|
|
+ {
|
|
|
+
|
|
|
+ List<TerminalDeviceVo> deviceVoList = userClient.findByDeviceCode(deviceCode);
|
|
|
+ if (CollectionUtils.isEmpty(deviceVoList))
|
|
|
+ {
|
|
|
+ log.error("device code not bind any eid! deviceCode={}", deviceCode);
|
|
|
+ return APIResult.error(ApiWebCode.INVALID_TOKEN);
|
|
|
+ }
|
|
|
+
|
|
|
+ TerminalDeviceVo deviceVo = null;
|
|
|
+
|
|
|
+ for (TerminalDeviceVo dv : deviceVoList)
|
|
|
+ {
|
|
|
+ //判断当前鉴权账号
|
|
|
+ if (StringUtils.isBlank(dv.getMerchant()))
|
|
|
+ {
|
|
|
+ //如果设备渠道code为空,则设置为当前渠道code
|
|
|
+ dv.setMerchant(merchant);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //更新数据库
|
|
|
+ updateDeviceBind(dv);
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ return APIResult.error(ApiWebCode.DEVICE_BOUND_ERROR);
|
|
|
+ }
|
|
|
+ deviceVo = dv;
|
|
|
+ }
|
|
|
+ else if (StringUtils.isNotBlank(merchant) && merchant.equals(dv.getMerchant()))
|
|
|
+ {
|
|
|
+ deviceVo = dv;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (null == deviceVo)
|
|
|
+ {
|
|
|
+ log.error("by device code not find this merchant! deviceCode={},merchant={}", deviceCode, merchant);
|
|
|
+ return APIResult.error(ApiWebCode.INVALID_TOKEN);
|
|
|
+ }
|
|
|
+
|
|
|
+ String uid = deviceVo.getUserId();
|
|
|
+
|
|
|
+ DeviceUserVo deviceUserVo;
|
|
|
+ if (force)
|
|
|
+ {
|
|
|
+ APIResult<TerminalUserVo> userAPIResult = userClient.findUserById(uid);
|
|
|
+ if (!userAPIResult.getSuccess())
|
|
|
+ {
|
|
|
+ log.error("load user api error, {}", userAPIResult.getMessage());
|
|
|
+ return APIResult.error(ApiWebCode.INVALID_TOKEN);
|
|
|
+ }
|
|
|
+ TerminalUserVo userVo = userAPIResult.getData();
|
|
|
+ deviceUserVo = toDeviceUserVo(userVo, deviceVo);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ String key = getUserFormatKey(uid);
|
|
|
+ deviceUserVo = (DeviceUserVo) redisService.get(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 无论怎样都能成功刷新
|
|
|
+ if (deviceUserVo == null)
|
|
|
+ {
|
|
|
+ deviceUserVo = getDeviceUserVo(uid);
|
|
|
+ }
|
|
|
+
|
|
|
+ refreshToken(deviceUserVo);
|
|
|
+ save(deviceUserVo);
|
|
|
+
|
|
|
+ UserInfoVo userInfoVo = toUserInfoVo(deviceUserVo, true);
|
|
|
+ return APIResult.ok(userInfoVo);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateDeviceBind(TerminalDeviceVo terminalDeviceVo)
|
|
|
+ {
|
|
|
+ TerminalDeviceDTO deviceDTO = new TerminalDeviceDTO();
|
|
|
+ deviceDTO.setId(terminalDeviceVo.getId());
|
|
|
+ deviceDTO.setMerchant(terminalDeviceVo.getMerchant());
|
|
|
+ deviceDTO.setDeviceCode(terminalDeviceVo.getDeviceCode());
|
|
|
+ deviceDTO.setUserId(terminalDeviceVo.getUserId());
|
|
|
+ APIResult apiResult = userClient.updateDeviceBind(deviceDTO);
|
|
|
+ if (!apiResult.getSuccess())
|
|
|
+ {
|
|
|
+ log.error("update bind user api error");
|
|
|
+ throw new RuntimeException("update bind user api error");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // cache user and device info
|
|
|
+ public void save(DeviceUserVo deviceUserVo)
|
|
|
+ {
|
|
|
+ String key = getUserFormatKey(deviceUserVo.getUid());
|
|
|
+ redisService.set(key, deviceUserVo);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getUserFormatKey(String uid)
|
|
|
+ {
|
|
|
+ return String.format(USER_FORMAT_KEY, uid);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static UserInfoVo toUserInfoVo(DeviceUserVo deviceUserVo, Boolean withToken)
|
|
|
+ {
|
|
|
+ UserInfoVo userInfoVo = new UserInfoVo();
|
|
|
+ userInfoVo.setUid(deviceUserVo.getUid());
|
|
|
+ userInfoVo.setEid(deviceUserVo.getEid());
|
|
|
+ userInfoVo.setName(deviceUserVo.getName());
|
|
|
+ userInfoVo.setMerchantName(deviceUserVo.getMerchantName());
|
|
|
+ userInfoVo.setMerchantContactName(deviceUserVo.getMerchantContactName());
|
|
|
+ userInfoVo.setMerchantContactMobile(deviceUserVo.getMerchantContactMobile());
|
|
|
+ if (withToken)
|
|
|
+ {
|
|
|
+ userInfoVo.setToken(deviceUserVo.getToken());
|
|
|
+ }
|
|
|
+ return userInfoVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ public DeviceUserVo toDeviceUserVo(TerminalUserVo userVo, TerminalDeviceVo deviceVo)
|
|
|
+ {
|
|
|
+ DeviceUserVo deviceUserVo = new DeviceUserVo();
|
|
|
+ deviceUserVo.setUid(userVo.getId());
|
|
|
+ deviceUserVo.setEid(userVo.getCode());
|
|
|
+ deviceUserVo.setPassword(userVo.getPassword());
|
|
|
+ deviceUserVo.setName(userVo.getCityName() + userVo.getZoneName() + userVo.getName());
|
|
|
+ deviceUserVo.setDeviceCode(deviceVo.getDeviceCode());
|
|
|
+ deviceUserVo.setMerchantId(userVo.getMerchantId());
|
|
|
+ deviceUserVo.setMerchantName(userVo.getMerchantName());
|
|
|
+ deviceUserVo.setMerchantContactName(userVo.getMerchantContactName());
|
|
|
+ deviceUserVo.setMerchantContactMobile(userVo.getMerchantContactMobile());
|
|
|
+ deviceUserVo.setTerminal(deviceVo.getTerminal());
|
|
|
+ refreshToken(deviceUserVo);
|
|
|
+ return deviceUserVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void refreshToken(DeviceUserVo deviceUserVo)
|
|
|
+ {
|
|
|
+ String token = SecurityManager.generateToken(deviceUserVo.getPassword());
|
|
|
+ log.info("token ======================= ,{}", token);
|
|
|
+ Date nowTime = new Date();
|
|
|
+ Date expireAt = DateUtils.addSeconds(nowTime, this.expiration);
|
|
|
+ deviceUserVo.setToken(token);
|
|
|
+ deviceUserVo.setExpireAt(expireAt);
|
|
|
+ deviceUserVo.setRefreshAt(nowTime);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|