commit
4f8d7c105e
|
@ -36,12 +36,18 @@
|
|||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>3.10.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
<!-- zipkin-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zipkin</artifactId>
|
||||
<version>2.2.8.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -16,6 +16,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
|
@ -112,7 +115,4 @@ public class AuthController {
|
|||
return authService.authentication(idCardRequest);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private UserServiceFeign userServiceFeign;
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import com.mall.common.domain.vo.UserInfoVo;
|
|||
import com.mall.common.result.Result;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public interface AuthService {
|
||||
Result login(LoginVo loginVo);
|
||||
|
||||
|
@ -25,4 +27,5 @@ public interface AuthService {
|
|||
|
||||
Result authentication(IdCardRequest idCardRequest);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -216,10 +216,9 @@ public class AuthServiceImpl implements AuthService {
|
|||
return idCardCheckLifeVo;
|
||||
}, threadPoolConfig.getThreadPoolExecutor());
|
||||
|
||||
// CompletableFuture.allOf(f1,f2).join();
|
||||
IdCardValidateVo idCardValidateVo = null;
|
||||
IdCardCheckLifeVo idCardCheckLifeVo = null;
|
||||
|
||||
// CompletableFuture.allOf(f1,f2).join();
|
||||
try {
|
||||
idCardValidateVo = f1.get();
|
||||
idCardCheckLifeVo = f2.get();
|
||||
|
|
|
@ -3,6 +3,18 @@ server:
|
|||
port: 9000
|
||||
# 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:
|
||||
multipart:
|
||||
#这将限制单个文件的最大大小为10MB
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
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.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
|
@ -12,6 +15,7 @@ import java.util.Base64;
|
|||
*/
|
||||
public class SecurityUtils {
|
||||
|
||||
private static final String key = "01020304";
|
||||
|
||||
/**
|
||||
* 生成BCryptPasswordEncoder密码
|
||||
|
@ -51,4 +55,44 @@ public class SecurityUtils {
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.mall.server;
|
|||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
|
@ -10,6 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EnableFeignClients
|
||||
@EnableAsync
|
||||
public class ServerApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ServerApplication.class,args);
|
||||
|
|
|
@ -23,17 +23,25 @@ public class LogAnnotationAspect {
|
|||
|
||||
// 应用周围通知
|
||||
@Around("allMethod()")
|
||||
public void doAround(ProceedingJoinPoint call) throws Throwable{
|
||||
long start = new Date().getTime();
|
||||
public Object doAround(ProceedingJoinPoint call) throws Throwable {
|
||||
long start = System.currentTimeMillis(); // 更推荐使用 System.currentTimeMillis()
|
||||
String methodName = call.getSignature().getName(); // 获取方法名
|
||||
Object[] args = call.getArgs(); // 获取方法的参数
|
||||
call.proceed();
|
||||
long end = new Date().getTime();
|
||||
log.info("耗时:"+(end-start)/1000+"秒");
|
||||
log.info(methodName+"()方法执行");
|
||||
|
||||
// 调用原始方法并获取返回值
|
||||
Object proceed = call.proceed();
|
||||
|
||||
long end = System.currentTimeMillis(); // 更推荐使用 System.currentTimeMillis()
|
||||
log.info("方法 {} 执行耗时:{} 秒", methodName, (end - start) / 1000.0);
|
||||
|
||||
// 打印方法名和参数
|
||||
log.info("{}() 方法执行", methodName);
|
||||
for (Object arg : args) {
|
||||
log.info("参数:"+String.valueOf(arg));
|
||||
log.info("参数:{}", String.valueOf(arg));
|
||||
}
|
||||
|
||||
// 将方法的返回值传回
|
||||
return proceed; // 确保返回原方法的返回值
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -4,22 +4,16 @@ 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.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @Author:Chen
|
||||
* @Package:com.bw.common.config
|
||||
* @Project:holiday2
|
||||
* @name:RabbitConfig
|
||||
* @Date:2024/2/5 10:55
|
||||
* @Description: TODO
|
||||
* 秒杀延迟队列
|
||||
*/
|
||||
@Log4j2
|
||||
@Configuration
|
||||
public class DelayConfig {
|
||||
public class SpikesDelayConfig {
|
||||
|
||||
/**
|
||||
* 队列
|
||||
|
@ -72,7 +66,7 @@ public class DelayConfig {
|
|||
/**
|
||||
* 5秒
|
||||
*/
|
||||
public static final Integer MESSAGE_FIVE = 5000;
|
||||
public static final Integer MESSAGE_FIVE = 20000;
|
||||
/**
|
||||
* 10分钟
|
||||
*/
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
/**
|
||||
* 拼团状态0正在平团1拼团成功2拼团失败
|
||||
*/
|
||||
private Integer groupStatus;
|
||||
/**
|
||||
* 活动状态
|
||||
*/
|
||||
private Integer activeState;
|
||||
/**
|
||||
* 商品属性
|
||||
*/
|
||||
private Long skuId;
|
||||
/**
|
||||
* 后台人员设置默认拼团持续时间(时间到未成团,解散)
|
||||
*/
|
||||
private Integer continueDate;
|
||||
/**
|
||||
* 拼团活动开始日期
|
||||
*/
|
||||
private Date createDate;
|
||||
/**
|
||||
* 拼团活动结束日期
|
||||
*/
|
||||
private Date endDate;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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> {
|
||||
}
|
|
@ -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> {
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@ package com.mall.server.monitor;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
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.constant.SpikesConstant;
|
||||
import com.mall.server.service.OrderItemService;
|
||||
|
@ -31,13 +31,27 @@ public class SpikesMonitor {
|
|||
@Autowired
|
||||
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){
|
||||
log.info("延迟队列接受到消息"+meg);
|
||||
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 skuId = split[0];
|
||||
String orderSn = split[1];
|
||||
try {
|
||||
OrderItemEntity orderItemEntity = orderItemService.getOne(
|
||||
new LambdaQueryWrapper<OrderItemEntity>()
|
||||
.eq(OrderItemEntity::getOrderSn, orderSn)
|
||||
|
@ -46,7 +60,6 @@ public class SpikesMonitor {
|
|||
RSemaphore semaphore = redissonClient.getSemaphore(SpikesConstant.SPIKES_INVENTORY + skuId);
|
||||
semaphore.release(1);
|
||||
}
|
||||
try {
|
||||
channel.basicAck(deliveryTag,false);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
|
@ -62,15 +75,26 @@ public class SpikesMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下订单
|
||||
* @param meg
|
||||
* @param message
|
||||
* @param channel
|
||||
*/
|
||||
@RabbitListener(queues = MqConfig.DXQUEUE)
|
||||
public void orderConsumer(String meg, Message message, Channel channel){
|
||||
log.info("下订单"+meg);
|
||||
long deliveryTag = message.getMessageProperties().getDeliveryTag();
|
||||
|
||||
orderItemService.save(JSON.parseObject(meg,OrderItemEntity.class));
|
||||
|
||||
if(meg ==null){
|
||||
try {
|
||||
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) {
|
||||
try {
|
||||
if(deliveryTag<3){
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -12,7 +12,7 @@ import com.mall.common.result.BizException;
|
|||
import com.mall.common.result.Result;
|
||||
import com.mall.common.utils.IdUtils;
|
||||
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.constant.SpikesConstant;
|
||||
import com.mall.server.domain.SkuEntity;
|
||||
|
@ -193,7 +193,7 @@ public class SpikesServiceImpl extends ServiceImpl<SpikesMapper, SpikesEntity>
|
|||
});
|
||||
|
||||
rabbitTemplate.convertAndSend(
|
||||
DelayConfig.EXCHANGE, DelayConfig.ROUKEYCZK, skuId + "," + orderSn,
|
||||
SpikesDelayConfig.EXCHANGE, SpikesDelayConfig.ROUKEYCZK, skuId + "," + orderSn,
|
||||
message -> {
|
||||
message.getMessageProperties().setMessageId(IdUtils.genId());
|
||||
return message;
|
||||
|
|
|
@ -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", "加密路径成功");
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue