Browse Source

订单业务代码提交

feature-1.1
wuxicheng 3 years ago
parent
commit
1a34ca17ad
  1. 5
      bnyer-common/bnyer-common-core/pom.xml
  2. 34
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/dto/VipOrderDto.java
  3. 50
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/ResponseEnum.java
  4. 203
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/bean/EntityConvertUtil.java
  5. 42
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/vo/VipOrderVo.java
  6. 10
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/web/domain/AjaxResult.java
  7. 20
      bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/adapter/CacheTtlAdapter.java
  8. 28
      bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/bo/CacheNameWithTtlBo.java
  9. 141
      bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/configure/RedisConfig.java
  10. 20
      bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/CacheNames.java
  11. 25
      bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/OrderCacheNames.java
  12. 49
      bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/service/RedisCacheService.java
  13. 29
      bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/service/RedisService.java
  14. 3
      bnyer-common/bnyer-common-redis/src/main/resources/META-INF/spring.factories
  15. 32
      bnyer-common/bnyer-common-rocketmq/pom.xml
  16. 38
      bnyer-common/bnyer-common-rocketmq/src/main/java/com/bnyer/common/rocketmq/config/RocketMqAdapter.java
  17. 40
      bnyer-common/bnyer-common-rocketmq/src/main/java/com/bnyer/common/rocketmq/config/RocketMqConstant.java
  18. 1
      bnyer-common/pom.xml
  19. 24
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipTypeConstant.java
  20. 22
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/UserVipServiceRecordImpl.java
  21. 5
      bnyer-services/bnyer-order/pom.xml
  22. 2
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/BnyerOrderApplication.java
  23. 27
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/OrderCacheTtlAdapter.java
  24. 28
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/RocketMqConfig.java
  25. 78
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/controller/VipOrderController.java
  26. 4
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/controller/testController.java
  27. 30
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/enums/EnumSceneCode.java
  28. 32
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/enums/EnumVipType.java
  29. 24
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/listener/vip/VipOrderCancelConsumer.java
  30. 18
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/listener/vip/VipOrderPaySuccessConsumer.java
  31. 4
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/TestService.java
  32. 27
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/VipOrderService.java
  33. 8
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/TestServiceImpl.java
  34. 97
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java
  35. 6
      bnyer-services/bnyer-pay/pom.xml
  36. 2
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/BnyerPayApplication.java
  37. 28
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/config/RocketMqConfig.java
  38. 4
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/config/TestConfig.java
  39. 13
      pom.xml

5
bnyer-common/bnyer-common-core/pom.xml

@ -65,6 +65,11 @@
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!-- Alibaba Fastjson -->
<dependency>
<groupId>com.alibaba</groupId>

34
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/dto/VipOrderDto.java

@ -0,0 +1,34 @@
package com.bnyer.common.core.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @author :WXC
* @Date :2023/03/27
* @description :
*/
@Getter
@Setter
@NoArgsConstructor
public class VipOrderDto implements Serializable {
@NotBlank(message = "手机号不能为空!")
@ApiModelProperty(value="手机号")
private String phone;
@NotNull(message = "用户vipId不能为空!")
@ApiModelProperty(value="用户vip表id")
private Long userVipId;
@NotBlank(message = "vip类型状态不能为空!")
@ApiModelProperty(value="vip类型状态(0->月卡;1->季卡;2->年卡)")
private String type;
}

50
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/ResponseEnum.java

@ -0,0 +1,50 @@
package com.bnyer.common.core.enums;
/**
* @author :WXC
* @Date :2023/03/28
* @description :
*/
public enum ResponseEnum {
//======================订单异常========================
/**
* 订单已过期当前端看到该状态码的时候提示订单信息已过期请重新确认后提交此时用户点击确定前端刷新页面
*/
ORDER_EXPIRED(110001, "订单已过期"),
/**
* 请勿重复提交订单
* 1.当前端遇到该异常时说明前端防多次点击没做好
* 2.提示用户 订单已发生改变请勿重复下单
*/
REPEAT_ORDER(110002,"请勿重复提交订单"),
;
private final int code;
private final String msg;
public int value() {
return code;
}
public String getMsg() {
return msg;
}
ResponseEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public String toString() {
return "ResponseEnum{" +
"code=" + code +
", msg='" + msg + '\'' +
'}';
}
}

203
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/bean/EntityConvertUtil.java

