第四次课程提交 认证登录和用户的初始化
This commit is contained in:
parent
aabcd49dfd
commit
1378baeac6
|
@ -14,9 +14,8 @@ public class AuthContextHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Long getUserId() {
|
public static Long getUserId() {
|
||||||
//return userId.get();
|
return userId.get();
|
||||||
//TODO 暂时硬编码为1,后续做完登录验证后再修改
|
|
||||||
return 1L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeUserId() {
|
public static void removeUserId() {
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,15 @@
|
||||||
|
package com.atguigu.tingshu.common.login;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
public @interface GuiGuLogin {
|
||||||
|
/**
|
||||||
|
* 改接口调用是否需要必须登录
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean required() default true;
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.atguigu.tingshu.common.login;
|
||||||
|
|
||||||
|
import com.atguigu.tingshu.common.constant.RedisConstant;
|
||||||
|
import com.atguigu.tingshu.common.execption.GuiguException;
|
||||||
|
import com.atguigu.tingshu.common.result.ResultCodeEnum;
|
||||||
|
import com.atguigu.tingshu.common.util.AuthContextHolder;
|
||||||
|
import com.atguigu.tingshu.vo.user.UserInfoVo;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: atguigu
|
||||||
|
* @create: 2025-07-21 09:49
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class GuiGuLoginAspect {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为了代码规范:认证状态校验注解只能用在api包下,且只有使用@GuiGuLogin注解的方法才能被增强
|
||||||
|
*
|
||||||
|
* @param pjp 目标方法对象
|
||||||
|
* @return
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
@Around("execution(* com.atguigu.tingshu.*.api.*.*(..)) && @annotation(guiGuLogin)")
|
||||||
|
public Object doBasicProfiling(ProceedingJoinPoint pjp, GuiGuLogin guiGuLogin) throws Throwable {
|
||||||
|
log.info("一、前置逻辑");
|
||||||
|
//1.获取用户令牌,用于查询redis中用户基本信息
|
||||||
|
//1.1 获取请求对象
|
||||||
|
//1.1.1 获取请求上下文对象 RequestAttributes是接口
|
||||||
|
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||||
|
//1.1.2 获取请求对象 ServletRequestAttributes是实现类
|
||||||
|
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
|
||||||
|
HttpServletRequest request = servletRequestAttributes.getRequest();
|
||||||
|
|
||||||
|
//1.2 获取请求头:token
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
|
||||||
|
//2.查询当时在登录成功后存入redis中用户基本信息 UserInfoVo
|
||||||
|
//2.1. 构建查询用户信息Redis的Key 注意:一定要跟登录成功存入Redis一致
|
||||||
|
String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
|
||||||
|
//2.2 查询Redis中用户信息
|
||||||
|
UserInfoVo userInfoVo = (UserInfoVo) redisTemplate.opsForValue().get(loginKey);
|
||||||
|
|
||||||
|
//3.如果目标方法要求必须登录但查询Redis用户信息为空,抛出登录异常,响应业务状态码208
|
||||||
|
if (guiGuLogin.required() && userInfoVo == null) {
|
||||||
|
log.error("用户未登录,引导用户登录");
|
||||||
|
throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
//4.如果查询Redis存在用户信息,将用户ID存入ThreadLocal中方便JavaEE三层任意层获取用户ID
|
||||||
|
if (userInfoVo != null) {
|
||||||
|
AuthContextHolder.setUserId(userInfoVo.getId());
|
||||||
|
}
|
||||||
|
log.info("二、目标方法执行");
|
||||||
|
Object retVal = pjp.proceed();
|
||||||
|
log.info("三、后置逻辑");
|
||||||
|
|
||||||
|
//5.清理ThreadLocal防止内存泄漏
|
||||||
|
AuthContextHolder.removeUserId();
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,49 @@
|
||||||
|
package com.atguigu.tingshu.account.receiver;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.atguigu.tingshu.account.service.UserAccountService;
|
||||||
|
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
|
||||||
|
import com.rabbitmq.client.Channel;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.Exchange;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.Queue;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.QueueBinding;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: atguigu
|
||||||
|
* @create: 2025-07-21 14:31
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class AccountReceiver {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserAccountService userAccountService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户首次登录,初始化账户信息
|
||||||
|
* @param map
|
||||||
|
* @param channel
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
@RabbitListener(bindings = @QueueBinding(
|
||||||
|
exchange = @Exchange(value = MqConst.EXCHANGE_USER, durable = "true"),
|
||||||
|
value = @Queue(value = MqConst.QUEUE_USER_REGISTER, durable = "true"),
|
||||||
|
key = MqConst.ROUTING_USER_REGISTER
|
||||||
|
))
|
||||||
|
public void initUserAccountListener(Map<String, Object> map, Channel channel, Message message) {
|
||||||
|
if (CollUtil.isNotEmpty(map)) {
|
||||||
|
log.info("用户首次登录,初始化账户信息,消息:{}", map);
|
||||||
|
userAccountService.saveUserAccount(map);
|
||||||
|
}
|
||||||
|
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,23 @@ package com.atguigu.tingshu.account.service;
|
||||||
import com.atguigu.tingshu.model.account.UserAccount;
|
import com.atguigu.tingshu.model.account.UserAccount;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface UserAccountService extends IService<UserAccount> {
|
public interface UserAccountService extends IService<UserAccount> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存账户记录
|
||||||
|
* @param map
|
||||||
|
*/
|
||||||
|
|
||||||
|
void saveUserAccount(Map<String, Object> map);
|
||||||
|
/**
|
||||||
|
* 保存账户变动日志(例如:充值,消费)
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param title 内容
|
||||||
|
* @param amount 金额
|
||||||
|
* @param orderNo 订单编号
|
||||||
|
*/
|
||||||
|
void saveUserAccountDetail(Long userId, String title, BigDecimal amount, String orderNo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
package com.atguigu.tingshu.account.service.impl;
|
package com.atguigu.tingshu.account.service.impl;
|
||||||
|
|
||||||
|
import com.atguigu.tingshu.account.mapper.UserAccountDetailMapper;
|
||||||
import com.atguigu.tingshu.account.mapper.UserAccountMapper;
|
import com.atguigu.tingshu.account.mapper.UserAccountMapper;
|
||||||
import com.atguigu.tingshu.account.service.UserAccountService;
|
import com.atguigu.tingshu.account.service.UserAccountService;
|
||||||
|
import com.atguigu.tingshu.common.constant.SystemConstant;
|
||||||
import com.atguigu.tingshu.model.account.UserAccount;
|
import com.atguigu.tingshu.model.account.UserAccount;
|
||||||
|
import com.atguigu.tingshu.model.account.UserAccountDetail;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
|
@ -15,5 +22,40 @@ public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserA
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserAccountMapper userAccountMapper;
|
private UserAccountMapper userAccountMapper;
|
||||||
|
@Autowired
|
||||||
|
private UserAccountDetailMapper userAccountDetailMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void saveUserAccount(Map<String, Object> map) {
|
||||||
|
//1.新增账户记录
|
||||||
|
Long userId = (Long) map.get("userId");
|
||||||
|
BigDecimal amount = (BigDecimal) map.get("amount");
|
||||||
|
UserAccount userAccount = new UserAccount();
|
||||||
|
userAccount.setUserId(userId);
|
||||||
|
userAccount.setTotalAmount(amount);
|
||||||
|
userAccount.setLockAmount(BigDecimal.ZERO);
|
||||||
|
userAccount.setAvailableAmount(amount);
|
||||||
|
userAccount.setTotalIncomeAmount(amount);
|
||||||
|
userAccount.setTotalPayAmount(BigDecimal.ZERO);
|
||||||
|
int rows = userAccountMapper.insert(userAccount);
|
||||||
|
if (rows > 0) {
|
||||||
|
String title = (String) map.get("title");
|
||||||
|
String orderNo = (String) map.get("orderNo");
|
||||||
|
//2.保存账户变动日志
|
||||||
|
this.saveUserAccountDetail(userId, title, amount, orderNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void saveUserAccountDetail(Long userId, String title, BigDecimal amount, String orderNo) {
|
||||||
|
UserAccountDetail userAccountDetail = new UserAccountDetail();
|
||||||
|
userAccountDetail.setUserId(userId);
|
||||||
|
userAccountDetail.setTitle(title);
|
||||||
|
userAccountDetail.setTradeType(SystemConstant.ACCOUNT_TRADE_TYPE_DEPOSIT);
|
||||||
|
userAccountDetail.setAmount(amount);
|
||||||
|
userAccountDetail.setOrderNo(orderNo);
|
||||||
|
userAccountDetailMapper.insert(userAccountDetail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.atguigu.tingshu.album.api;
|
package com.atguigu.tingshu.album.api;
|
||||||
|
|
||||||
import com.atguigu.tingshu.album.service.AlbumInfoService;
|
import com.atguigu.tingshu.album.service.AlbumInfoService;
|
||||||
|
import com.atguigu.tingshu.common.login.GuiGuLogin;
|
||||||
import com.atguigu.tingshu.common.result.Result;
|
import com.atguigu.tingshu.common.result.Result;
|
||||||
import com.atguigu.tingshu.common.util.AuthContextHolder;
|
import com.atguigu.tingshu.common.util.AuthContextHolder;
|
||||||
import com.atguigu.tingshu.model.album.AlbumInfo;
|
import com.atguigu.tingshu.model.album.AlbumInfo;
|
||||||
|
@ -28,6 +29,7 @@ public class AlbumInfoApiController {
|
||||||
|
|
||||||
|
|
||||||
@Operation(summary = "新建专辑信息")
|
@Operation(summary = "新建专辑信息")
|
||||||
|
@GuiGuLogin
|
||||||
@PostMapping("/albumInfo/saveAlbumInfo")
|
@PostMapping("/albumInfo/saveAlbumInfo")
|
||||||
public Result saveAlbumInfo(@Validated @RequestBody AlbumInfoVo albumInfoVo) {
|
public Result saveAlbumInfo(@Validated @RequestBody AlbumInfoVo albumInfoVo) {
|
||||||
Long userId = AuthContextHolder.getUserId();
|
Long userId = AuthContextHolder.getUserId();
|
||||||
|
@ -37,11 +39,11 @@ public class AlbumInfoApiController {
|
||||||
}
|
}
|
||||||
|
|
||||||
//这个是在登录到专辑页面的时候,会调用这个接口,获取当前登录用户的专辑信息
|
//这个是在登录到专辑页面的时候,会调用这个接口,获取当前登录用户的专辑信息
|
||||||
|
@GuiGuLogin
|
||||||
@Operation(summary = "分页条件查询当前登录用户发布专辑")
|
@Operation(summary = "分页条件查询当前登录用户发布专辑")
|
||||||
@PostMapping("/albumInfo/findUserAlbumPage/{page}/{limit}")
|
@PostMapping("/albumInfo/findUserAlbumPage/{page}/{limit}")
|
||||||
public Result<IPage<AlbumListVo>> findUserAlbumPage(@PathVariable Long page,
|
public Result<IPage<AlbumListVo>> findUserAlbumPage(@PathVariable Long page,
|
||||||
@PathVariable Long limit,
|
@PathVariable Long limit,@RequestBody AlbumInfoQuery albumInfoQuery){
|
||||||
@RequestBody AlbumInfoQuery albumInfoQuery){
|
|
||||||
//先从线程中取出来用户id
|
//先从线程中取出来用户id
|
||||||
Long userId = AuthContextHolder.getUserId();
|
Long userId = AuthContextHolder.getUserId();
|
||||||
//将用户id放进到查询条件中
|
//将用户id放进到查询条件中
|
||||||
|
@ -81,6 +83,7 @@ public class AlbumInfoApiController {
|
||||||
* 查询当前用户专辑列表
|
* 查询当前用户专辑列表
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@GuiGuLogin
|
||||||
@Operation(summary = "查询当前用户专辑列表")
|
@Operation(summary = "查询当前用户专辑列表")
|
||||||
@GetMapping("/albumInfo/findUserAllAlbumList")
|
@GetMapping("/albumInfo/findUserAllAlbumList")
|
||||||
public Result<List<AlbumInfo>> findUserAllAlbumList(){
|
public Result<List<AlbumInfo>> findUserAllAlbumList(){
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.atguigu.tingshu.album.api;
|
||||||
|
|
||||||
import com.atguigu.tingshu.album.service.TrackInfoService;
|
import com.atguigu.tingshu.album.service.TrackInfoService;
|
||||||
import com.atguigu.tingshu.album.service.VodService;
|
import com.atguigu.tingshu.album.service.VodService;
|
||||||
|
import com.atguigu.tingshu.common.login.GuiGuLogin;
|
||||||
import com.atguigu.tingshu.common.result.Result;
|
import com.atguigu.tingshu.common.result.Result;
|
||||||
import com.atguigu.tingshu.common.util.AuthContextHolder;
|
import com.atguigu.tingshu.common.util.AuthContextHolder;
|
||||||
import com.atguigu.tingshu.model.album.TrackInfo;
|
import com.atguigu.tingshu.model.album.TrackInfo;
|
||||||
|
@ -47,6 +48,7 @@ public class TrackInfoApiController {
|
||||||
* @param trackInfoVo
|
* @param trackInfoVo
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@GuiGuLogin
|
||||||
@Operation(summary = "保存声音")
|
@Operation(summary = "保存声音")
|
||||||
@PostMapping("/trackInfo/saveTrackInfo")
|
@PostMapping("/trackInfo/saveTrackInfo")
|
||||||
public Result saveTrackInfo(@Validated @RequestBody TrackInfoVo trackInfoVo) {
|
public Result saveTrackInfo(@Validated @RequestBody TrackInfoVo trackInfoVo) {
|
||||||
|
@ -63,6 +65,7 @@ public class TrackInfoApiController {
|
||||||
* @param trackInfoQuery
|
* @param trackInfoQuery
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@GuiGuLogin
|
||||||
@Operation(summary = "分页条件查询当前用户声音列表")
|
@Operation(summary = "分页条件查询当前用户声音列表")
|
||||||
@PostMapping("/trackInfo/findUserTrackPage/{page}/{limit}")
|
@PostMapping("/trackInfo/findUserTrackPage/{page}/{limit}")
|
||||||
public Result<Page<TrackListVo>> findUserTrackPage(
|
public Result<Page<TrackListVo>> findUserTrackPage(
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -32,6 +32,11 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.binarywang</groupId>
|
||||||
|
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
||||||
|
<version>4.5.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
package com.atguigu.tingshu.user.api;
|
package com.atguigu.tingshu.user.api;
|
||||||
|
|
||||||
|
import com.atguigu.tingshu.common.login.GuiGuLogin;
|
||||||
|
import com.atguigu.tingshu.common.result.Result;
|
||||||
|
import com.atguigu.tingshu.common.util.AuthContextHolder;
|
||||||
import com.atguigu.tingshu.user.service.UserInfoService;
|
import com.atguigu.tingshu.user.service.UserInfoService;
|
||||||
|
import com.atguigu.tingshu.vo.user.UserInfoVo;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Tag(name = "微信授权登录接口")
|
@Tag(name = "微信授权登录接口")
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -16,5 +22,47 @@ public class WxLoginApiController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserInfoService userInfoService;
|
private UserInfoService userInfoService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信一键登录
|
||||||
|
*
|
||||||
|
* @param code 小程序集成微信基于当前微信用户生成临时票据code
|
||||||
|
* @return {token:"令牌"}
|
||||||
|
*/
|
||||||
|
@Operation(summary = "小程序端微信一键登录")
|
||||||
|
@GetMapping("/wxLogin/{code}")
|
||||||
|
public Result<Map<String, String>> wxLogin(@PathVariable String code) {
|
||||||
|
Map<String, String> map = userInfoService.wxLogin(code);
|
||||||
|
return Result.ok(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前登录用户基本信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GuiGuLogin
|
||||||
|
@GetMapping("/getUserInfo")
|
||||||
|
@Operation(summary = "获取当前登录用户基本信息")
|
||||||
|
public Result<UserInfoVo> getUserInfo() {
|
||||||
|
Long userId = AuthContextHolder.getUserId();
|
||||||
|
UserInfoVo userInfoVo = userInfoService.getUserInfo(userId);
|
||||||
|
return Result.ok(userInfoVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新当前用户基本信息
|
||||||
|
* @param userInfoVo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GuiGuLogin
|
||||||
|
@Operation(summary = "更新当前用户基本信息")
|
||||||
|
@PostMapping("/updateUser")
|
||||||
|
public Result updateUser(@RequestBody UserInfoVo userInfoVo) {
|
||||||
|
Long userId = AuthContextHolder.getUserId();
|
||||||
|
userInfoService.updateUser(userInfoVo, userId);
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
package com.atguigu.tingshu.user.service;
|
package com.atguigu.tingshu.user.service;
|
||||||
|
|
||||||
import com.atguigu.tingshu.model.user.UserInfo;
|
import com.atguigu.tingshu.model.user.UserInfo;
|
||||||
|
import com.atguigu.tingshu.vo.user.UserInfoVo;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface UserInfoService extends IService<UserInfo> {
|
public interface UserInfoService extends IService<UserInfo> {
|
||||||
|
|
||||||
|
Map<String, String> wxLogin(String code);
|
||||||
|
|
||||||
|
UserInfoVo getUserInfo(Long userId);
|
||||||
|
|
||||||
|
void updateUser(UserInfoVo userInfoVo, Long userId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,30 @@
|
||||||
package com.atguigu.tingshu.user.service.impl;
|
package com.atguigu.tingshu.user.service.impl;
|
||||||
|
|
||||||
|
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||||
|
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.atguigu.tingshu.common.constant.RedisConstant;
|
||||||
|
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
|
||||||
|
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
|
||||||
import com.atguigu.tingshu.model.user.UserInfo;
|
import com.atguigu.tingshu.model.user.UserInfo;
|
||||||
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
|
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
|
||||||
import com.atguigu.tingshu.user.service.UserInfoService;
|
import com.atguigu.tingshu.user.service.UserInfoService;
|
||||||
|
import com.atguigu.tingshu.vo.user.UserInfoVo;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.chanjar.weixin.common.error.WxErrorException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@SuppressWarnings({"all"})
|
@SuppressWarnings({"all"})
|
||||||
|
@ -15,5 +32,73 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserInfoMapper userInfoMapper;
|
private UserInfoMapper userInfoMapper;
|
||||||
|
@Autowired
|
||||||
|
private WxMaService wxMaService;
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate redisTemplate;
|
||||||
|
@Autowired
|
||||||
|
private RabbitService rabbitService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> wxLogin(String code) {
|
||||||
|
try {
|
||||||
|
//1.根据小程序提交的临时票据code调用微信接口服务,获取当前微信用户唯一标识openid
|
||||||
|
WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
|
||||||
|
String wxOpenid = sessionInfo.getOpenid();
|
||||||
|
//2.根据openid查询数据库用户表,判断微信账户是否关联用户
|
||||||
|
UserInfo userInfo = userInfoMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<UserInfo>()
|
||||||
|
.eq(UserInfo::getWxOpenId, wxOpenid)
|
||||||
|
);//3.如果不存在用户记录,说明该微信是首次登录
|
||||||
|
if (userInfo == null) {
|
||||||
|
//3.1 新增用户记录
|
||||||
|
userInfo = new UserInfo();
|
||||||
|
userInfo.setWxOpenId(wxOpenid);
|
||||||
|
userInfo.setNickname("听友" + IdUtil.nanoId());
|
||||||
|
userInfo.setAvatarUrl("http://192.168.200.6:9000/tingshu/2025-07-21/1ce194e3-4212-4ff8-948b-babd9a7b8a02.jpg");
|
||||||
|
userInfoMapper.insert(userInfo);
|
||||||
|
//3.2 TODO 隐式初始化账户记录,用于后续订单消费,采用MQ
|
||||||
|
//3.2.1 创建初始化账户MQ消息对象 注意:如果使用的是VO对象,该对象必须得实现序列化接口 Serializable
|
||||||
|
Map<String, Object> mqData = new HashMap<>();
|
||||||
|
mqData.put("userId", userInfo.getId());
|
||||||
|
mqData.put("amount", BigDecimal.valueOf(100));
|
||||||
|
mqData.put("orderNo", "ZS"+ DateUtil.today().replaceAll("-", "")+IdUtil.getSnowflakeNextId());
|
||||||
|
mqData.put("title", "首次注册,赠送体验金活动");
|
||||||
|
|
||||||
|
//3.2.2 发送消息到RabbitMQ交换机 todo 使用RabbitService
|
||||||
|
rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, mqData);
|
||||||
|
|
||||||
|
}
|
||||||
|
//4.无论是否首次登录,都需要生成令牌,返回给小程序
|
||||||
|
//4.1 生成随机令牌
|
||||||
|
String token = IdUtil.randomUUID();
|
||||||
|
//4.2 将用户令牌作为Key,用户基本信息UserInfoVo作为Value,保存到Redis中
|
||||||
|
String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
|
||||||
|
UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
|
||||||
|
redisTemplate.opsForValue().set(loginKey, userInfoVo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
//4.3 返回用户令牌
|
||||||
|
return Map.of("token", token);
|
||||||
|
} catch (WxErrorException e) {
|
||||||
|
log.error("微信登录失败:{}", e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserInfoVo getUserInfo(Long userId) {
|
||||||
|
UserInfo userInfo = userInfoMapper.selectById(userId);
|
||||||
|
return BeanUtil.copyProperties(userInfo, UserInfoVo.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateUser(UserInfoVo userInfoVo, Long userId) {
|
||||||
|
UserInfo userInfo = new UserInfo();
|
||||||
|
userInfo.setId(userId);
|
||||||
|
userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
|
||||||
|
userInfo.setNickname(userInfoVo.getNickname());
|
||||||
|
userInfoMapper.updateById(userInfo);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue