|
@@ -1,13 +1,38 @@
|
|
|
package com.atguigu.tingshu.order.service.impl;
|
|
|
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.lang.Assert;
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
+import com.atguigu.tingshu.album.AlbumFeignClient;
|
|
|
+import com.atguigu.tingshu.common.constant.RedisConstant;
|
|
|
+import com.atguigu.tingshu.model.album.AlbumInfo;
|
|
|
import com.atguigu.tingshu.model.order.OrderInfo;
|
|
|
+import com.atguigu.tingshu.model.user.VipServiceConfig;
|
|
|
+import com.atguigu.tingshu.order.helper.SignHelper;
|
|
|
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
|
|
|
import com.atguigu.tingshu.order.service.OrderInfoService;
|
|
|
+import com.atguigu.tingshu.user.client.UserFeignClient;
|
|
|
+import com.atguigu.tingshu.vo.order.OrderDerateVo;
|
|
|
+import com.atguigu.tingshu.vo.order.OrderDetailVo;
|
|
|
+import com.atguigu.tingshu.vo.order.OrderInfoVo;
|
|
|
+import com.atguigu.tingshu.vo.order.TradeVo;
|
|
|
+import com.atguigu.tingshu.vo.user.UserInfoVo;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+import static com.atguigu.tingshu.common.constant.SystemConstant.*;
|
|
|
+
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@SuppressWarnings({"all"})
|
|
@@ -16,5 +41,151 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
|
|
@Autowired
|
|
|
private OrderInfoMapper orderInfoMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private UserFeignClient userFeignClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AlbumFeignClient albumFeignClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisTemplate redisTemplate;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对购买商品(VIP会员、专辑、声音)封装订单结算页所需要数据
|
|
|
+ *
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @param tradeVo {购买商品类别,商品ID,声音数量}
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public OrderInfoVo trade(Long userId, TradeVo tradeVo) {
|
|
|
+ //1.创建订单VO
|
|
|
+ OrderInfoVo orderInfoVo = new OrderInfoVo();
|
|
|
+
|
|
|
+ //1.1.初始化订单结算页三个价格:原价、减免价、订单价
|
|
|
+ BigDecimal originalAmount = new BigDecimal("0.00");
|
|
|
+ BigDecimal derateAmount = new BigDecimal("0.00");
|
|
|
+ BigDecimal orderAmount = new BigDecimal("0.00");
|
|
|
+ //1.2.初始化订单结算页两个集合:商品明细集合、商品优惠集合
|
|
|
+ List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
|
|
|
+ List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
|
|
|
+
|
|
|
+ //获取购买商品类别:付款项目类型: 1001-专辑 1002-声音 1003-vip会员
|
|
|
+ String itemType = tradeVo.getItemType();
|
|
|
+ //2.处理购买商品类别:VIP套餐
|
|
|
+ if (ORDER_ITEM_TYPE_VIP.equals(itemType)) {
|
|
|
+ //2.1 远程调用"用户服务"获取套餐详情
|
|
|
+ VipServiceConfig vipServiceConfig = userFeignClient.getVipServiceConfig(tradeVo.getItemId()).getData();
|
|
|
+ Assert.notNull(vipServiceConfig, "套餐:{}不存在", tradeVo.getItemId());
|
|
|
+ //2.2 计算订单相关价格 订单价=原价-减免价
|
|
|
+ originalAmount = vipServiceConfig.getPrice();
|
|
|
+ orderAmount = vipServiceConfig.getDiscountPrice();
|
|
|
+ derateAmount = originalAmount.subtract(orderAmount);
|
|
|
+
|
|
|
+ //2.3 封装订单明细列表
|
|
|
+ OrderDetailVo orderDetailVo = new OrderDetailVo();
|
|
|
+ orderDetailVo.setItemId(tradeVo.getItemId());
|
|
|
+ orderDetailVo.setItemName("VIP套餐:" + vipServiceConfig.getName());
|
|
|
+ orderDetailVo.setItemUrl(vipServiceConfig.getImageUrl());
|
|
|
+ orderDetailVo.setItemPrice(originalAmount);
|
|
|
+ orderDetailVoList.add(orderDetailVo);
|
|
|
+
|
|
|
+ //2.4 封装订单优惠列表
|
|
|
+ if (originalAmount.compareTo(orderAmount) == 1) {
|
|
|
+ OrderDerateVo orderDerateVo = new OrderDerateVo();
|
|
|
+ //订单减免类型 1405-专辑折扣 1406-VIP服务折
|
|
|
+ orderDerateVo.setDerateType(ORDER_DERATE_VIP_SERVICE_DISCOUNT);
|
|
|
+ orderDerateVo.setDerateAmount(derateAmount);
|
|
|
+ orderDerateVo.setRemarks("套餐限时减免:" + derateAmount);
|
|
|
+ orderDerateVoList.add(orderDerateVo);
|
|
|
+ }
|
|
|
+ } else if (ORDER_ITEM_TYPE_ALBUM.equals(itemType)) {
|
|
|
+ //3. 处理购买商品类别:专辑
|
|
|
+ //3.1 远程调用"用户服务"判断是否重复购买专辑 如果是:业务终止
|
|
|
+ Long albumId = tradeVo.getItemId();
|
|
|
+ Boolean isPaid = userFeignClient.isPaidAlbum(albumId).getData();
|
|
|
+ Assert.state(!isPaid, "用户已购买专辑:{}", albumId);
|
|
|
+
|
|
|
+ //3.2 远程调用"专辑服务"获取专辑信息
|
|
|
+ AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();
|
|
|
+ Assert.notNull(albumInfo, "专辑:{}不存在", albumId);
|
|
|
+ //3.2.1 专辑价格
|
|
|
+ BigDecimal price = albumInfo.getPrice();
|
|
|
+ //3.2.2 普通用户折扣
|
|
|
+ BigDecimal discount = albumInfo.getDiscount();
|
|
|
+ //3.2.3 VIP用户折扣
|
|
|
+ BigDecimal vipDiscount = albumInfo.getVipDiscount();
|
|
|
+
|
|
|
+ //3.3 远程调用"用户服务"判断用户身份
|
|
|
+ Boolean isVIP = false;
|
|
|
+ UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
|
|
|
+ Assert.notNull(userInfoVo, "用户:{}不存在", userId);
|
|
|
+ if (userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().after(new Date())) {
|
|
|
+ isVIP = true;
|
|
|
+ }
|
|
|
+ //3.4 计算相关价格
|
|
|
+ //3.4.1 暂时让订单价等于原价
|
|
|
+ originalAmount = price;
|
|
|
+ orderAmount = originalAmount;
|
|
|
+ //3.4.2 如果是普通用户且专辑设置普通用户折扣,则订单价=原价*普通用户折扣
|
|
|
+ if (!isVIP && discount.doubleValue() != -1) {
|
|
|
+ orderAmount =
|
|
|
+ originalAmount.multiply(discount).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
|
|
|
+ derateAmount = originalAmount.subtract(orderAmount);
|
|
|
+ }
|
|
|
+ //3.4.3 如果是VIP用户且专辑设置VIP用户折扣,则订单价=原价*VIP用户折扣
|
|
|
+ if (isVIP && vipDiscount.doubleValue() != -1) {
|
|
|
+ orderAmount =
|
|
|
+ originalAmount.multiply(vipDiscount).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
|
|
|
+ derateAmount = originalAmount.subtract(orderAmount);
|
|
|
+ }
|
|
|
+ //3.5 封装订单明细列表、优惠列表
|
|
|
+ OrderDetailVo orderDetailVo = new OrderDetailVo();
|
|
|
+ orderDetailVo.setItemId(albumId);
|
|
|
+ orderDetailVo.setItemName("专辑:" + albumInfo.getAlbumTitle());
|
|
|
+ orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
|
|
|
+ orderDetailVo.setItemPrice(originalAmount);
|
|
|
+ orderDetailVoList.add(orderDetailVo);
|
|
|
+
|
|
|
+ //3.6 封装订单优惠列表
|
|
|
+ if(originalAmount.compareTo(orderAmount) == 1){
|
|
|
+ OrderDerateVo orderDerateVo = new OrderDerateVo();
|
|
|
+ orderDerateVo.setDerateType(ORDER_DERATE_ALBUM_DISCOUNT);
|
|
|
+ orderDerateVo.setDerateAmount(derateAmount);
|
|
|
+ orderDerateVo.setRemarks("专辑限时减免:"+derateAmount);
|
|
|
+ orderDerateVoList.add(orderDerateVo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //4.TODO 处理购买商品类别:声音
|
|
|
+
|
|
|
+
|
|
|
+ //5.封装订单VO 包含三类数据:价格相关、商品相关、其他杂项
|
|
|
+ //5.1 为订单价、原价、减免价赋值
|
|
|
+ orderInfoVo.setOriginalAmount(originalAmount);
|
|
|
+ orderInfoVo.setOrderAmount(orderAmount);
|
|
|
+ orderInfoVo.setDerateAmount(derateAmount);
|
|
|
+ //5.2 为商品列表、优惠列表赋值
|
|
|
+ orderInfoVo.setOrderDetailVoList(orderDetailVoList);
|
|
|
+ orderInfoVo.setOrderDerateVoList(orderDerateVoList);
|
|
|
+
|
|
|
+ //5.3 为订单VO其他杂项赋值:购买商品类别、流水号、时间戳及签名
|
|
|
+ orderInfoVo.setItemType(itemType);
|
|
|
+ //5.3.1 为当前用户本次订单生成流水号,将流水号存入Redis,有效时间5分钟,解决订单重复提交问题
|
|
|
+ String tradeNo = IdUtil.randomUUID();
|
|
|
+ String tradeKey = RedisConstant.ORDER_TRADE_NO_PREFIX + userId;
|
|
|
+ redisTemplate.opsForValue().set(tradeKey, tradeNo, RedisConstant.ORDER_TRADE_EXPIRE, TimeUnit.MINUTES);
|
|
|
+ orderInfoVo.setTradeNo(tradeNo);
|
|
|
+
|
|
|
+ //5.3.2 为本次订单生产时间戳及签名
|
|
|
+ orderInfoVo.setTimestamp(System.currentTimeMillis());
|
|
|
+ //将订单VO转为Map TODO:VO中包含付款方式"payWay"此时为空 生成签名将排除掉payWay字段,故暂时不参与签名
|
|
|
+ Map<String, Object> map = BeanUtil.beanToMap(orderInfoVo, false, true);
|
|
|
+ String sign = SignHelper.getSign(map);
|
|
|
+ orderInfoVo.setSign(sign);
|
|
|
+ //6.响应订单VO
|
|
|
+ return orderInfoVo;
|
|
|
+ }
|
|
|
|
|
|
}
|