@ -0,0 +1,203 @@
package com.bnyer.common.core.utils.bean;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.CollectionUtils;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.*;
@Slf4j
public class EntityConvertUtil {
/**
* 数组集合转化为指定对象集合
* 指定的实体对象必须包含所以字段的构造方法数组的元素的顺序将和构造方法顺序和类型一一对应
*
* @param list 集合
* @param clazz c
* @param <T> 类型
* @return List<T>
* @description 用于jpa查询自定义vo用的
*/
public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz) {
List<T> returnList = new ArrayList<>();
if (list.size() == 0) {
return returnList;
}
Class[] c2 = null;
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
Class[] tClass = constructor.getParameterTypes();
if (tClass.length == list.get(0).length) {
c2 = tClass;
break;
}
}
//构造方法实例化对象
for (Object[] o : list) {
Constructor<T> constructor = null;
try {
constructor = clazz.getConstructor(c2);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
assert constructor != null;
returnList.add(constructor.newInstance(o));
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return returnList;
}
/**
* @param object 要强转的对象 , entityClass 强转后的类型
*/
public static <T> T convertBean(Object object, Class<T> entityClass) {
if (null == object) {
return null;
}
return JSON.parseObject(JSON.toJSONString(object), entityClass);
}
/**
* @param object 要转话的对象
*/
public static Map<?, ?> objectToMap(Object object) {
return convertBean(object, Map.class);
}
/**
* @param map map集合, t 对象
*/
public static <T> T mapToObject(Map<String, Object> map, Class<T> beanClass) throws InstantiationException, IllegalAccessException, InvocationTargetException {
T t = beanClass.newInstance();
Field[] declaredFields = t.getClass().getDeclaredFields();
for(Field field:declaredFields){
int mod = field.getModifiers();
if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
continue;
}
field.setAccessible(true);
field.set(t, map.get(field.getName()));
}
return t;
}
/**
* @param source 资源对象, target 目标对象, ignoreProperties 赋值new String[]{}
* @return T target对象
*/
public static <T> T copy(Object source, Class<T> target, String... ignoreProperties) {
T targetInstance = null;
try {
targetInstance = target.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
if (ArrayUtils.isEmpty(ignoreProperties)) {
assert targetInstance != null;
BeanUtils.copyProperties(source, targetInstance);
} else {
assert targetInstance != null;
BeanUtils.copyProperties(source, targetInstance, ignoreProperties);
}
return targetInstance;
}
/**
* 从List<A> copy到List<B>
* @param list List<B>
* @param clazz B
* @return List<B>
*/
public static <T> List<T> copy(List<?> list,Class<T> clazz){
String oldOb = JSON.toJSONString(list);
return JSON.parseArray(oldOb, clazz);
}
public static <T, E> List<T> copyList(List<E> list, Class<T> target, String... ignoreProperties) {
List<T> targetList = new ArrayList<>();
if (CollectionUtils.isEmpty(list)) {
return targetList;
}
for (E e : list) {
targetList.add(copy(e, target, ignoreProperties));
}
return targetList;
}
/**
* 功能描述: Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
*
*/
public static Map<String, String> transBean2Map(Object obj) {
if (obj == null) {
return null;
}
Map<String, String> map = new HashMap<String, String>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
// 过滤class属性
if (!"class".equals(key)) {
// 得到property对应的getter方法
Method getter = property.getReadMethod();
Object value = getter.invoke(obj);
map.put(key, value.toString());
}
}
} catch (Exception e) {
log.error("transBean2Map Error " + e);
}
return map;
}
/**
* 属性复制跳过为null的值
* @param source 提供值的obj
* @param target 接收值的obj
* @param <T>
* @return target
*/
public static <T> T copyNotNullProperties(T source, T target){
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
return target;
}
/**
* 获取值为Null的字段名称
* @param source
* @return
*/
public static String[] getNullPropertyNames (Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<>();
for(java.beans.PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) emptyNames.add(pd.getName());
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
}

42
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/vo/VipOrderVo.java

@ -0,0 +1,42 @@
package com.bnyer.common.core.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author :WXC
* @Date :2023/03/27
* @description :
*/
@Getter
@Setter
@NoArgsConstructor
public class VipOrderVo {
@ApiModelProperty(value="手机号")
private String phone;
@ApiModelProperty(value="用户vip表id")
private Long userVipId;
@ApiModelProperty(value="vip类型状态(0->月卡;1->季卡;2->年卡)")
private String type;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value="开始时间")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value="到期时间")
private Date endTime;
@ApiModelProperty(value="总金额")
private BigDecimal totalAmount;
}

10
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/web/domain/AjaxResult.java

@ -2,6 +2,7 @@ package com.bnyer.common.core.web.domain;
import java.util.HashMap;
import com.bnyer.common.core.constant.HttpStatus;
import com.bnyer.common.core.enums.ResponseEnum;
import com.bnyer.common.core.utils.StringUtils;
/**
@ -159,4 +160,13 @@ public class AjaxResult extends HashMap<String, Object>
{
return new AjaxResult(code, msg, null);
}
/**
* 返回错误消息
* @param responseEnum
* @return
*/
public static AjaxResult error(ResponseEnum responseEnum) {
return new AjaxResult(responseEnum.value(), responseEnum.getMsg(), null);
}
}

