diff --git a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumUserClientType.java b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumUserClientType.java index 8cfa658..ce8b869 100644 --- a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumUserClientType.java +++ b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumUserClientType.java @@ -1,5 +1,6 @@ package com.bnyer.common.core.enums; +import com.bnyer.common.core.exception.ServiceException; import lombok.AllArgsConstructor; import lombok.Getter; @@ -33,7 +34,13 @@ public enum EnumUserClientType { return s.getCode(); } } - return null; + throw new ServiceException("userClientType 未匹配上对应的类型"); + } + + public static EnumUserClientType getEnumByType(Integer type) { + return Arrays.stream(values()) + .filter(userClientType -> userClientType.getType() == type) + .findFirst().orElseThrow(() -> new ServiceException("type 未匹配上对应的客户端类型")); } public static EnumUserClientType getTypeByCode(String code) { diff --git a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumVipType.java b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumVipType.java index 544a5a8..622a655 100644 --- a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumVipType.java +++ b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumVipType.java @@ -14,25 +14,12 @@ import java.util.Objects; @AllArgsConstructor public enum EnumVipType { - IMG_VIP("img","下图会员"), - VIDEO_VIP("video","视频会员"), - AI_VIP("ai","ai会员"), - UNKNOWN("unknown","未知"), + YJ_VIP("yj-vip"), + UNKNOWN("unknown"), ; private final String code; - private final String name; - - public static String getNameByCode(String code) { - for (EnumVipType s : EnumVipType.values()) { - if (Objects.equals(code, s.code)) { - return s.getName(); - } - } - return null; - } - public static EnumVipType getVipTypeByCode(String code) { return Arrays.stream(values()) .filter(vipCategory -> Objects.equals(vipCategory.getCode(), code)) diff --git a/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/bo/CacheNameWithTtlBo.java b/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/bo/CacheNameWithTtlBo.java index 6c29cb2..99fbfa3 100644 --- a/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/bo/CacheNameWithTtlBo.java +++ b/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/bo/CacheNameWithTtlBo.java @@ -22,7 +22,7 @@ public class CacheNameWithTtlBo { private String cacheName; /** - * 过期时间 + * 过期时间:单位秒 */ private Integer ttl; } diff --git a/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/CacheNames.java b/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/CacheNames.java index c3051a2..e0aa1f4 100644 --- a/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/CacheNames.java +++ b/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/CacheNames.java @@ -5,16 +5,16 @@ package com.bnyer.common.redis.constant; * @Date :2023/03/28 * @description : */ -public class CacheNames { +public interface CacheNames { /** * * 参考CacheKeyPrefix * cacheNames 与 key 之间的默认连接字符 */ - public final static String UNION = "::"; + String UNION = "::"; /** * key内部的连接字符(自定义) */ - public final static String UNION_KEY = ":"; + String UNION_KEY = ":"; } diff --git a/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/OrderCacheNames.java b/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/OrderCacheNames.java index b601dd6..fc40196 100644 --- a/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/OrderCacheNames.java +++ b/bnyer-common/bnyer-common-redis/src/main/java/com/bnyer/common/redis/constant/OrderCacheNames.java @@ -5,21 +5,20 @@ package com.bnyer.common.redis.constant; * @Date :2023/03/27 * @description : */ -public class OrderCacheNames { +public interface OrderCacheNames { /** - * 会员订单前缀 + * 订单前缀 */ - public static final String VIP_ORDER_PREFIX = "vip_cloud_order:"; + String ORDER_PREFIX = "bnyer_order:"; /** - * 确认订单信息缓存 + * 会员订单前缀 */ - public static final String ORDER_CONFIRM_KEY = "order:confirm"; + String VIP_ORDER_PREFIX = "vip_order:"; /** - * 订单uid + * 会员确认订单 */ - public static final String ORDER_CONFIRM_UID_KEY = "order:uid_confirm"; - + String VIP_ORDER_CONFIRM = VIP_ORDER_PREFIX + "order_confirm"; } diff --git a/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/OrderCacheTtlAdapter.java b/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/OrderCacheTtlAdapter.java index 9155ba0..7c67965 100644 --- a/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/OrderCacheTtlAdapter.java +++ b/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/config/OrderCacheTtlAdapter.java @@ -1,7 +1,9 @@ package com.bnyer.order.config; +import com.bnyer.common.core.enums.EnumUserClientType; import com.bnyer.common.redis.adapter.CacheTtlAdapter; import com.bnyer.common.redis.bo.CacheNameWithTtlBo; +import com.bnyer.common.redis.constant.CacheNames; import com.bnyer.common.redis.constant.OrderCacheNames; import org.springframework.stereotype.Component; @@ -20,8 +22,12 @@ public class OrderCacheTtlAdapter implements CacheTtlAdapter{ public List listCacheNameWithTtl() { List 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)); + //cacheNameWithTtls.add(new CacheNameWithTtlBo(OrderCacheNames.ORDER_CONFIRM_UID_KEY, 60 * 30)); + for (EnumUserClientType userClientType : EnumUserClientType.values()) { + cacheNameWithTtls.add(new CacheNameWithTtlBo(OrderCacheNames.ORDER_PREFIX + userClientType.getCode() + + CacheNames.UNION_KEY + + OrderCacheNames.VIP_ORDER_CONFIRM, 60 * 30)); + } return cacheNameWithTtls; } } diff --git a/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/enums/EnumVipType.java b/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/enums/EnumVipType.java deleted file mode 100644 index 559ff0b..0000000 --- a/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/enums/EnumVipType.java +++ /dev/null @@ -1,50 +0,0 @@ -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","月卡", com.bnyer.common.core.enums.EnumVipType.IMG_VIP), - SEASON_CARD("1","季卡", com.bnyer.common.core.enums.EnumVipType.IMG_VIP), - YEAR_CARD("2","年卡", com.bnyer.common.core.enums.EnumVipType.IMG_VIP), - - //========================视频会员(待扩展)=================== - - - - //========================AI会员(待扩展)==================== - ; - - private final String typeCode; - - private final String typeName; - - private final com.bnyer.common.core.enums.EnumVipType enumVipType; - - public static String getNameByTypeCode(String typeCode) { - for (EnumVipType s : com.bnyer.order.enums.EnumVipType.values()) { - if (typeCode.equals(s.getTypeCode())) { - return s.getTypeName(); - } - } - return null; - } - - public static String getCategoryByTypeCode(String typeCode){ - for (EnumVipType s : com.bnyer.order.enums.EnumVipType.values()) { - if (typeCode.equals(s.getTypeCode())) { - return s.getEnumVipType().getCode(); - } - } - return null; - } -} diff --git a/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java b/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java index db4136f..c78311e 100644 --- a/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java +++ b/bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java @@ -2,21 +2,23 @@ package com.bnyer.order.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.bnyer.common.core.constant.ServiceNameConstants; import com.bnyer.common.core.domain.R; import com.bnyer.common.core.domain.VipOrder; import com.bnyer.common.core.enums.*; import com.bnyer.common.core.exception.ServiceException; import com.bnyer.common.core.utils.DateUtils; import com.bnyer.common.core.utils.OrderUtil; +import com.bnyer.common.core.utils.Sm4Util; import com.bnyer.common.core.utils.StringUtils; import com.bnyer.common.core.utils.bean.EntityConvertUtil; -import com.bnyer.common.core.utils.uuid.IdUtils; import com.bnyer.common.core.vo.UserInfoVo; +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.rocketmq.constant.RocketMqConstant; -import com.bnyer.common.rocketmq.constant.RocketMqRepeatConstant; import com.bnyer.common.rocketmq.constant.RocketMqTag; import com.bnyer.common.rocketmq.constant.RocketMqTopic; import com.bnyer.common.rocketmq.domain.img.AddUserVipRecordMessage; @@ -70,6 +72,11 @@ public class VipOrderServiceImpl implements VipOrderService { @Autowired private RemoteUserVipService remoteUserVipService; + @Autowired + private RedisCacheService redisCacheService; + + + /** * 查询会员订单列表信息 * @param query @@ -113,22 +120,57 @@ public class VipOrderServiceImpl implements VipOrderService { @Override @Transactional(rollbackFor = Exception.class) public String addVipOrder(AddVipOrderDto addVipOrderDto) { - //构建订单 - VipOrder vipOrder = buildVipOrder(addVipOrderDto); - vipOrderMapper.insert(vipOrder); - String orderNo = vipOrder.getOrderNo(); - //发送消息,如果三十分钟后没有支付,则取消订单 - VipOrderCancelMessage vipOrderCancelMessage = new VipOrderCancelMessage(); - vipOrderCancelMessage.setOrderNo(orderNo); - //延时消息不走消息表,因为延时消息最少支持秒级延时,定时任务不可能对消息表进行秒级扫描,那样性能损耗太大了 - //所以确保消息一定发送成功,走同步发送,如果发送失败直接抛异常,确保本地事物回滚 - SendStatus sendStatus = rocketMQEnhanceTemplate.send(RocketMqTopic.ORDER_CANCEL_TOPIC, RocketMqTag.ORDER_VIP_TAG, vipOrderCancelMessage, RocketMqConstant.THIRTY_MINUTES).getSendStatus(); - if (SendStatus.SEND_OK != sendStatus){ - throw new ServiceException("下单失败,请重试"); + VipOrder vipOrder = getCacheVipOrder(addVipOrderDto); + String orderNo; + if (ObjectUtil.isNull(vipOrder)){ + //构建订单 + vipOrder = buildVipOrder(addVipOrderDto); + vipOrderMapper.insert(vipOrder); + //缓存订单,有效期30分钟,防止用户一直创建重复的订单 + cacheOrder(vipOrder); + orderNo = vipOrder.getOrderNo(); + //发送消息,如果三十分钟后没有支付,则取消订单 + VipOrderCancelMessage vipOrderCancelMessage = new VipOrderCancelMessage(); + vipOrderCancelMessage.setOrderNo(orderNo); + //延时消息不走消息表,因为延时消息最少支持秒级延时,定时任务不可能对消息表进行秒级扫描,那样性能损耗太大了 + //所以确保消息一定发送成功,走同步发送,如果发送失败直接抛异常,确保本地事物回滚 + SendStatus sendStatus = rocketMQEnhanceTemplate.send(RocketMqTopic.ORDER_CANCEL_TOPIC, RocketMqTag.ORDER_VIP_TAG, vipOrderCancelMessage, RocketMqConstant.THIRTY_MINUTES).getSendStatus(); + if (SendStatus.SEND_OK != sendStatus){ + throw new ServiceException("下单失败,请重试"); + } + }else { + orderNo = vipOrder.getOrderNo(); } return orderNo; } + /** + * 获取缓存中的订单信息 + * @param addVipOrderDto + * @return + */ + private VipOrder getCacheVipOrder(AddVipOrderDto addVipOrderDto) { + UserInfoVo userInfo = SecurityUtils.getUserInfo(); + Long userId = userInfo.getId(); + String code = EnumUserClientType.getCodeByType(userInfo.getUserClientType()); + String key = addVipOrderDto.getVipId() + CacheNames.UNION_KEY + userId; + return redisCacheService.getCache( OrderCacheNames.ORDER_PREFIX + code + + CacheNames.UNION_KEY + OrderCacheNames.VIP_ORDER_CONFIRM,key); + } + + /** + * 缓存订单,防止用户一直创建重复的订单 + * @param vipOrder + */ + private void cacheOrder(VipOrder vipOrder) { + UserInfoVo userInfo = SecurityUtils.getUserInfo(); + Long userId = userInfo.getId(); + String code = EnumUserClientType.getCodeByType(userInfo.getUserClientType()); + String key = vipOrder.getVipId() + CacheNames.UNION_KEY + userId; + redisCacheService.putCache( OrderCacheNames.ORDER_PREFIX + code + + CacheNames.UNION_KEY + OrderCacheNames.VIP_ORDER_CONFIRM, key, vipOrder); + } + /** * 构建订单 * @param addVipOrderDto @@ -145,13 +187,9 @@ public class VipOrderServiceImpl implements VipOrderService { VipOrder vipOrder = null; EnumVipType enumVipType = EnumVipType.getVipTypeByCode(userVipVo.getVipTypeCode()); switch (enumVipType){ - case IMG_VIP: + case YJ_VIP: vipOrder = buildImgVipOrder(userVipVo,addVipOrderDto); break; - case VIDEO_VIP: - break; - case AI_VIP: - break; default: throw new ServiceException("vipTypeCode 未匹配上对应分类"); } @@ -172,18 +210,13 @@ public class VipOrderServiceImpl implements VipOrderService { vipOrder.setVipCode(userVipVo.getVipCode()); vipOrder.setVipName(userVipVo.getVipName()); vipOrder.setVipTypeName(userVipVo.getVipTypeName()); - //// TODO: 2023/05/10 待加密 - vipOrder.setPhone(addVipOrderDto.getPhone()); + vipOrder.setPhone(StringUtils.isNotBlank(addVipOrderDto.getPhone())? + Sm4Util.sm4Encryption(addVipOrderDto.getPhone()):null); vipOrder.setVipName(userVipVo.getVipName()); vipOrder.setVipTypeName(userVipVo.getVipTypeName()); vipOrder.setPayAmount(userVipVo.getPrice()); vipOrder.setVipTypeName(userVipVo.getVipTypeName()); vipOrder.setUserId(userId); -// vipOrder.setIsDelay("0"); -// vipOrder.setStartTime(nowDate); -// EnumTimeUnit enumTimeUnitByUnit = EnumTimeUnit.getEnumTimeUnitByUnit(userVipVo.getValidTimeUnit()); -// //计算会员结束时间 -// vipOrder.setEndTime(DateUtils.getDateByType(enumTimeUnitByUnit,nowDate, userVipVo.getValidTimeNum())); EnumTimeUnit enumTimeUnitByUnit = EnumTimeUnit.getEnumTimeUnitByUnit(userVipVo.getValidTimeUnit()); //计算本次开通的天数 Date nowDate = new Date(); diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/PayInfoServiceImpl.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/PayInfoServiceImpl.java index e011df4..0147a7f 100644 --- a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/PayInfoServiceImpl.java +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/PayInfoServiceImpl.java @@ -1,14 +1,13 @@ package com.bnyer.pay.service.impl; +import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.bnyer.common.core.constant.ServiceNameConstants; import com.bnyer.common.core.domain.PayInfo; import com.bnyer.common.core.enums.EnumSceneCode; import com.bnyer.common.core.enums.ResponseEnum; import com.bnyer.common.core.exception.ServiceException; import com.bnyer.common.core.utils.bean.EntityConvertUtil; -import com.bnyer.common.core.utils.uuid.IdUtils; import com.bnyer.common.rocketmq.constant.RocketMqTag; import com.bnyer.common.rocketmq.constant.RocketMqTopic; import com.bnyer.common.rocketmq.domain.order.VipOrderPayNotifyMessage; @@ -52,8 +51,15 @@ public class PayInfoServiceImpl implements PayInfoService { */ @Override public void addPayInfo(AddPayInfoDto dto) { + //判断是否是原来的订单表订单号支付,如果是更新信息即可,否则创建支付单信息 + PayInfo oldPayInfo = payInfoMapper.selectOne(new LambdaQueryWrapper().eq(PayInfo::getOrderNo, dto.getOrderNo())); PayInfo payInfo = dto.toEntity(); - payInfoMapper.insert(payInfo); + if (ObjectUtil.isNull(oldPayInfo)){ + payInfoMapper.insert(payInfo); + }else { + payInfo.setId(oldPayInfo.getId()); + payInfoMapper.updateById(payInfo); + } } /**