package com.backendsys.service.B2c; import com.backendsys.entity.B2c.B2cMemberDTO; import com.backendsys.mapper.B2c.B2cMemberMapper; import com.backendsys.modules.common.config.security.utils.JwtUtil; import com.backendsys.utils.response.PageInfoResult; import com.backendsys.utils.response.Result; import com.backendsys.utils.response.ResultEnum; import com.github.pagehelper.PageHelper; import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Service public class B2cMemberServiceImpl implements B2cMemberService { @Autowired private JwtUtil jwtUtil; @Autowired private RedisTemplate redisTemplate; @Value("${REDIS_LOGIN_TOKEN_PREFIX}") private String REDIS_LOGIN_TOKEN_PREFIX; @Value("${TOKEN_DURATION_MEMBER}") private Long TOKEN_DURATION_MEMBER; @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private B2cMemberMapper b2cMemberMapper; /** * 查询 列表 */ public Map queryMemberList(Integer pageNum, Integer pageSize, B2cMemberDTO b2cMemberDTO) { // 分页查询 if (pageNum != null && pageSize != null) { PageHelper.startPage(pageNum, pageSize); PageHelper.getLocalPage().setPageSizeZero(true); } // 分页输出 (自定义) List> list = b2cMemberMapper.queryMemberList(b2cMemberDTO); PageInfoResult pageInfoResult = new PageInfoResult(list); return pageInfoResult.toMap(); } /** * 查询 详情 */ @Override public Map queryMemberDetail(Long good_member_id) { return b2cMemberMapper.queryMemberDetail(good_member_id); } /** * 创建 */ @Override @Transactional(rollbackFor = Exception.class) public Map insertMember(B2cMemberDTO b2cMemberDTO) { b2cMemberMapper.insertMember(b2cMemberDTO); return Map.of("good_member_id", b2cMemberDTO.getMember_id()); } /** * 更新 */ @Override @Transactional(rollbackFor = Exception.class) public Map updateMember(B2cMemberDTO b2cMemberDTO) { b2cMemberMapper.updateMember(b2cMemberDTO); return Map.of("good_member_id", b2cMemberDTO.getMember_id()); } /** * 删除 */ @Override @Transactional(rollbackFor = Exception.class) public Map deleteMember(B2cMemberDTO b2cMemberDTO) { b2cMemberMapper.deleteMember(b2cMemberDTO); return Map.of("good_member_id", b2cMemberDTO.getMember_id()); } /** --------------------------- Member Auth Login ----------------------------- **/ // [Method] 判断密码是否正确 private Boolean isUserPasswordValid(Map userDTO, String password) { if (userDTO == null) return false; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); return encoder.matches(password, (String) userDTO.get("password")); } /** * 查询 会员用户列表 (在线) */ @Override public List> queryMemberWithLogined(Integer pageNum, Integer pageSize, B2cMemberDTO b2cMemberDTO) { // 分页查询 if (pageNum != null && pageSize != null) { PageHelper.startPage(pageNum, pageSize); } // 获得用户最后登录的UUID Set redisKeys = redisTemplate.keys("token:*"); // 获得UUID数组 Set last_login_uuids = (Set) redisKeys.stream().map( e -> String.valueOf(e).replace(REDIS_LOGIN_TOKEN_PREFIX, "") ).collect(Collectors.toSet()); return b2cMemberMapper.queryMemberWithLogined(last_login_uuids); } /** * 登录 (会员用户) * @param b2cMemberDTO(username, password) * @return { token, b2cMemberDTO } */ @Override public Result login(HttpServletRequest request, B2cMemberDTO b2cMemberDTO) { String phone = b2cMemberDTO.getPhone(); String password = b2cMemberDTO.getPassword(); // [Method] 判断 用户是否存在 && 密码是否正确 Map b2cMemberDTOSimple = b2cMemberMapper.queryMemberByIdOrName(null, phone); if (!(b2cMemberDTOSimple != null && isUserPasswordValid(b2cMemberDTOSimple, password))) { return Result.error(ResultEnum.INVALID_CREDENTIALS.getCode(), "用户名或密码错误"); } // [登录成功] // 1.[查询] 用户信息详情 String uuid = String.valueOf(UUID.randomUUID()); Long memberId = (Long) b2cMemberDTOSimple.get("id"); Map b2cMemberDetail = b2cMemberMapper.queryMemberDetail(memberId); // [Redis] 删除旧 Redis Key String old_uuid = (String) b2cMemberDetail.get("last_login_uuid"); if (old_uuid != null) { stringRedisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + old_uuid); } //System.out.println(b2cMemberDetail); // 生成 Token 过期时间 (存入Token/带出Result返回值) Date tokenExpiration = new Date((new Date()).getTime() + TOKEN_DURATION_MEMBER); b2cMemberDetail.put("token_expiration", tokenExpiration); // 生成 Token b2cMemberDetail.put("last_login_uuid", uuid); String token = jwtUtil.createMemberToken(b2cMemberDetail); // 存入 Redis:Token、Token过期时间 // String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + memberId; String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + uuid; stringRedisTemplate.opsForValue().set(tokenRedisKey, token, TOKEN_DURATION_MEMBER, TimeUnit.MILLISECONDS); // 6.[更新] 用户最后登录时间、登录IP B2cMemberDTO b2cMemberLastLogin = new B2cMemberDTO(); b2cMemberLastLogin.setMember_id(memberId); b2cMemberLastLogin.setLast_login_ip(request.getRemoteAddr()); b2cMemberLastLogin.setLast_login_uuid(uuid); b2cMemberLastLogin.setLast_login_time(LocalDateTime.now()); b2cMemberMapper.updateMember(b2cMemberLastLogin); // 7.[格式化] 将 Token 拼接到输出结果 Map result = new LinkedHashMap<>(b2cMemberDetail); result.remove("del_flag"); result.put("token", token); return Result.success(result); } }