20
bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/adapter/CacheTtlAdapter.java

@ -0,0 +1,20 @@
package com.bnyer.common.redis.adapter;
import com.bnyer.common.redis.bo.CacheNameWithTtlBo;
import java.util.List;
/**
* @author :WXC
* @Date :2023/03/28
* @description : 实现该接口之后根据缓存的cacheName和ttl将缓存进行过期
*/
public interface CacheTtlAdapter {
/**
* 根据缓存的cacheName和ttl将缓存进行过期
* @return 需要独立设置过期时间的缓存列表
*/
List<CacheNameWithTtlBo> listCacheNameWithTtl();
}

28
bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/bo/CacheNameWithTtlBo.java

@ -0,0 +1,28 @@
package com.bnyer.common.redis.bo;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @author :WXC
* @Date :2023/03/28
* @description : 通过 cacheName 配置 时间告诉缓存多久清楚一遍
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class CacheNameWithTtlBo {
/**
* 缓存名称
*/
private String cacheName;
/**
* 过期时间
*/
private Integer ttl;
}

141
bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/configure/RedisConfig.java

@ -1,17 +1,31 @@
package com.bnyer.common.redis.configure;
import com.bnyer.common.redis.adapter.CacheTtlAdapter;
import com.bnyer.common.redis.bo.CacheNameWithTtlBo;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* redis配置
@ -22,29 +36,114 @@ import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, CacheTtlAdapter cacheTtlAdapter) {
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
RedisCacheManager redisCacheManager = new RedisCacheManager(
RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
// 默认策略,未配置的 key 会使用这个
this.getRedisCacheConfigurationWithTtl(3600),
// 指定 key 策略
this.getRedisCacheConfigurationMap(cacheTtlAdapter));
redisCacheManager.setTransactionAware(true);
return redisCacheManager;
}
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap(CacheTtlAdapter cacheTtlAdapter) {
if (cacheTtlAdapter == null) {
return Collections.emptyMap();
}
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(16);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);
for (CacheNameWithTtlBo cacheNameWithTtlBO : cacheTtlAdapter.listCacheNameWithTtl()) {
redisCacheConfigurationMap.put(cacheNameWithTtlBO.getCacheName(),
getRedisCacheConfigurationWithTtl(cacheNameWithTtlBO.getTtl()));
}
return redisCacheConfigurationMap;
}
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer()))
.entryTtl(Duration.ofSeconds(seconds));
return redisCacheConfiguration;
}
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
/**
* 自定义redis序列化的机制,重新定义一个ObjectMapper.防止和MVC的冲突
*/
@Bean
public RedisSerializer<Object> redisSerializer() {
ObjectMapper objectMapper = new ObjectMapper();
// // 反序列化时候遇到不匹配的属性并不抛出异常
// objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// // 序列化时候遇到空对象不抛出异常
// objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// // 反序列化的时候如果是无效子类型,不抛出异常
// objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
// // 不使用默认的dateTime进行序列化,
// objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
// // 使用JSR310提供的序列化类,里面包含了大量的JDK8时间序列化类
// objectMapper.registerModule(new JavaTimeModule());
// 启用反序列化所需的类型信息,在属性中添加@class
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 配置null值的序列化器
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
serializer.setObjectMapper(objectMapper);
return serializer;
}
// @Bean
// @SuppressWarnings(value = { "unchecked", "rawtypes" })
// public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
// {
// RedisTemplate<Object, Object> template = new RedisTemplate<>();
// template.setConnectionFactory(connectionFactory);
//
// FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
//
// ObjectMapper mapper = new ObjectMapper();
// mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// serializer.setObjectMapper(mapper);
//
// // 使用StringRedisSerializer来序列化和反序列化redis的key值
// template.setKeySerializer(new StringRedisSerializer());
// template.setValueSerializer(serializer);
//
// // Hash的key也采用StringRedisSerializer的序列化方式
// template.setHashKeySerializer(new StringRedisSerializer());
// template.setHashValueSerializer(serializer);
//
// template.afterPropertiesSet();
// return template;
// }
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory,
RedisSerializer<Object> redisSerializer) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setDefaultSerializer(redisSerializer);
template.setValueSerializer(redisSerializer);
template.setHashValueSerializer(redisSerializer);
template.setKeySerializer(StringRedisSerializer.UTF_8);
template.setHashKeySerializer(StringRedisSerializer.UTF_8);
template.afterPropertiesSet();
return template;
}
@Bean
@ConditionalOnMissingBean
public CacheTtlAdapter cacheTtl() {
return Collections::emptyList;
}
}

20
bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/CacheNames.java

