B2cMemberServiceImpl.java 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package com.backendsys.service.B2c;
  2. import com.backendsys.entity.B2c.B2cMemberDTO;
  3. import com.backendsys.mapper.B2c.B2cMemberMapper;
  4. import com.backendsys.modules.common.config.security.utils.JwtUtil;
  5. import com.backendsys.utils.response.PageInfoResult;
  6. import com.backendsys.utils.response.Result;
  7. import com.backendsys.utils.response.ResultEnum;
  8. import com.github.pagehelper.PageHelper;
  9. import jakarta.servlet.http.HttpServletRequest;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.beans.factory.annotation.Value;
  12. import org.springframework.data.redis.core.RedisTemplate;
  13. import org.springframework.data.redis.core.StringRedisTemplate;
  14. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  15. import org.springframework.stereotype.Service;
  16. import org.springframework.transaction.annotation.Transactional;
  17. import java.time.LocalDateTime;
  18. import java.util.*;
  19. import java.util.concurrent.TimeUnit;
  20. import java.util.stream.Collectors;
  21. @Service
  22. public class B2cMemberServiceImpl implements B2cMemberService {
  23. @Autowired
  24. private JwtUtil jwtUtil;
  25. @Autowired
  26. private RedisTemplate redisTemplate;
  27. @Value("${REDIS_LOGIN_TOKEN_PREFIX}")
  28. private String REDIS_LOGIN_TOKEN_PREFIX;
  29. @Value("${TOKEN_DURATION_MEMBER}")
  30. private Long TOKEN_DURATION_MEMBER;
  31. @Autowired
  32. private StringRedisTemplate stringRedisTemplate;
  33. @Autowired
  34. private B2cMemberMapper b2cMemberMapper;
  35. /**
  36. * 查询 列表
  37. */
  38. public Map<String, Object> queryMemberList(Integer pageNum, Integer pageSize, B2cMemberDTO b2cMemberDTO) {
  39. // 分页查询
  40. if (pageNum != null && pageSize != null) {
  41. PageHelper.startPage(pageNum, pageSize);
  42. PageHelper.getLocalPage().setPageSizeZero(true);
  43. }
  44. // 分页输出 (自定义)
  45. List<Map<String, Object>> list = b2cMemberMapper.queryMemberList(b2cMemberDTO);
  46. PageInfoResult pageInfoResult = new PageInfoResult(list);
  47. return pageInfoResult.toMap();
  48. }
  49. /**
  50. * 查询 详情
  51. */
  52. @Override
  53. public Map<String, Object> queryMemberDetail(Long good_member_id) {
  54. return b2cMemberMapper.queryMemberDetail(good_member_id);
  55. }
  56. /**
  57. * 创建
  58. */
  59. @Override
  60. @Transactional(rollbackFor = Exception.class)
  61. public Map<String, Object> insertMember(B2cMemberDTO b2cMemberDTO) {
  62. b2cMemberMapper.insertMember(b2cMemberDTO);
  63. return Map.of("good_member_id", b2cMemberDTO.getMember_id());
  64. }
  65. /**
  66. * 更新
  67. */
  68. @Override
  69. @Transactional(rollbackFor = Exception.class)
  70. public Map<String, Object> updateMember(B2cMemberDTO b2cMemberDTO) {
  71. b2cMemberMapper.updateMember(b2cMemberDTO);
  72. return Map.of("good_member_id", b2cMemberDTO.getMember_id());
  73. }
  74. /**
  75. * 删除
  76. */
  77. @Override
  78. @Transactional(rollbackFor = Exception.class)
  79. public Map<String, Object> deleteMember(B2cMemberDTO b2cMemberDTO) {
  80. b2cMemberMapper.deleteMember(b2cMemberDTO);
  81. return Map.of("good_member_id", b2cMemberDTO.getMember_id());
  82. }
  83. /** --------------------------- Member Auth Login ----------------------------- **/
  84. // [Method] 判断密码是否正确
  85. private Boolean isUserPasswordValid(Map<String, Object> userDTO, String password) {
  86. if (userDTO == null) return false;
  87. BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
  88. return encoder.matches(password, (String) userDTO.get("password"));
  89. }
  90. /**
  91. * 查询 会员用户列表 (在线)
  92. */
  93. @Override
  94. public List<Map<String, Object>> queryMemberWithLogined(Integer pageNum, Integer pageSize, B2cMemberDTO b2cMemberDTO) {
  95. // 分页查询
  96. if (pageNum != null && pageSize != null) {
  97. PageHelper.startPage(pageNum, pageSize);
  98. }
  99. // 获得用户最后登录的UUID
  100. Set redisKeys = redisTemplate.keys("token:*");
  101. // 获得UUID数组
  102. Set last_login_uuids = (Set) redisKeys.stream().map(
  103. e -> String.valueOf(e).replace(REDIS_LOGIN_TOKEN_PREFIX, "")
  104. ).collect(Collectors.toSet());
  105. return b2cMemberMapper.queryMemberWithLogined(last_login_uuids);
  106. }
  107. /**
  108. * 登录 (会员用户)
  109. * @param b2cMemberDTO(username, password)
  110. * @return { token, b2cMemberDTO }
  111. */
  112. @Override
  113. public Result login(HttpServletRequest request, B2cMemberDTO b2cMemberDTO) {
  114. String phone = b2cMemberDTO.getPhone();
  115. String password = b2cMemberDTO.getPassword();
  116. // [Method] 判断 用户是否存在 && 密码是否正确
  117. Map<String, Object> b2cMemberDTOSimple = b2cMemberMapper.queryMemberByIdOrName(null, phone);
  118. if (!(b2cMemberDTOSimple != null && isUserPasswordValid(b2cMemberDTOSimple, password))) {
  119. return Result.error(ResultEnum.INVALID_CREDENTIALS.getCode(), "用户名或密码错误");
  120. }
  121. // [登录成功]
  122. // 1.[查询] 用户信息详情
  123. String uuid = String.valueOf(UUID.randomUUID());
  124. Long memberId = (Long) b2cMemberDTOSimple.get("id");
  125. Map<String, Object> b2cMemberDetail = b2cMemberMapper.queryMemberDetail(memberId);
  126. // [Redis] 删除旧 Redis Key
  127. String old_uuid = (String) b2cMemberDetail.get("last_login_uuid");
  128. if (old_uuid != null) {
  129. stringRedisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + old_uuid);
  130. }
  131. //System.out.println(b2cMemberDetail);
  132. // 生成 Token 过期时间 (存入Token/带出Result返回值)
  133. Date tokenExpiration = new Date((new Date()).getTime() + TOKEN_DURATION_MEMBER);
  134. b2cMemberDetail.put("token_expiration", tokenExpiration);
  135. // 生成 Token
  136. b2cMemberDetail.put("last_login_uuid", uuid);
  137. String token = jwtUtil.createMemberToken(b2cMemberDetail);
  138. // 存入 Redis:Token、Token过期时间
  139. // String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + memberId;
  140. String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + uuid;
  141. stringRedisTemplate.opsForValue().set(tokenRedisKey, token, TOKEN_DURATION_MEMBER, TimeUnit.MILLISECONDS);
  142. // 6.[更新] 用户最后登录时间、登录IP
  143. B2cMemberDTO b2cMemberLastLogin = new B2cMemberDTO();
  144. b2cMemberLastLogin.setMember_id(memberId);
  145. b2cMemberLastLogin.setLast_login_ip(request.getRemoteAddr());
  146. b2cMemberLastLogin.setLast_login_uuid(uuid);
  147. b2cMemberLastLogin.setLast_login_time(LocalDateTime.now());
  148. b2cMemberMapper.updateMember(b2cMemberLastLogin);
  149. // 7.[格式化] 将 Token 拼接到输出结果
  150. Map<String, Object> result = new LinkedHashMap<>(b2cMemberDetail);
  151. result.remove("del_flag");
  152. result.put("token", token);
  153. return Result.success(result);
  154. }
  155. }