Merge pull request '拼团优化' (#10) from czk into main

Reviewed-on: #10
main
czk 2024-05-20 16:45:46 +08:00
commit 4f8d7c105e
21 changed files with 772 additions and 38 deletions

View File

@ -36,12 +36,18 @@
<artifactId>aliyun-sdk-oss</artifactId> <artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version> <version>3.10.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <version>4.12</version>
</dependency> </dependency>
<!-- zipkin-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -16,6 +16,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
/** /**
@ -112,7 +115,4 @@ public class AuthController {
return authService.authentication(idCardRequest); return authService.authentication(idCardRequest);
} }
@Autowired
private UserServiceFeign userServiceFeign;
} }

View File

@ -8,6 +8,8 @@ import com.mall.common.domain.vo.UserInfoVo;
import com.mall.common.result.Result; import com.mall.common.result.Result;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
public interface AuthService { public interface AuthService {
Result login(LoginVo loginVo); Result login(LoginVo loginVo);
@ -25,4 +27,5 @@ public interface AuthService {
Result authentication(IdCardRequest idCardRequest); Result authentication(IdCardRequest idCardRequest);
} }

View File

@ -216,10 +216,9 @@ public class AuthServiceImpl implements AuthService {
return idCardCheckLifeVo; return idCardCheckLifeVo;
}, threadPoolConfig.getThreadPoolExecutor()); }, threadPoolConfig.getThreadPoolExecutor());
// CompletableFuture.allOf(f1,f2).join();
IdCardValidateVo idCardValidateVo = null; IdCardValidateVo idCardValidateVo = null;
IdCardCheckLifeVo idCardCheckLifeVo = null; IdCardCheckLifeVo idCardCheckLifeVo = null;
// CompletableFuture.allOf(f1,f2).join();
try { try {
idCardValidateVo = f1.get(); idCardValidateVo = f1.get();
idCardCheckLifeVo = f2.get(); idCardCheckLifeVo = f2.get();

View File

@ -3,6 +3,18 @@ server:
port: 9000 port: 9000
# Spring # Spring
spring: spring:
#服务追踪
zipkin:
base-url: http://124.221.183.9:9411/ # zipkin服务器的地址
discovery-client-enabled: false #关闭服务发现否则spring cloud会把zipkin的url当作服务名称
sender:
type: web #设苦使用http的方式传输数据
sleuth:
traceId128: true
sampler:
probability: 1.0 #抽样采集率为100%,默认为0.1 即10%
propagation-keys: user_name
servlet: servlet:
multipart: multipart:
#这将限制单个文件的最大大小为10MB #这将限制单个文件的最大大小为10MB

View File

@ -1,6 +1,9 @@
package com.mall.common.utils; package com.mall.common.utils;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Base64; import java.util.Base64;
@ -12,6 +15,7 @@ import java.util.Base64;
*/ */
public class SecurityUtils { public class SecurityUtils {
private static final String key = "01020304";
/** /**
* BCryptPasswordEncoder * BCryptPasswordEncoder
@ -51,4 +55,44 @@ public class SecurityUtils {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
// 加密方法
public static String encrypt(String plaintext) throws Exception {
// 创建 Cipher 对象
Cipher cipher = Cipher.getInstance("DES");
// 创建 SecretKey 对象
SecretKey secretKey = new SecretKeySpec(key.getBytes(), "DES");
// 初始化 Cipher 对象为加密模式,并传入密钥
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 执行加密操作
byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes());
// 对加密后的数据进行 Base64 编码
return Base64.getEncoder().encodeToString(encryptedBytes);
}
// 解密方法
public static String decrypt(String ciphertext) throws Exception {
// 创建 Cipher 对象
Cipher cipher = Cipher.getInstance("DES");
// 创建 SecretKey 对象
SecretKey secretKey = new SecretKeySpec(key.getBytes(), "DES");
// 初始化 Cipher 对象为解密模式,并传入密钥
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// 对 Base64 编码后的密文进行解码
byte[] encryptedBytes = Base64.getDecoder().decode(ciphertext);
// 执行解密操作
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
// 将解密后的字节数组转换为字符串并返回
return new String(decryptedBytes);
}
} }

View File

@ -2,6 +2,7 @@ package com.mall.server;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
/** /**
@ -10,6 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@EnableScheduling @EnableScheduling
@EnableFeignClients @EnableFeignClients
@EnableAsync
public class ServerApplication { public class ServerApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(ServerApplication.class,args); SpringApplication.run(ServerApplication.class,args);

View File

@ -23,17 +23,25 @@ public class LogAnnotationAspect {
// 应用周围通知 // 应用周围通知
@Around("allMethod()") @Around("allMethod()")
public void doAround(ProceedingJoinPoint call) throws Throwable{ public Object doAround(ProceedingJoinPoint call) throws Throwable {
long start = new Date().getTime(); long start = System.currentTimeMillis(); // 更推荐使用 System.currentTimeMillis()
String methodName = call.getSignature().getName(); // 获取方法名 String methodName = call.getSignature().getName(); // 获取方法名
Object[] args = call.getArgs(); // 获取方法的参数 Object[] args = call.getArgs(); // 获取方法的参数
call.proceed();
long end = new Date().getTime(); // 调用原始方法并获取返回值
log.info("耗时:"+(end-start)/1000+"秒"); Object proceed = call.proceed();
log.info(methodName+"()方法执行");
long end = System.currentTimeMillis(); // 更推荐使用 System.currentTimeMillis()
log.info("方法 {} 执行耗时:{} 秒", methodName, (end - start) / 1000.0);
// 打印方法名和参数
log.info("{}() 方法执行", methodName);
for (Object arg : args) { for (Object arg : args) {
log.info("参数:"+String.valueOf(arg)); log.info("参数:{}", String.valueOf(arg));
} }
// 将方法的返回值传回
return proceed; // 确保返回原方法的返回值
} }
} }

View File

@ -0,0 +1,94 @@
package com.mall.server.config;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
/**
*
*/
@Log4j2
@Configuration
public class GroupDelayConfig {
/**
*
*/
public static final String CZKQUEUE = "group_queue";
/**
*
*/
public static final String EXCHANGE = "group_exchange";
/**
* key
*/
public static final String ROUKEYCZK = "group_queue";
@Bean
public DirectExchange directExchange() {
return new DirectExchange(EXCHANGE);
}
@Bean
public Queue autoDeleteQueue1(){
HashMap<String, Object> map = new HashMap<>();
map.put("x-dead-letter-exchange",DEADEXCHANGE);
map.put("x-dead-letter-routing-key",DEADROUKEY);
map.put("x-message-ttl",MESSAGE_FIVE);
return new Queue(CZKQUEUE,true,false,false,map);
}
@Bean
public Binding binding1a() {
return BindingBuilder.bind(autoDeleteQueue1())
.to(directExchange())
.with(ROUKEYCZK);
}
/**
*
*/
public static final String DEADEXCHANGE = "group_dead_exchange";
/**
*
*/
public static final String DEADQUEUE = "group_dead_queue";
/**
* key
*/
public static final String DEADROUKEY = "group_dead_queue";
/**
* 5
*/
public static final Integer MESSAGE_FIVE = 20000;
/**
* 10
*/
public static final Integer MESSAGE_FEN = 600000;
@Bean
public DirectExchange deadExchange() {
return new DirectExchange(DEADEXCHANGE);
}
@Bean
public Queue autoDeleteQueue2(){
return new Queue(DEADQUEUE,true);
}
@Bean
public Binding binding2() {
return BindingBuilder.bind(autoDeleteQueue2())
.to(deadExchange())
.with(DEADROUKEY);
}
}

View File

@ -4,22 +4,16 @@ import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange; import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import java.util.HashMap; import java.util.HashMap;
/** /**
* @AuthorChen *
* @Packagecom.bw.common.config
* @Projectholiday2
* @nameRabbitConfig
* @Date2024/2/5 10:55
* @Description: TODO
*/ */
@Log4j2 @Log4j2
@Configuration @Configuration
public class DelayConfig { public class SpikesDelayConfig {
/** /**
* *
@ -72,7 +66,7 @@ public class DelayConfig {
/** /**
* 5 * 5
*/ */
public static final Integer MESSAGE_FIVE = 5000; public static final Integer MESSAGE_FIVE = 20000;
/** /**
* 10 * 10
*/ */

View File

@ -0,0 +1,55 @@
package com.mall.server.controller;
import cn.hutool.crypto.SecureUtil;
import com.mall.common.result.BizException;
import com.mall.common.result.Result;
import com.mall.common.utils.SecurityUtils;
import com.mall.server.service.TeamworkService;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
/**
*Controller
*/
@RestController
@RequestMapping("/teamwork")
public class TeamworkController {
@Autowired
private TeamworkService teamworkService;
/**
*
* @param id
* @return
*/
@GetMapping("groupBooking")
public Result<String> groupBooking(@NotNull String id, @RequestParam Integer state){
//state 0未加密 1加密
if(state==null || state==0){
return teamworkService.groupBooking(Long.parseLong(id));
}
String skuId = null;
try {
skuId = SecurityUtils.decrypt(id);
} catch (Exception e) {
throw new RuntimeException(e);
}
return teamworkService.groupBooking(Long.parseLong(skuId));
}
/**
*
* @param skuId
* @return
*/
@GetMapping("encryption")
public Result encryption(@NotNull Long skuId){
return teamworkService.encryption(skuId);
}
}

View File

@ -0,0 +1,109 @@
package com.mall.server.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
/**
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("pms_teamwork")
public class TeamworkEntity {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* id
*/
private Long userId;
/**
*
*/
private Date startGroupTime;
/**
*
*/
private Integer groupOfSeveral;
/**
*
*/
private Integer severalPeopleInvolved;
/**
*
*/
private Integer packageNumber;
/**
*
*/
private Date finishTime;
/**
*
*/
private String groupName;
/**
*
*/
private String groupIntroduce;
/**
*
*/
private BigDecimal originalPrice;
/**
*
*/
private BigDecimal groupPrice;
/**
*
*/
private Date groupAging;
/**
*
*/
private Integer groupNumber;
/**
*
*/
private Integer buyNumRestrict;
/**
* 0- 1-
*/
private Integer freightType;
/**
* 012
*/
private Integer groupStatus;
/**
*
*/
private Integer activeState;
/**
*
*/
private Long skuId;
/**
*
*/
private Integer continueDate;
/**
*
*/
private Date createDate;
/**
*
*/
private Date endDate;
}

View File

@ -0,0 +1,65 @@
package com.mall.server.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
/**
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("pms_teamwork_record")
public class TeamworkRecordEntity {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
*
*/
private String teamworkOrderSn;
/**
* id
*/
private Long teamworkId;
/**
*
*/
private BigDecimal price;
/**
*
*/
private Integer num;
/**
* 0 1
*/
private Integer severalPeopleInvolved;
/**
*
*/
private Date createTime;
/**
* id
*/
private Long userId;
/**
* id
*/
private Long skuId;
/**
* 0 1
*/
private Integer state;
}

View File

@ -0,0 +1,18 @@
package com.mall.server.domain.vo;
import com.mall.common.domain.OrderItemEntity;
import com.mall.server.domain.TeamworkRecordEntity;
import lombok.Builder;
import lombok.Data;
/**
*
*/
@Data
@Builder
public class GroupBookingVo {
private TeamworkRecordEntity teamworkRecordEntity;
private OrderItemEntity orderItemEntity;
}

View File

@ -0,0 +1,12 @@
package com.mall.server.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mall.server.domain.TeamworkEntity;
import org.apache.ibatis.annotations.Mapper;
/**
*Mapper
*/
@Mapper
public interface TeamworkMapper extends BaseMapper<TeamworkEntity> {
}

View File

@ -0,0 +1,12 @@
package com.mall.server.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mall.server.domain.TeamworkRecordEntity;
import org.apache.ibatis.annotations.Mapper;
/**
*
*/
@Mapper
public interface TeamworkRecordMapper extends BaseMapper<TeamworkRecordEntity> {
}

View File

@ -0,0 +1,68 @@
package com.mall.server.monitor;
import com.alibaba.fastjson.JSON;
import com.mall.common.domain.OrderItemEntity;
import com.mall.server.domain.vo.GroupBookingVo;
import com.mall.server.mapper.OrderItemMapper;
import com.mall.server.mapper.TeamworkRecordMapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
*
*/
@Component
public class GroupBookingMonitor {
@Autowired
private TeamworkRecordMapper teamworkRecordMapper;
@Autowired
private OrderItemMapper orderItemMapper;
/**
*
* @param groupBookingVo
*/
@Async
@EventListener(GroupBookingVo.class)
public void customerEventListener(GroupBookingVo groupBookingVo) {
orderItemMapper.insert(groupBookingVo.getOrderItemEntity());
teamworkRecordMapper.insert(groupBookingVo.getTeamworkRecordEntity());
}
/**
*
* @param msg
* @param message
* @param channel
*/
public void GroupConsumer(String msg, Message message, Channel channel){
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
channel.basicAck(deliveryTag,false);
} catch (IOException e) {
try {
if(deliveryTag<3){
Thread.sleep(3000);
channel.basicNack(deliveryTag,false,true);
}else {
channel.basicNack(deliveryTag,false,false);
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
}

View File

@ -3,7 +3,7 @@ package com.mall.server.monitor;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mall.common.domain.OrderItemEntity; import com.mall.common.domain.OrderItemEntity;
import com.mall.server.config.DelayConfig; import com.mall.server.config.SpikesDelayConfig;
import com.mall.server.config.MqConfig; import com.mall.server.config.MqConfig;
import com.mall.server.constant.SpikesConstant; import com.mall.server.constant.SpikesConstant;
import com.mall.server.service.OrderItemService; import com.mall.server.service.OrderItemService;
@ -31,13 +31,27 @@ public class SpikesMonitor {
@Autowired @Autowired
private OrderItemService orderItemService; private OrderItemService orderItemService;
@RabbitListener(queues = DelayConfig.DEADQUEUE) /**
*
* @param meg
* @param message
* @param channel
*/
@RabbitListener(queues = SpikesDelayConfig.DEADQUEUE)
public void consumer(String meg, Message message, Channel channel){ public void consumer(String meg, Message message, Channel channel){
log.info("延迟队列接受到消息"+meg); log.info("延迟队列接受到消息"+meg);
long deliveryTag = message.getMessageProperties().getDeliveryTag(); long deliveryTag = message.getMessageProperties().getDeliveryTag();
if(meg==null){
try {
channel.basicAck(deliveryTag,false);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
String[] split = meg.split(","); String[] split = meg.split(",");
String skuId = split[0]; String skuId = split[0];
String orderSn = split[1]; String orderSn = split[1];
try {
OrderItemEntity orderItemEntity = orderItemService.getOne( OrderItemEntity orderItemEntity = orderItemService.getOne(
new LambdaQueryWrapper<OrderItemEntity>() new LambdaQueryWrapper<OrderItemEntity>()
.eq(OrderItemEntity::getOrderSn, orderSn) .eq(OrderItemEntity::getOrderSn, orderSn)
@ -46,7 +60,6 @@ public class SpikesMonitor {
RSemaphore semaphore = redissonClient.getSemaphore(SpikesConstant.SPIKES_INVENTORY + skuId); RSemaphore semaphore = redissonClient.getSemaphore(SpikesConstant.SPIKES_INVENTORY + skuId);
semaphore.release(1); semaphore.release(1);
} }
try {
channel.basicAck(deliveryTag,false); channel.basicAck(deliveryTag,false);
} catch (IOException e) { } catch (IOException e) {
try { try {
@ -62,15 +75,26 @@ public class SpikesMonitor {
} }
} }
/**
*
* @param meg
* @param message
* @param channel
*/
@RabbitListener(queues = MqConfig.DXQUEUE) @RabbitListener(queues = MqConfig.DXQUEUE)
public void orderConsumer(String meg, Message message, Channel channel){ public void orderConsumer(String meg, Message message, Channel channel){
log.info("下订单"+meg); log.info("下订单"+meg);
long deliveryTag = message.getMessageProperties().getDeliveryTag(); long deliveryTag = message.getMessageProperties().getDeliveryTag();
if(meg ==null){
orderItemService.save(JSON.parseObject(meg,OrderItemEntity.class));
try { try {
channel.basicAck(deliveryTag,false); channel.basicAck(deliveryTag,false);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
try {
orderItemService.save(JSON.parseObject(meg,OrderItemEntity.class));
channel.basicAck(deliveryTag,false);
} catch (IOException e) { } catch (IOException e) {
try { try {
if(deliveryTag<3){ if(deliveryTag<3){

View File

@ -0,0 +1,17 @@
package com.mall.server.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mall.common.result.Result;
import com.mall.server.domain.TeamworkEntity;
import java.util.HashMap;
import java.util.Map;
/**
*Service
*/
public interface TeamworkService extends IService<TeamworkEntity> {
Result<String> groupBooking(Long skuId);
Result encryption(Long skuId);
}

View File

@ -12,7 +12,7 @@ import com.mall.common.result.BizException;
import com.mall.common.result.Result; import com.mall.common.result.Result;
import com.mall.common.utils.IdUtils; import com.mall.common.utils.IdUtils;
import com.mall.common.utils.StringUtils; import com.mall.common.utils.StringUtils;
import com.mall.server.config.DelayConfig; import com.mall.server.config.SpikesDelayConfig;
import com.mall.server.config.MqConfig; import com.mall.server.config.MqConfig;
import com.mall.server.constant.SpikesConstant; import com.mall.server.constant.SpikesConstant;
import com.mall.server.domain.SkuEntity; import com.mall.server.domain.SkuEntity;
@ -193,7 +193,7 @@ public class SpikesServiceImpl extends ServiceImpl<SpikesMapper, SpikesEntity>
}); });
rabbitTemplate.convertAndSend( rabbitTemplate.convertAndSend(
DelayConfig.EXCHANGE, DelayConfig.ROUKEYCZK, skuId + "," + orderSn, SpikesDelayConfig.EXCHANGE, SpikesDelayConfig.ROUKEYCZK, skuId + "," + orderSn,
message -> { message -> {
message.getMessageProperties().setMessageId(IdUtils.genId()); message.getMessageProperties().setMessageId(IdUtils.genId());
return message; return message;

View File

@ -0,0 +1,192 @@
package com.mall.server.service.impl;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.DES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mall.common.constant.TokenConstants;
import com.mall.common.domain.OrderItemEntity;
import com.mall.common.domain.UserInfo;
import com.mall.common.redis.RedisCache;
import com.mall.common.result.BizException;
import com.mall.common.result.Result;
import com.mall.common.utils.IdUtils;
import com.mall.common.utils.SecurityUtils;
import com.mall.common.utils.StringUtils;
import com.mall.server.config.GroupDelayConfig;
import com.mall.server.domain.SkuEntity;
import com.mall.server.domain.TeamworkEntity;
import com.mall.server.domain.TeamworkRecordEntity;
import com.mall.server.domain.vo.GroupBookingVo;
import com.mall.server.mapper.OrderItemMapper;
import com.mall.server.mapper.SkuMapper;
import com.mall.server.mapper.TeamworkMapper;
import com.mall.server.mapper.TeamworkRecordMapper;
import com.mall.server.service.TeamworkService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* ServiceImpl
*/
@Service
public class TeamworkServiceImpl extends ServiceImpl<TeamworkMapper, TeamworkEntity>
implements TeamworkService {
@Autowired
private TeamworkMapper teamworkMapper;
@Autowired
private TeamworkRecordMapper teamworkRecordMapper;
@Autowired
private RedisCache redisCache;
@Autowired
private HttpServletRequest request;
@Autowired
private SkuMapper skuMapper;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private RabbitTemplate rabbitTemplate;
public UserInfo getLogin() {
String token = request.getHeader(TokenConstants.TOKEN);
if (StringUtils.isBlank(token)) {
throw new BizException(401, "未登录");
}
UserInfo userInfo = redisCache.getCacheObject(TokenConstants.TOKEN + token);
return userInfo;
}
@Transactional
@Override
public Result<String> groupBooking(Long skuId) {
UserInfo login = getLogin();
if (redisCache.hasKey("groupBooking_" + login.getId() + skuId)) {
throw new BizException(500, "禁止重复抢购欧");
}
redisCache.setCacheObject("groupBooking_" + login.getId() + skuId, IdUtils.genId().toString(), 1L, TimeUnit.MINUTES);
//商品id查询商品表
SkuEntity skuEntity = skuMapper.selectOne(
new LambdaQueryWrapper<SkuEntity>()
.eq(SkuEntity::getId, skuId)
);
//商品的拼图id查询拼团表
TeamworkEntity teamworkEntity = teamworkMapper.selectOne(
new LambdaQueryWrapper<TeamworkEntity>()
.eq(TeamworkEntity::getId, skuEntity.getBargainId())
);
//校验拼团时间
if (teamworkEntity.getCreateDate().compareTo(new Date()) > 0 || teamworkEntity.getEndDate().compareTo(new Date()) < 0) {
throw new BizException(500, skuEntity.getName() + "该商品不在拼团时间内");
}
//查询拼团记录防止用户拼同一活动同一商品
TeamworkRecordEntity teamworkRecordEntity = teamworkRecordMapper.selectOne(
new LambdaQueryWrapper<TeamworkRecordEntity>()
.eq(TeamworkRecordEntity::getUserId, login.getId())
.eq(TeamworkRecordEntity::getTeamworkId, teamworkEntity.getId())
.eq(TeamworkRecordEntity::getSkuId, skuEntity.getId())
);
if (teamworkRecordEntity != null) {
throw new BizException(500, "禁止重复拼团");
}
//根据拼团id和商品id查询拼团记录表几人拼团
List<TeamworkRecordEntity> teamworkRecordEntityList = teamworkRecordMapper.selectList(
new LambdaQueryWrapper<TeamworkRecordEntity>()
.eq(TeamworkRecordEntity::getTeamworkId, teamworkEntity.getId())
.eq(TeamworkRecordEntity::getSkuId, skuEntity.getId())
);
//订单信息
String orderSn = IdUtils.genId();
OrderItemEntity orderItem = OrderItemEntity.builder()
.userId(login.getId())
.orderSn(orderSn)
.skuId(skuId)
.skuName(skuEntity.getName())
.skuPic(skuEntity.getDefaultImage())
.skuPrice(skuEntity.getPrice())
// .promotionAmount()
// .couponAmount()
// .integrationAmount()
.realAmount(skuEntity.getActivityPrice())
.status(0).build();
//拼团记录表
TeamworkRecordEntity teamworkRecord = TeamworkRecordEntity.builder()
.teamworkOrderSn(orderSn)
.teamworkId(teamworkEntity.getId())
.price(skuEntity.getPrice())
.num(1)
.severalPeopleInvolved(0)
.createTime(new Date())
.userId(login.getId())
.skuId(skuEntity.getId())
.state(0).build();//发起人
//参与拼团
if (teamworkRecordEntityList.size() != 0) {
//团满
if (teamworkRecordEntityList.size() == teamworkEntity.getGroupOfSeveral()) {
throw new BizException(500, "拼团人数已满");
}
teamworkRecord.setState(1);
applicationContext.publishEvent(
GroupBookingVo.builder()
.orderItemEntity(orderItem)
.teamworkRecordEntity(teamworkRecord).build()
);
return Result.success(orderSn, "拼团成功");
}
//拼团发起人
applicationContext.publishEvent(
GroupBookingVo.builder()
.orderItemEntity(orderItem)
.teamworkRecordEntity(teamworkRecord).build()
);
//发起拼团之后扣减库存,把一整个拼团的库存全部扣减
skuMapper.updateById(
SkuEntity.builder()
.id(skuId)
.inventoryRestrict(teamworkEntity.getGroupOfSeveral())
.build()
);
//延迟队列48小时后没有成团取消拼团并归还库存支付的退款
rabbitTemplate.convertAndSend(GroupDelayConfig.EXCHANGE, GroupDelayConfig.ROUKEYCZK, orderSn,
message -> {
message.getMessageProperties().setMessageId(orderSn);
return message;
});
return Result.success(orderSn, "拼团成功");
}
@Override
public Result encryption(Long skuId) {
String encrypt = null;
try {
encrypt = SecurityUtils.encrypt(skuId.toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
return Result.success("http://localhost:9002/teamwork/groupBooking?skuId=" + encrypt + "&state=1", "加密路径成功");
}
}