@ -0,0 +1,20 @@
package com.bnyer.common.redis.constant;
/**
* @author :WXC
* @Date :2023/03/28
* @description :
*/
public class CacheNames {
/**
*
* 参考CacheKeyPrefix
* cacheNames key 之间的默认连接字符
*/
public final static String UNION = "::";
/**
* key内部的连接字符自定义
*/
public final static String UNION_KEY = ":";
}

25
bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/OrderCacheNames.java

@ -0,0 +1,25 @@
package com.bnyer.common.redis.constant;
/**
* @author :WXC
* @Date :2023/03/27
* @description :
*/
public class OrderCacheNames {
/**
* 会员订单前缀
*/
public static final String VIP_ORDER_PREFIX = "vip_cloud_order:";
/**
* 确认订单信息缓存
*/
public static final String ORDER_CONFIRM_KEY = "order:confirm";
/**
* 订单uid
*/
public static final String ORDER_CONFIRM_UID_KEY = "order:uid_confirm";
}

49
bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/service/RedisCacheService.java

@ -0,0 +1,49 @@
package com.bnyer.common.redis.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
/**
* @author :WXC
* @Date :2023/03/28
* @description :
*/
@Component
public class RedisCacheService {
private final CacheManager cacheManager;
@Autowired
public RedisCacheService(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@SuppressWarnings({ "unchecked" })
public <T> T getCache(String cacheName, String key) {
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
return null;
}
Cache.ValueWrapper valueWrapper = cache.get(key);
if (valueWrapper == null) {
return null;
}
return (T) valueWrapper.get();
}
public void putCache(String cacheName, String key, Object value) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cache.put(key, value);
}
}
public void evictCache(String cacheName, String key) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cache.evict(key);
}
}
}

29
bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/service/RedisService.java

@ -1,17 +1,15 @@
package com.bnyer.common.redis.service;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.apache.poi.ss.formula.functions.T;
import cn.hutool.core.util.StrUtil;
import com.bnyer.common.core.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* spring redis 工具类
*
@ -353,4 +351,21 @@ public class RedisService
return redisTemplate.opsForHyperLogLog().add(today + page+"UV", ip);
}
public boolean cad(String key, String value) {
if (key.contains(StrUtil.SPACE) || value.contains(StrUtil.SPACE)) {
throw new ServiceException("系统繁忙,请稍候重试!");
}
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//通过lure脚本原子验证令牌和删除令牌
Long result = (Long) redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class),
Collections.singletonList(key),
value);
return !Objects.equals(result, 0L);
}
}

3
bnyer-common/bnyer-common-redis/src/main/resources/META-INF/spring.factories

@ -2,6 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.bnyer.common.redis.configure.RedisConfig,\
com.bnyer.common.redis.service.RedisService,\
com.bnyer.common.redis.configure.RedissonConfig,\
com.bnyer.common.redis.service.RedissonService
com.bnyer.common.redis.service.RedissonService,\
com.bnyer.common.redis.service.RedisCacheService

32
bnyer-common/bnyer-common-rocketmq/pom.xml

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.dimensionalnode</groupId>
<artifactId>bnyer-common</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>
bnyer-common-rocketmq消息队列模块
</description>
<artifactId>bnyer-common-rocketmq</artifactId>
<dependencies>
<!-- bnyer Common Core-->
<dependency>
<groupId>com.dimensionalnode</groupId>
<artifactId>bnyer-common-core</artifactId>
</dependency>
<!-- bnyer Common rocketmq-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

38
bnyer-common/bnyer-common-rocketmq/src/main/java/com/bnyer/common/rocketmq/config/RocketMqAdapter.java

@ -0,0 +1,38 @@
package com.bnyer.common.rocketmq.config;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
/**
* @author :WXC
* @Date :2023/03/24
* @description :
*/
@RefreshScope
@Configuration
public class RocketMqAdapter {
@Autowired
private RocketMQMessageConverter rocketMqMessageConverter;
@Value("${rocketmq.name-server:}")
private String nameServer;
public RocketMQTemplate getTemplateByTopicName(String topic){
RocketMQTemplate mqTemplate = new RocketMQTemplate();
DefaultMQProducer producer = new DefaultMQProducer(topic);
producer.setNamesrvAddr(nameServer);
producer.setRetryTimesWhenSendFailed(RocketMqConstant.RETRY_FAILED_COUNT);
producer.setRetryTimesWhenSendAsyncFailed(RocketMqConstant.ASYNC_RETRY_FAILED_COUNT);
producer.setSendMsgTimeout((int) RocketMqConstant.TIMEOUT);
mqTemplate.setProducer(producer);
mqTemplate.setMessageConverter(rocketMqMessageConverter.getMessageConverter());
return mqTemplate;
}
}

40
bnyer-common/bnyer-common-rocketmq/src/main/java/com/bnyer/common/rocketmq/config/RocketMqConstant.java

@ -0,0 +1,40 @@
package com.bnyer.common.rocketmq.config;
/**
* @author :WXC
* @Date :2023/03/24
* @description :
*/
public class RocketMqConstant {
/**
* 默认发送消息超时时间
*/
public static final long TIMEOUT = 3000;
/**
* 延迟队列取消订单时间实际上30分钟
* 按顺序匹配1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h (1-18)
*/
public static final int CANCEL_ORDER_DELAY_LEVEL = 16;
/**
* 发送消息失败重试次数默认2
*/
public static final int RETRY_FAILED_COUNT = 2;
/**
* 发送异步消息失败重试次数默认2
*/
public static final int ASYNC_RETRY_FAILED_COUNT = 2;
/**
* vip订单取消
*/
public static final String VIP_ORDER_CANCEL_TOPIC = "vip-order-cancel-topic";
/**
* vip订单支付成功
*/
public static final String VIP_ORDER_PAY_SUCCESS_TOPIC = "vip-order-pay-success-topic";
}

1
bnyer-common/pom.xml

@ -16,6 +16,7 @@
<module>bnyer-common-security</module>
<module>bnyer-common-datascope</module>
<module>bnyer-common-datasource</module>
<module>bnyer-common-rocketmq</module>
</modules>
<artifactId>bnyer-common</artifactId>

24
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipTypeConstant.java

@ -1,24 +0,0 @@
package com.bnyer.img.constants;
/**
* 用户会员vip常量
* @author chengkun
* @date 2022/4/21 18:12
*/
public class UserVipTypeConstant {
/**
* 月卡
*/
public static final String MONTH_CARD = "0";
/**
* 季卡
*/
public static final String SEASON_CARD = "1";
/**
* 年卡
*/
public static final String YEAR_CARD = "2";
}

22
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/UserVipServiceRecordImpl.java

@ -5,10 +5,8 @@ import com.bnyer.common.core.constant.RedisKeyConstant;
import com.bnyer.common.core.domain.UserVipRecord;
import com.bnyer.common.core.dto.PayUserVipDto;
import com.bnyer.common.core.exception.ServiceException;
import com.bnyer.common.core.utils.DateUtils;
import com.bnyer.common.redis.service.RedissonService;
import com.bnyer.img.constants.UserVipOrderStatusConstant;
import com.bnyer.img.constants.UserVipTypeConstant;
import com.bnyer.img.mapper.UserVipRecordMapper;
import com.bnyer.img.service.UserVipRecordService;
import lombok.extern.slf4j.Slf4j;
@ -50,16 +48,16 @@ public class UserVipServiceRecordImpl implements UserVipRecordService {
userVipRecord.setIsShow("1");
Date startTime = new Date();
userVipRecord.setStartTime(startTime);
if(userVipRecord.getType().equals(UserVipTypeConstant.MONTH_CARD)){
//计算月卡(30天)的结束时间
userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 30));
}else if(userVipRecord.getType().equals(UserVipTypeConstant.SEASON_CARD)){
//结算季卡(90天)的结束时间
userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 90));
}else{
//计算年卡(365天)的结束时间
userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 365));
}
// if(userVipRecord.getType().equals(UserVipTypeConstant.MONTH_CARD)){
// //计算月卡(30天)的结束时间
// userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 30));
// }else if(userVipRecord.getType().equals(UserVipTypeConstant.SEASON_CARD)){
// //结算季卡(90天)的结束时间
// userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 90));
// }else{
// //计算年卡(365天)的结束时间
// userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 365));
// }
}else{
userVipRecord.setStatus(UserVipOrderStatusConstant.PAY_EXCEPTION);
log.error("用户会员vip支付异常,锁被占用!");

5
bnyer-services/bnyer-order/pom.xml

@ -89,6 +89,11 @@
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- bnyer Common Rocketmq-->
<dependency>
<groupId>com.dimensionalnode</groupId>
<artifactId>bnyer-common-rocketmq</artifactId>
</dependency>
<!--任务调度中心-->
<!-- <dependency>-->
<!-- <groupId>com.xuxueli</groupId>-->

2
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/BnyerOrderApplication.java

@ -15,7 +15,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication
@SpringBootApplication(scanBasePackages = { "com.bnyer" })
@EnableAsync
public class BnyerOrderApplication
{

27
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/OrderCacheTtlAdapter.java

@ -0,0 +1,27 @@
package com.bnyer.order.config;
import com.bnyer.common.redis.adapter.CacheTtlAdapter;
import com.bnyer.common.redis.bo.CacheNameWithTtlBo;
import com.bnyer.common.redis.constant.OrderCacheNames;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* @author :WXC
* @Date :2023/03/28
* @description :
*/
@Component
public class OrderCacheTtlAdapter implements CacheTtlAdapter{
@Override
public List<CacheNameWithTtlBo> listCacheNameWithTtl() {
List<CacheNameWithTtlBo> cacheNameWithTtls = new ArrayList<>();
// 确认订单缓存30分钟
cacheNameWithTtls.add(new CacheNameWithTtlBo(OrderCacheNames.VIP_ORDER_PREFIX + OrderCacheNames.ORDER_CONFIRM_UID_KEY, 60 * 30));
cacheNameWithTtls.add(new CacheNameWithTtlBo(OrderCacheNames.VIP_ORDER_PREFIX + OrderCacheNames.ORDER_CONFIRM_KEY, 60 * 30));
return cacheNameWithTtls;
}
}

28
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/RocketMqConfig.java

@ -0,0 +1,28 @@
package com.bnyer.order.config;
import com.bnyer.common.rocketmq.config.RocketMqAdapter;
import com.bnyer.common.rocketmq.config.RocketMqConstant;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
/**
* @author :WXC
* @Date :2023/03/24
* @description :
*/
@RefreshScope
@Configuration
public class RocketMqConfig {
@Autowired
private RocketMqAdapter rocketMqAdapter;
@Lazy
@Bean(destroyMethod = "destroy")
public RocketMQTemplate orderCancelMqTemplate() {
return rocketMqAdapter.getTemplateByTopicName(RocketMqConstant.VIP_ORDER_CANCEL_TOPIC);
}
}

78
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/controller/VipOrderController.java

@ -0,0 +1,78 @@
package com.bnyer.order.controller;
import com.bnyer.common.core.context.SecurityContextHolder;
import com.bnyer.common.core.dto.VipOrderDto;
import com.bnyer.common.core.enums.ResponseEnum;
import com.bnyer.common.core.vo.VipOrderVo;
import com.bnyer.common.core.web.controller.BaseController;
import com.bnyer.common.core.web.domain.AjaxResult;
import com.bnyer.common.redis.constant.CacheNames;
import com.bnyer.common.redis.constant.OrderCacheNames;
import com.bnyer.common.redis.service.RedisCacheService;
import com.bnyer.common.redis.service.RedisService;
import com.bnyer.order.service.VipOrderService;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Objects;
/**
* @author :WXC
* @Date :2023/03/24
* @description :
*/
@Api(value = "会员订单相关接口",tags = "会员订单相关接口")
@RestController
@RequestMapping("/order/vip")
@Slf4j
public class VipOrderController extends BaseController {
@Autowired
private RedisService redisService;
@Autowired
private RedisCacheService redisCacheService;
@Autowired
private VipOrderService vipOrderService;
/**
* 生成订单
*/
@PostMapping("/confirmVipOrder")
@Operation(summary = "生成订单,返回订单信息" , description = "传入下单所需要的参数进行下单")
public AjaxResult confirmVipOrder(@Valid @RequestBody VipOrderDto vipOrderDto){
VipOrderVo vipOrderVo = vipOrderService.confirmVipOrder(vipOrderDto);
return AjaxResult.success(vipOrderVo);
}
/**
* 提交订单
*/
@PostMapping("/submitOrder")
@Operation(summary = "提交订单,返回支付流水号" , description = "提交订单,通过支付场景获取订单信息生成订单并返回订单号")
public AjaxResult submitVipOrder() {
// 防止重复提交
Long userId = SecurityContextHolder.getUserId();
VipOrderVo vipOrderVo = redisCacheService.getCache(OrderCacheNames.VIP_ORDER_PREFIX + OrderCacheNames.ORDER_CONFIRM_KEY, String.valueOf(userId));
// 看看订单有没有过期
if (Objects.isNull(vipOrderVo)) {
return AjaxResult.error(ResponseEnum.ORDER_EXPIRED);
}
boolean cad = redisService.cad(OrderCacheNames.VIP_ORDER_PREFIX + OrderCacheNames.ORDER_CONFIRM_UID_KEY + CacheNames.UNION + userId, String.valueOf(userId));
if (!cad) {
return AjaxResult.error(ResponseEnum.REPEAT_ORDER);
}
String orderId = vipOrderService.submitVipOrder(userId,vipOrderVo);
return AjaxResult.success(orderId);
}
}

4
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/controller/testController.java

@ -1,4 +0,0 @@
package com.bnyer.order.controller;
public class testController {
}

30
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/enums/EnumSceneCode.java

@ -0,0 +1,30 @@
package com.bnyer.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author :WXC
* @description :
*/
@Getter
@AllArgsConstructor
public enum EnumSceneCode {
VIP_RECHARGE("1","会员充值"),
;
private String sceneCode;
private String name;
public static String getSceneCodeName(String sceneCode) {
for (EnumSceneCode s : EnumSceneCode.values()) {
if (sceneCode.equals(s.getSceneCode())) {
return s.getName();
}
}
return null;
}
}

32
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/enums/EnumVipType.java

@ -0,0 +1,32 @@
package com.bnyer.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 用户会员vip常量
* @author chengkun
* @date 2022/4/21 18:12
*/
@Getter
@AllArgsConstructor
public enum EnumVipType {
MONTH_CARD("0","月卡"),
SEASON_CARD("1","季卡"),
YEAR_CARD("2","年卡"),
;
private String typeCode;
private String name;
public static String getTypeCodeName(String typeCode) {
for (EnumSceneCode s : EnumSceneCode.values()) {
if (typeCode.equals(s.getSceneCode())) {
return s.getName();
}
}
return null;
}
}

24
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/listener/vip/VipOrderCancelConsumer.java

@ -0,0 +1,24 @@
package com.bnyer.order.listener.vip;
import com.bnyer.common.rocketmq.config.RocketMqConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;
/**
* @author :WXC
* @Date :2023/03/24
* @description :取消订单mq消费监听
*/
@Slf4j
@Component
@RocketMQMessageListener(topic = RocketMqConstant.VIP_ORDER_CANCEL_TOPIC,consumerGroup = RocketMqConstant.VIP_ORDER_CANCEL_TOPIC)
public class VipOrderCancelConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String orderId) {
log.info("收到消息:{}", orderId);
// cancelOrder();
}
}

18
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/listener/vip/VipOrderPaySuccessConsumer.java

@ -0,0 +1,18 @@
//package com.bnyer.order.listener.vip;
//
//import com.bnyer.common.rocketmq.config.RocketMqConstant;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
//import org.springframework.stereotype.Component;
//
///**
// * @author :WXC
// * @Date :2023/03/24
// * @description :订单支付成功mq消费监听
// */
//@Slf4j
//@Component
//@RocketMQMessageListener(topic = RocketMqConstant.VIP_ORDER_PAY_SUCCESS_TOPIC,consumerGroup = RocketMqConstant.VIP_ORDER_PAY_SUCCESS_TOPIC)
//public class VipOrderPaySuccessConsumer {
//
//}

4
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/TestService.java

@ -1,4 +0,0 @@
package com.bnyer.order.service;
public interface TestService {
}

27
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/VipOrderService.java

@ -0,0 +1,27 @@
package com.bnyer.order.service;
import com.bnyer.common.core.dto.VipOrderDto;
import com.bnyer.common.core.vo.VipOrderVo;
/**
* @author :WXC
* @Date :2023/03/27
* @description :
*/
public interface VipOrderService {
/**
* 生成订单返回订单信息
* @param vipOrderDto 下单所需要的参数
* @return 订单信息
*/
VipOrderVo confirmVipOrder(VipOrderDto vipOrderDto);
/**
* 提交订单返回支付流水号
*
* @param userId
* @param vipOrderVo 缓存的订单信息
* @return 支付流水号
*/
String submitVipOrder(Long userId, VipOrderVo vipOrderVo);
}

8
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/TestServiceImpl.java

@ -1,8 +0,0 @@
package com.bnyer.order.service.impl;
import com.bnyer.order.service.TestService;
import org.springframework.stereotype.Service;
@Service
public class TestServiceImpl implements TestService {
}

97
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java

@ -0,0 +1,97 @@
package com.bnyer.order.service.impl;
import com.bnyer.common.core.exception.ServiceException;
import com.bnyer.common.core.utils.DateUtils;
import com.bnyer.common.core.utils.bean.EntityConvertUtil;
import com.bnyer.common.redis.constant.CacheNames;
import com.bnyer.common.redis.constant.OrderCacheNames;
import com.bnyer.common.core.context.SecurityContextHolder;
import com.bnyer.common.core.dto.VipOrderDto;
import com.bnyer.common.core.vo.VipOrderVo;
import com.bnyer.common.redis.service.RedisCacheService;
import com.bnyer.common.redis.service.RedisService;
import com.bnyer.common.rocketmq.config.RocketMqConstant;
import com.bnyer.order.enums.EnumVipType;
import com.bnyer.order.service.VipOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* @author :WXC
* @Date :2023/03/28
* @description :
*/
@Slf4j
@Service
public class VipOrderServiceImpl implements VipOrderService {
@Autowired
private RedisService redisService;
@Autowired
private RedisCacheService redisCacheService;
@Autowired
private RocketMQTemplate orderCancelMqTemplate;
@Override
public VipOrderVo confirmVipOrder(VipOrderDto vipOrderDto) {
Long userId = SecurityContextHolder.getUserId();
//将要返回给前端的完整的订单信息
VipOrderVo vipOrderVo = buildVipOrderVo(vipOrderDto);
// 防止重复提交
redisService.setCacheObject(OrderCacheNames.VIP_ORDER_PREFIX + OrderCacheNames.ORDER_CONFIRM_UID_KEY + CacheNames.UNION + userId, String.valueOf(userId));
// 保存订单计算结果缓存
redisCacheService.putCache(OrderCacheNames.VIP_ORDER_PREFIX + OrderCacheNames.ORDER_CONFIRM_KEY ,String.valueOf(userId), vipOrderVo);
return vipOrderVo;
}
/**
* 构建vip订单
* @param vipOrderDto
* @return
*/
private VipOrderVo buildVipOrderVo(VipOrderDto vipOrderDto) {
VipOrderVo vipOrderVo = EntityConvertUtil.copy(vipOrderDto, VipOrderVo.class);
Date startTime = new Date();
vipOrderVo.setStartTime(startTime);
if(EnumVipType.MONTH_CARD.getTypeCode().equals(vipOrderDto.getType())){
//计算月卡(30天)的结束时间
vipOrderVo.setEndTime(DateUtils.getDateAfter(startTime, 30));
}else if(EnumVipType.SEASON_CARD.getTypeCode().equals(vipOrderDto.getType())){
//结算季卡(90天)的结束时间
vipOrderVo.setEndTime(DateUtils.getDateAfter(startTime, 90));
}else if (EnumVipType.YEAR_CARD.getTypeCode().equals(vipOrderDto.getType())){
//计算年卡(365天)的结束时间
vipOrderVo.setEndTime(DateUtils.getDateAfter(startTime, 365));
}else {
throw new ServiceException("参数异常!");
}
return vipOrderVo;
}
@Override
@Transactional(rollbackFor = Exception.class)
public String submitVipOrder(Long userId,VipOrderVo vipOrderVo) {
String orderId = "123";
//发送消息,如果三十分钟后没有支付,则取消订单
SendStatus sendStatus = orderCancelMqTemplate.syncSend(RocketMqConstant.VIP_ORDER_CANCEL_TOPIC, new GenericMessage<>(orderId), RocketMqConstant.TIMEOUT, RocketMqConstant.CANCEL_ORDER_DELAY_LEVEL).getSendStatus();
if (!Objects.equals(sendStatus,SendStatus.SEND_OK)) {
// 消息发不出去就抛异常,发的出去无所谓
throw new ServiceException("系统繁忙,请稍候重试!");
}else {
log.info("消息发送成功,topic:{}",RocketMqConstant.VIP_ORDER_CANCEL_TOPIC);
}
return orderId;
}
}

6
bnyer-services/bnyer-pay/pom.xml

@ -95,6 +95,12 @@
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- bnyer Common Rocketmq-->
<dependency>
<groupId>com.dimensionalnode</groupId>
<artifactId>bnyer-common-rocketmq</artifactId>
</dependency>
<!--任务调度中心-->
<!-- <dependency>-->

2
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/BnyerPayApplication.java

@ -15,7 +15,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication
@SpringBootApplication(scanBasePackages = { "com.bnyer" })
@EnableAsync
public class BnyerPayApplication
{

28
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/config/RocketMqConfig.java

@ -0,0 +1,28 @@
package com.bnyer.pay.config;
import com.bnyer.common.rocketmq.config.RocketMqAdapter;
import com.bnyer.common.rocketmq.config.RocketMqConstant;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
/**
* @author :WXC
* @Date :2023/03/24
* @description :
*/
@RefreshScope
@Configuration
public class RocketMqConfig {
@Autowired
private RocketMqAdapter rocketMqAdapter;
@Lazy
@Bean(destroyMethod = "destroy")
public RocketMQTemplate orderPaySuccessMqTemplate() {
return rocketMqAdapter.getTemplateByTopicName(RocketMqConstant.VIP_ORDER_PAY_SUCCESS_TOPIC);
}
}

4
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/config/TestConfig.java

@ -1,4 +0,0 @@
package com.bnyer.pay.config;
public class TestConfig {
}

13
pom.xml

@ -46,6 +46,7 @@
<aliPay.version>4.23.21.ALL</aliPay.version>
<wePay.version>4.2.0</wePay.version>
<qiniu.version>7.2.18</qiniu.version>
<rocketmq-springboot.version>2.2.2</rocketmq-springboot.version>
</properties>
<!-- 依赖声明 -->
@ -250,6 +251,13 @@
<version>${bnyer.version}</version>
</dependency>
<!-- 消息队列 -->
<dependency>
<groupId>com.dimensionalnode</groupId>
<artifactId>bnyer-common-rocketmq</artifactId>
<version>${bnyer.version}</version>
</dependency>
<!-- 日志记录 -->
<dependency>
<groupId>com.dimensionalnode</groupId>
@ -282,6 +290,11 @@
<artifactId>qiniu-java-sdk</artifactId>
<version>${qiniu.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>${rocketmq-springboot.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Loading…
Cancel
Save