|
@@ -8,8 +8,10 @@
|
|
|
- 购买项目-VIP(允许重复购买)
|
|
|
- 购买项目-专辑(只能购买一次)
|
|
|
- 购买项目-声音(只能购买一次)
|
|
|
+ - 结算商品代码优化-设计模式(策略模式+工厂模式)
|
|
|
- 提交订单(余额付款)-->确保余额安全性
|
|
|
- 分布式事务解决方案-Seata
|
|
|
+ - 虚拟物品发货代码优化-设计模式(策略模式+工厂模式)
|
|
|
- 我的订单
|
|
|
- 订单延迟关单
|
|
|
- RabbitMQ提供延迟任务
|
|
@@ -285,19 +287,16 @@ public class OrderInfoApiController {
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * 用户选择不同虚拟商品进行下单结算,封装渲染订单结算页所需要参数
|
|
|
+ * 三种商品(VIP会员、专辑、声音)订单结算,渲染订单结算页面
|
|
|
*
|
|
|
- * @param tradeVo
|
|
|
- * @return OrderInfoVo订单VO对象,将来订单提交时,需要将订单VO对象提交到服务端
|
|
|
+ * @param tradeVo (购买项目类型、购买项目ID、声音数量)
|
|
|
+ * @return 订单VO信息
|
|
|
*/
|
|
|
@GuiGuLogin
|
|
|
- @Operation(summary = "用户选择不同虚拟商品进行下单结算,封装渲染订单结算页所需要参数")
|
|
|
+ @Operation(summary = "三种商品(VIP会员、专辑、声音)订单结算")
|
|
|
@PostMapping("/orderInfo/trade")
|
|
|
- public Result<OrderInfoVo> tradeData(@Valid @RequestBody TradeVo tradeVo) {
|
|
|
- //1.获取用户ID
|
|
|
- Long userId = AuthContextHolder.getUserId();
|
|
|
- //2.封装订单VO对象
|
|
|
- OrderInfoVo orderInfoVo = orderInfoService.tradeData(userId, tradeVo);
|
|
|
+ public Result<OrderInfoVo> trade(@RequestBody TradeVo tradeVo) {
|
|
|
+ OrderInfoVo orderInfoVo = orderInfoService.trade(tradeVo);
|
|
|
return Result.ok(orderInfoVo);
|
|
|
}
|
|
|
|
|
@@ -318,14 +317,13 @@ public interface OrderInfoService extends IService<OrderInfo> {
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * 订单确认数据汇总
|
|
|
- * @param userId 用户ID
|
|
|
- * @param tradeVo 选择购买商品交易vo对象
|
|
|
- * @return
|
|
|
+ * 三种商品(VIP会员、专辑、声音)订单结算,渲染订单结算页面
|
|
|
+ *
|
|
|
+ * @param tradeVo (购买项目类型、购买项目ID、声音数量)
|
|
|
+ * @return 订单VO信息
|
|
|
*/
|
|
|
- OrderInfoVo tradeData(Long userId, TradeVo tradeVo);
|
|
|
+ OrderInfoVo trade(TradeVo tradeVo);
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
```java
|
|
@@ -378,56 +376,55 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * 订单确认数据汇总
|
|
|
+ * 三种商品(VIP会员、专辑、声音)订单结算,渲染订单结算页面
|
|
|
*
|
|
|
- * @param userId 用户ID
|
|
|
- * @param tradeVo 选择购买商品交易vo对象
|
|
|
- * @return
|
|
|
+ * @param tradeVo (购买项目类型、购买项目ID、声音数量)
|
|
|
+ * @return 订单VO信息
|
|
|
*/
|
|
|
@Override
|
|
|
- public OrderInfoVo tradeData(Long userId, TradeVo tradeVo) {
|
|
|
- //1.初始化OrderInfoVo
|
|
|
+ public OrderInfoVo trade(TradeVo tradeVo) {
|
|
|
+ //0.创建订单VO对象
|
|
|
OrderInfoVo orderInfoVo = new OrderInfoVo();
|
|
|
- //1.1. 初始化相关金额:0.00 此时金额必须是字符串"0.00"
|
|
|
+ Long userId = AuthContextHolder.getUserId();
|
|
|
+ //1.初始化订单VO中价格、订单明细列表、订单减免明细列表
|
|
|
+ //1.1 声明三个初始价格:原价、减免金额、订单金额
|
|
|
BigDecimal originalAmount = new BigDecimal("0.00");
|
|
|
BigDecimal orderAmount = new BigDecimal("0.00");
|
|
|
BigDecimal derateAmount = new BigDecimal("0.00");
|
|
|
-
|
|
|
- //1.2. 初始化商品及优惠列表
|
|
|
+ //1.2 声明封装订单明细集合
|
|
|
List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
|
|
|
+ //1.3 声明封装订单减免明细集合
|
|
|
List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
|
|
|
|
|
|
- //付款项目类型: 1001-专辑 1002-声音 1003-vip会员
|
|
|
+ //获取购买项目类型 1001-专辑 1002-声音 1003-vip会员
|
|
|
String itemType = tradeVo.getItemType();
|
|
|
- //2.处理购买商品类型为:VIP套餐
|
|
|
+ //2.处理购买项目类型:VIP套餐
|
|
|
if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(itemType)) {
|
|
|
- //2.1 远程调用“用户”服务获取套餐信息
|
|
|
+ //2.1 远程调用用户服务,得到购买VIP会员套餐信息
|
|
|
VipServiceConfig vipServiceConfig = userFeignClient.getVipServiceConfig(tradeVo.getItemId()).getData();
|
|
|
- Assert.notNull(vipServiceConfig, "选择套餐:{}有误", tradeVo.getItemId());
|
|
|
- //2.2 封装价格:原价 减免价 定价价
|
|
|
+ Assert.notNull(vipServiceConfig, "会员套餐{}不存在", tradeVo.getItemId());
|
|
|
+ //2.2 计算商品价格:订单价=原价-减免金额
|
|
|
originalAmount = vipServiceConfig.getPrice();
|
|
|
orderAmount = vipServiceConfig.getDiscountPrice();
|
|
|
- if (orderAmount.compareTo(originalAmount) != 0) {
|
|
|
- //减免价格=原价-订单价
|
|
|
+ if (originalAmount.compareTo(orderAmount) == 1) {
|
|
|
derateAmount = originalAmount.subtract(orderAmount);
|
|
|
}
|
|
|
- //2.3 封装订单中商品明细列表
|
|
|
+ //2.3 将得到VIP套餐作为订单明细,封装成订单明细VO对象,加入到订单明细列表
|
|
|
OrderDetailVo orderDetailVo = new OrderDetailVo();
|
|
|
- orderDetailVo.setItemId(tradeVo.getItemId());
|
|
|
- orderDetailVo.setItemName("会员:" + vipServiceConfig.getName());
|
|
|
- orderDetailVo.setItemPrice(vipServiceConfig.getPrice());
|
|
|
+ orderDetailVo.setItemId(vipServiceConfig.getId());
|
|
|
+ orderDetailVo.setItemName("会员套餐:" + vipServiceConfig.getName());
|
|
|
orderDetailVo.setItemUrl(vipServiceConfig.getImageUrl());
|
|
|
+ orderDetailVo.setItemPrice(originalAmount);
|
|
|
orderDetailVoList.add(orderDetailVo);
|
|
|
- //2.4 封装商品优惠列表
|
|
|
- if (orderAmount.compareTo(originalAmount) != 0) {
|
|
|
+
|
|
|
+ //2.4 如有优惠金额,封装订单减免vo对象,加入到订单减免列表
|
|
|
+ if (originalAmount.compareTo(orderAmount) == 1) {
|
|
|
OrderDerateVo orderDerateVo = new OrderDerateVo();
|
|
|
orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_VIP_SERVICE_DISCOUNT);
|
|
|
orderDerateVo.setDerateAmount(derateAmount);
|
|
|
- orderDerateVo.setRemarks("会员限时优惠:" + derateAmount);
|
|
|
+ orderDerateVo.setRemarks("套餐限时减免:" + derateAmount);
|
|
|
orderDerateVoList.add(orderDerateVo);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
} else if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(itemType)) {
|
|
|
//3.TODO 处理购买商品类型为:专辑
|
|
|
|
|
@@ -435,29 +432,38 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
|
|
//4.TODO 处理购买商品类型为:声音
|
|
|
|
|
|
}
|
|
|
- //5.封装共有订单VO信息:价格、商品及优惠 TODO 、杂项信息(购买项目类型、流水号、时间戳签名)
|
|
|
+ //5.封装订单VO信息共有的信息,价格赋值、商品明细列表赋值、订单减免明细列表赋值、流水号机制、签名机制
|
|
|
+ //5.1 封装第一类信息:三个价格(原价、订单价、减免价)
|
|
|
orderInfoVo.setOriginalAmount(originalAmount);
|
|
|
orderInfoVo.setOrderAmount(orderAmount);
|
|
|
orderInfoVo.setDerateAmount(derateAmount);
|
|
|
+
|
|
|
+ //5.2 封装第二类信息:商品明细列表、优惠列表
|
|
|
orderInfoVo.setOrderDetailVoList(orderDetailVoList);
|
|
|
orderInfoVo.setOrderDerateVoList(orderDerateVoList);
|
|
|
- orderInfoVo.setItemType(itemType);
|
|
|
|
|
|
- //5.1 为本次订单产生唯一流水号且存入Redis,将来在提交订单验证流水号
|
|
|
- String tradeNo = IdUtil.randomUUID();
|
|
|
+ //5.3 封装第三类信息:购买项目类型、流水号机制(本次订单流水号)、签名机制(时间戳+签名值)
|
|
|
+ //5.3.1 购买项目类型
|
|
|
+ orderInfoVo.setItemType(itemType);
|
|
|
+ //5.3.2 流水号机制第一步:生成本次订单流水号,解决回退、重复点击提交造成订单重复提交问题
|
|
|
+ //5.3.2.1. 构建当前用户本次订单流水号Key
|
|
|
String tradeKey = RedisConstant.ORDER_TRADE_NO_PREFIX + userId;
|
|
|
- redisTemplate.opsForValue().set(tradeKey, tradeNo, RedisConstant.ORDER_TRADE_EXPIRE, TimeUnit.MINUTES);
|
|
|
+ //5.3.2.2. 构建当前用户本次订单流水号UUID值
|
|
|
+ String tradeNo = IdUtil.randomUUID();
|
|
|
+ //5.3.2.3. 写入Redis有效时间5分钟
|
|
|
+ redisTemplate.opsForValue().set(tradeKey, tradeNo, 5, TimeUnit.MINUTES);
|
|
|
orderInfoVo.setTradeNo(tradeNo);
|
|
|
|
|
|
- //5.2 生成时间戳及订单签名
|
|
|
- orderInfoVo.setTimestamp(System.currentTimeMillis());
|
|
|
- //5.2.1 将订单VO转为Map TODO:将付款方式payWay空值属性排除掉 不需要参与签名计算
|
|
|
+ //5.3.3 签名机制
|
|
|
+ //5.3.3.1. 生成本次订单时间戳
|
|
|
+ long timeMillis = System.currentTimeMillis();
|
|
|
+ orderInfoVo.setTimestamp(timeMillis);
|
|
|
+ //5.3.3.2 将订单VO转为Map,生成本次订单签名值 TODO 由于付款方式属性payWay为null不需要参与签名
|
|
|
Map<String, Object> orderInfoMap = BeanUtil.beanToMap(orderInfoVo, false, true);
|
|
|
- //5.2.2 调用工具类生成签名值
|
|
|
String sign = SignHelper.getSign(orderInfoMap);
|
|
|
+ //5.3.3.3. 封装Vo中签名值
|
|
|
orderInfoVo.setSign(sign);
|
|
|
-
|
|
|
- //6.响应订单VO对象
|
|
|
+ //6.响应订单vo,客户端完成订单页面渲染
|
|
|
return orderInfoVo;
|
|
|
}
|
|
|
}
|
|
@@ -511,16 +517,18 @@ public class FeignInterceptor implements RequestInterceptor {
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 查询当前用户是否购买指定专辑
|
|
|
+ * 判断当前用户是否购买过指定专辑
|
|
|
+ *
|
|
|
* @param albumId
|
|
|
- * @return true:已购买 false:未购买
|
|
|
+ * @return
|
|
|
*/
|
|
|
@GuiGuLogin
|
|
|
-@Operation(summary = "查询当前用户是否购买指定专辑")
|
|
|
+@Operation(summary = "判断当前用户是否购买过指定专辑")
|
|
|
@GetMapping("/userInfo/isPaidAlbum/{albumId}")
|
|
|
-public Result<Boolean> isPaidAlbum(@PathVariable Long albumId){
|
|
|
- Boolean isPaid = userInfoService.isPaidAlbum(albumId);
|
|
|
- return Result.ok(isPaid);
|
|
|
+public Result<Boolean> isPaidAlbum(@PathVariable Long albumId) {
|
|
|
+ Long userId = AuthContextHolder.getUserId();
|
|
|
+ Boolean isPaidAlbum = userInfoService.isPaidAlbum(userId, albumId);
|
|
|
+ return Result.ok(isPaidAlbum);
|
|
|
}
|
|
|
```
|
|
|
|
|
@@ -539,18 +547,19 @@ Boolean isPaidAlbum(Long albumId);
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 查询当前用户是否购买指定专辑
|
|
|
+ * 判断当前用户是否购买过指定专辑
|
|
|
*
|
|
|
* @param albumId
|
|
|
* @return
|
|
|
*/
|
|
|
@Override
|
|
|
-public Boolean isPaidAlbum(Long albumId) {
|
|
|
- Long userId = AuthContextHolder.getUserId();
|
|
|
- LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
- queryWrapper.eq(UserPaidAlbum::getUserId, userId);
|
|
|
- queryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
|
|
|
- return userPaidAlbumMapper.selectCount(queryWrapper) > 0;
|
|
|
+public Boolean isPaidAlbum(Long userId, Long albumId) {
|
|
|
+ Long count = userPaidAlbumMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<UserPaidAlbum>()
|
|
|
+ .eq(UserPaidAlbum::getUserId, userId)
|
|
|
+ .eq(UserPaidAlbum::getAlbumId, albumId)
|
|
|
+ );
|
|
|
+ return count > 0;
|
|
|
}
|
|
|
```
|
|
|
|
|
@@ -558,9 +567,10 @@ public Boolean isPaidAlbum(Long albumId) {
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 查询当前用户是否购买指定专辑
|
|
|
+ * 判断当前用户是否购买过指定专辑
|
|
|
+ *
|
|
|
* @param albumId
|
|
|
- * @return true:已购买 false:未购买
|
|
|
+ * @return
|
|
|
*/
|
|
|
@GetMapping("/userInfo/isPaidAlbum/{albumId}")
|
|
|
public Result<Boolean> isPaidAlbum(@PathVariable Long albumId);
|
|
@@ -593,57 +603,58 @@ public Result<Boolean> isPaidAlbum(Long albumId) {
|
|
|
*/
|
|
|
@Override
|
|
|
public OrderInfoVo tradeData(Long userId, TradeVo tradeVo) {
|
|
|
- //1.初始化OrderInfoVo
|
|
|
+ //0.创建订单VO对象
|
|
|
OrderInfoVo orderInfoVo = new OrderInfoVo();
|
|
|
- //1.1. 初始化相关金额:0.00 此时金额必须是字符串"0.00"
|
|
|
- BigDecimal originalAmount = new BigDecimal("0.00");
|
|
|
- BigDecimal orderAmount = new BigDecimal("0.00");
|
|
|
- BigDecimal derateAmount = new BigDecimal("0.00");
|
|
|
+ //...省略已写代码
|
|
|
|
|
|
- //1.2. 初始化商品及优惠列表
|
|
|
- List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
|
|
|
- List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
|
|
|
-
|
|
|
- //付款项目类型: 1001-专辑 1002-声音 1003-vip会员
|
|
|
+ //获取购买项目类型 1001-专辑 1002-声音 1003-vip会员
|
|
|
String itemType = tradeVo.getItemType();
|
|
|
+
|
|
|
//2.处理购买商品类型为:VIP套餐
|
|
|
if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(itemType)) {
|
|
|
//2.1...省略代码
|
|
|
|
|
|
} else if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(itemType)) {
|
|
|
- //3. 处理购买商品类型为:专辑
|
|
|
- //3.1 远程调用“用户”服务是否已购专辑
|
|
|
+ //3. 处理购买项目类型:专辑
|
|
|
+ //3.1 远程调用用户服务,判断用户是否已购买过专辑,如果已买则响应已购买
|
|
|
Long albumId = tradeVo.getItemId();
|
|
|
- Boolean isPaid = userFeignClient.isPaidAlbum(albumId).getData();
|
|
|
- if (isPaid) {
|
|
|
- throw new RuntimeException("用户已购买专辑:" + albumId);
|
|
|
+ Boolean flag = userFeignClient.isPaidAlbum(albumId).getData();
|
|
|
+ if (flag) {
|
|
|
+ throw new GuiguException(500, "用户已购买专辑");
|
|
|
}
|
|
|
- //3.2 远程调用"专辑"服务获取专辑信息
|
|
|
+
|
|
|
+ //3.2 远程调用专辑服务,获取专辑价格以及相关折扣(普通、VIP折扣)
|
|
|
AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();
|
|
|
- Assert.notNull(albumInfo, "专辑:{}不存在", albumId);
|
|
|
+ Assert.notNull(albumInfo, "专辑{}不存在", albumId);
|
|
|
+ BigDecimal price = albumInfo.getPrice();
|
|
|
+ BigDecimal discount = albumInfo.getDiscount();
|
|
|
+ BigDecimal vipDiscount = albumInfo.getVipDiscount();
|
|
|
|
|
|
- //3.3 远程调用用户服务获取用户身份,封装"商品"相关价格
|
|
|
- UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
|
|
|
+ //3.3 远程调用用户服务,判断当前用户是否是会员
|
|
|
Boolean isVIP = false;
|
|
|
- if (1 == userInfoVo.getIsVip().intValue() && userInfoVo.getVipExpireTime().after(new Date())) {
|
|
|
+
|
|
|
+ UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
|
|
|
+ Assert.notNull(userInfoVo, "用户{}不存在", userId);
|
|
|
+ if (userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().after(new Date())) {
|
|
|
isVIP = true;
|
|
|
}
|
|
|
- originalAmount = albumInfo.getPrice();
|
|
|
- orderAmount = originalAmount;
|
|
|
- //减免价=原价*折扣
|
|
|
- if (!isVIP && albumInfo.getDiscount().intValue() != -1) {
|
|
|
- //普通用户 且 专辑有普通用户折扣
|
|
|
- orderAmount = originalAmount.multiply(albumInfo.getDiscount()).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
|
|
|
- if (isVIP && albumInfo.getVipDiscount().intValue() != -1) {
|
|
|
- //VIP用户 且 专辑有VIP用户折扣
|
|
|
- orderAmount = originalAmount.multiply(albumInfo.getVipDiscount()).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
|
|
|
+ //3.4 基于用户角色专辑折扣计算专辑价格(原价、订单价、减免价格)
|
|
|
+ originalAmount = price;
|
|
|
+ orderAmount = originalAmount;
|
|
|
+ if (!isVIP && discount.doubleValue() != -1) {
|
|
|
+ //专辑价格 普通用户折扣 订单价格=原价*折扣
|
|
|
+ orderAmount =
|
|
|
+ originalAmount.multiply(discount).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
- if (orderAmount.compareTo(originalAmount) != 0) {
|
|
|
- derateAmount = originalAmount.subtract(orderAmount);
|
|
|
+ if (isVIP && vipDiscount.doubleValue() != -1) {
|
|
|
+ //专辑价格 VIP会员折扣 订单价格=原价*折扣
|
|
|
+ orderAmount =
|
|
|
+ originalAmount.multiply(vipDiscount).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
- //3.4 封装"商品"列表及商品优惠列表
|
|
|
+ //计算专辑价格减免金额 = 原价-订单价格
|
|
|
+ derateAmount = originalAmount.subtract(orderAmount);
|
|
|
+ //3.5 将专辑信息作为订单明细,封装成订单明细VO对象,加入到订单明细列表
|
|
|
OrderDetailVo orderDetailVo = new OrderDetailVo();
|
|
|
orderDetailVo.setItemId(albumId);
|
|
|
orderDetailVo.setItemName("专辑:" + albumInfo.getAlbumTitle());
|
|
@@ -651,40 +662,19 @@ public OrderInfoVo tradeData(Long userId, TradeVo tradeVo) {
|
|
|
orderDetailVo.setItemPrice(originalAmount);
|
|
|
orderDetailVoList.add(orderDetailVo);
|
|
|
|
|
|
- if (orderAmount.compareTo(originalAmount) != 0) {
|
|
|
+ //3.6 如有优惠金额,封装订单减免vo对象,加入到订单减免列表
|
|
|
+ if (originalAmount.compareTo(orderAmount) == 1) {
|
|
|
OrderDerateVo orderDerateVo = new OrderDerateVo();
|
|
|
orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_ALBUM_DISCOUNT);
|
|
|
orderDerateVo.setDerateAmount(derateAmount);
|
|
|
- orderDerateVo.setRemarks("专辑限时优惠:" + derateAmount);
|
|
|
+ orderDerateVo.setRemarks("专辑折扣减免:" + derateAmount);
|
|
|
orderDerateVoList.add(orderDerateVo);
|
|
|
}
|
|
|
} else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(itemType)) {
|
|
|
//4.TODO 处理购买商品类型为:声音
|
|
|
|
|
|
}
|
|
|
- //5.封装共有订单VO信息:价格、商品及优惠 TODO 、杂项信息(购买项目类型、流水号、时间戳签名)
|
|
|
- orderInfoVo.setOriginalAmount(originalAmount);
|
|
|
- orderInfoVo.setOrderAmount(orderAmount);
|
|
|
- orderInfoVo.setDerateAmount(derateAmount);
|
|
|
- orderInfoVo.setOrderDetailVoList(orderDetailVoList);
|
|
|
- orderInfoVo.setOrderDerateVoList(orderDerateVoList);
|
|
|
- orderInfoVo.setItemType(itemType);
|
|
|
-
|
|
|
- //5.1 为本次订单产生唯一流水号且存入Redis,将来在提交订单验证流水号
|
|
|
- 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.2 生成时间戳及订单签名
|
|
|
- orderInfoVo.setTimestamp(System.currentTimeMillis());
|
|
|
- //5.2.1 将订单VO转为Map TODO:将付款方式payWay空值属性排除掉 不需要参与签名计算
|
|
|
- Map<String, Object> orderInfoMap = BeanUtil.beanToMap(orderInfoVo, false, true);
|
|
|
- //5.2.2 调用工具类生成签名值
|
|
|
- String sign = SignHelper.getSign(orderInfoMap);
|
|
|
- orderInfoVo.setSign(sign);
|
|
|
-
|
|
|
- //6.响应订单VO对象
|
|
|
+ //5.省略已写代码
|
|
|
return orderInfoVo;
|
|
|
}
|
|
|
```
|
|
@@ -706,18 +696,16 @@ public OrderInfoVo tradeData(Long userId, TradeVo tradeVo) {
|
|
|
```java
|
|
|
/**
|
|
|
* 查询当前用户某个专辑下已购声音ID列表
|
|
|
- * @param albumId 专辑ID
|
|
|
- * @return 已购声音ID列表
|
|
|
+ * @param albumId
|
|
|
+ * @return
|
|
|
*/
|
|
|
@GuiGuLogin
|
|
|
@Operation(summary = "查询当前用户某个专辑下已购声音ID列表")
|
|
|
@GetMapping("/userInfo/findUserPaidTrackList/{albumId}")
|
|
|
-public Result<List<Long>> getUserPaidTrackIdList(@PathVariable Long albumId){
|
|
|
- //1.获取当前登录用户ID
|
|
|
+public Result<List<Long>> findUserPaidTrackList(@PathVariable Long albumId) {
|
|
|
Long userId = AuthContextHolder.getUserId();
|
|
|
- //2.调用业务逻辑获取已购声音ID列表
|
|
|
- List<Long> trackIdList = userInfoService.getUserPaidTrackIdList(userId, albumId);
|
|
|
- return Result.ok(trackIdList);
|
|
|
+ List<Long> list = userInfoService.findUserPaidTrackList(userId, albumId);
|
|
|
+ return Result.ok(list);
|
|
|
}
|
|
|
```
|
|
|
|
|
@@ -726,10 +714,10 @@ public Result<List<Long>> getUserPaidTrackIdList(@PathVariable Long albumId){
|
|
|
```java
|
|
|
/**
|
|
|
* 查询当前用户某个专辑下已购声音ID列表
|
|
|
- * @param albumId 专辑ID
|
|
|
- * @return 已购声音ID列表
|
|
|
+ * @param albumId
|
|
|
+ * @return
|
|
|
*/
|
|
|
-List<Long> getUserPaidTrackIdList(Long userId, Long albumId);
|
|
|
+List<Long> findUserPaidTrackList(Long userId, Long albumId);
|
|
|
```
|
|
|
|
|
|
##### **UserInfoServiceImpl**实现类
|
|
@@ -737,19 +725,23 @@ List<Long> getUserPaidTrackIdList(Long userId, Long albumId);
|
|
|
```java
|
|
|
/**
|
|
|
* 查询当前用户某个专辑下已购声音ID列表
|
|
|
- * @param albumId 专辑ID
|
|
|
- * @return 已购声音ID列表
|
|
|
+ *
|
|
|
+ * @param albumId
|
|
|
+ * @return
|
|
|
*/
|
|
|
@Override
|
|
|
-public List<Long> getUserPaidTrackIdList(Long userId, Long albumId) {
|
|
|
- LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
- queryWrapper.eq(UserPaidTrack::getUserId, userId);
|
|
|
- queryWrapper.eq(UserPaidTrack::getAlbumId, albumId);
|
|
|
- //只需要获取已购声音ID
|
|
|
- queryWrapper.select(UserPaidTrack::getTrackId);
|
|
|
- List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(queryWrapper);
|
|
|
- if(CollectionUtil.isNotEmpty(userPaidTrackList)){
|
|
|
- return userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
|
|
|
+public List<Long> findUserPaidTrackList(Long userId, Long albumId) {
|
|
|
+ List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<UserPaidTrack>()
|
|
|
+ .eq(UserPaidTrack::getUserId, userId)
|
|
|
+ .eq(UserPaidTrack::getAlbumId, albumId)
|
|
|
+ .select(UserPaidTrack::getTrackId)
|
|
|
+ );
|
|
|
+ if (CollUtil.isNotEmpty(userPaidTrackList)) {
|
|
|
+ List<Long> userPaidTrackIdList = userPaidTrackList.stream()
|
|
|
+ .map(UserPaidTrack::getTrackId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ return userPaidTrackIdList;
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
@@ -760,19 +752,19 @@ public List<Long> getUserPaidTrackIdList(Long userId, Long albumId) {
|
|
|
```java
|
|
|
/**
|
|
|
* 查询当前用户某个专辑下已购声音ID列表
|
|
|
- * @param albumId 专辑ID
|
|
|
- * @return 已购声音ID列表
|
|
|
+ * @param albumId
|
|
|
+ * @return
|
|
|
*/
|
|
|
@GetMapping("/userInfo/findUserPaidTrackList/{albumId}")
|
|
|
-public Result<List<Long>> getUserPaidTrackIdList(@PathVariable Long albumId);
|
|
|
+public Result<List<Long>> findUserPaidTrackList(@PathVariable Long albumId);
|
|
|
```
|
|
|
|
|
|
**UserDegradeFeignClient**熔断类
|
|
|
|
|
|
```java
|
|
|
@Override
|
|
|
-public Result<List<Long>> getUserPaidTrackIdList(Long albumId) {
|
|
|
- log.error("[用户服务]远程调用getuserPaidTrackIdList执行服务降级");
|
|
|
+public Result<List<Long>> findUserPaidTrackList(Long albumId) {
|
|
|
+ log.error("[用户服务]远程调用findUserPaidTrackList执行服务降级");
|
|
|
return null;
|
|
|
}
|
|
|
```
|
|
@@ -820,12 +812,12 @@ public Result<List<Map<String, Object>>> getUserTrackPaidList(@PathVariable Long
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 基于当前选择购买起始声音得到分集购买列表
|
|
|
+ * 基于当前用户未购买声音数量动态渲染分集购买列表
|
|
|
* @param userId 用户ID
|
|
|
- * @param trackId 选择购买声音ID(起始计算参照)
|
|
|
+ * @param trackId 选择购买声音ID,作为起始标准计算未购买声音数量
|
|
|
* @return
|
|
|
*/
|
|
|
-List<Map<String, Object>> getUserTrackPaidList(Long userId, Long trackId);
|
|
|
+List<Map<String, Object>> findUserTrackPaidList(Long userId, Long trackId);
|
|
|
```
|
|
|
|
|
|
##### AlbumInfoServiceImpl实现类
|
|
@@ -841,61 +833,58 @@ List<Map<String, Object>> getUserTrackPaidList(Long userId, Long trackId);
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 基于当前选择购买起始声音得到分集购买列表
|
|
|
+ * 基于当前用户未购买声音数量动态渲染分集购买列表
|
|
|
*
|
|
|
* @param userId 用户ID
|
|
|
- * @param trackId 选择购买声音ID(起始计算参照)
|
|
|
- * @return [{name:"本集",price:1,trackCount:1}]
|
|
|
+ * @param trackId 选择购买声音ID,作为起始标准计算未购买声音数量
|
|
|
+ * @return [{name:"本集",price:0.1,trackCount:1},{name:"后10集",price:1,trackCount:10}..,{name:"全集",price:3.8,trackCount:38}]
|
|
|
*/
|
|
|
@Override
|
|
|
-public List<Map<String, Object>> getUserTrackPaidList(Long userId, Long trackId) {
|
|
|
- //1.创建分集购买列表
|
|
|
- List<Map<String, Object>> list = new ArrayList<>();
|
|
|
-
|
|
|
- //2.根据声音ID查询到“起始”待购声音记录,得到当前声音徐浩、所属专辑ID
|
|
|
+public List<Map<String, Object>> findUserTrackPaidList(Long userId, Long trackId) {
|
|
|
+ //1.根据选择购买声音ID查询声音记录,得到声音序号,得到专辑ID
|
|
|
TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
|
|
|
Integer orderNum = trackInfo.getOrderNum();
|
|
|
Long albumId = trackInfo.getAlbumId();
|
|
|
-
|
|
|
- //3.根据"起始"声音序号获取所有待购买声音列表(可能包含用户已购声音)
|
|
|
- LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
- queryWrapper.eq(TrackInfo::getAlbumId, albumId);
|
|
|
- queryWrapper.ge(TrackInfo::getOrderNum, orderNum);
|
|
|
- queryWrapper.select(TrackInfo::getId);
|
|
|
- List<TrackInfo> trackInfoList = trackInfoMapper.selectList(queryWrapper);
|
|
|
-
|
|
|
- //4.远程调用"用户服务"获取已购买声音ID列表
|
|
|
- List<Long> userPaidTrackIdList = userFeignClient.getUserPaidTrackIdList(albumId).getData();
|
|
|
-
|
|
|
- //5.如果存在已购声音ID,将已购声音ID排除掉得到真正未购买声音列表
|
|
|
- if (CollectionUtil.isNotEmpty(userPaidTrackIdList)) {
|
|
|
- trackInfoList = trackInfoList.stream()
|
|
|
- .filter(track -> !userPaidTrackIdList.contains(track.getId())).collect(Collectors.toList());
|
|
|
+ //2.根据"起始声音"需要+专辑ID查询声音表得到“未购买声音列表”,这里可能包含已购买声音
|
|
|
+ List<TrackInfo> waitBuyTrackList = trackInfoMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<TrackInfo>()
|
|
|
+ .eq(TrackInfo::getAlbumId, albumId)
|
|
|
+ .ge(TrackInfo::getOrderNum, orderNum)
|
|
|
+ .select(TrackInfo::getId)
|
|
|
+ );
|
|
|
+
|
|
|
+ //3.远程调用用户服务,得到用户已购声音ID列表,如果有值将已购买声音ID排除掉
|
|
|
+ List<Long> userPaidTrackIdList = userFeignClient.findUserPaidTrackList(albumId).getData();
|
|
|
+ if (CollUtil.isNotEmpty(userPaidTrackIdList)) {
|
|
|
+ waitBuyTrackList =
|
|
|
+ waitBuyTrackList.stream()
|
|
|
+ .filter(t -> !userPaidTrackIdList.contains(t.getId()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
- //6.根据未购买声音列表长度动态构建分集购买列表
|
|
|
- //6.0 根据专辑ID查询专辑价格=声音价格
|
|
|
- BigDecimal price = albumInfoMapper.selectById(albumId).getPrice();
|
|
|
- //6.1 构建"本集"分集购买对象
|
|
|
+ //4.基于未购买声音数量,动态封装分集购买列表
|
|
|
+ int size = waitBuyTrackList.size();
|
|
|
+ List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
|
|
|
+ //4.0 查询专辑记录得到单集价格
|
|
|
+ AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
|
|
|
+ BigDecimal price = albumInfo.getPrice();
|
|
|
+ ///4.1 创建"本集"分集购买对象
|
|
|
Map<String, Object> currMap = new HashMap<>();
|
|
|
currMap.put("name", "本集");
|
|
|
currMap.put("price", price);
|
|
|
currMap.put("trackCount", 1);
|
|
|
list.add(currMap);
|
|
|
- //6.2 根据未购买声音数量循环最多构建6个分集购买对象(50集)
|
|
|
- int size = trackInfoList.size();
|
|
|
- //例如:size=12 展示 后10集,全集 size=35 展示 后10集 后20集 后30集 全集
|
|
|
- for (int i = 10; i <= 50; i += 10) {
|
|
|
- if (size > i) {
|
|
|
- Map<String, Object> map = new HashMap<>();
|
|
|
+ //4.2 创建"后i*10集"分集购买对象
|
|
|
+ for (int i = 10; i < 50; i += 10) {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ if (i < size) {
|
|
|
map.put("name", "后" + i + "集");
|
|
|
- map.put("price", price.multiply(BigDecimal.valueOf(i)));
|
|
|
+ map.put("price", price.multiply(new BigDecimal(i)));
|
|
|
map.put("trackCount", i);
|
|
|
list.add(map);
|
|
|
} else {
|
|
|
- Map<String, Object> map = new HashMap<>();
|
|
|
- map.put("name", "全集(" + size + "集)");
|
|
|
- map.put("price", price.multiply(BigDecimal.valueOf(size)));
|
|
|
+ map.put("name", "全集(后" + size + "集)");
|
|
|
+ map.put("price", price.multiply(new BigDecimal(size)));
|
|
|
map.put("trackCount", size);
|
|
|
list.add(map);
|
|
|
break;
|
|
@@ -915,20 +904,17 @@ public List<Map<String, Object>> getUserTrackPaidList(Long userId, Long trackId)
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 查询当前用户未购买声音列表
|
|
|
- *
|
|
|
- * @param trackId 点击付费标识声音ID,将该声音作为起始标准
|
|
|
- * @param trackCount 购买数量
|
|
|
- * @return 待购声音列表
|
|
|
+ * 查询用户未购买声音列表
|
|
|
+ * @param trackId 选择购买声音ID,作为起始标准计算未购买声音数量
|
|
|
+ * @param trackCount 限制查询未购买声音数量
|
|
|
+ * @return
|
|
|
*/
|
|
|
@GuiGuLogin
|
|
|
-@Operation(summary = "查询当前用户未购买声音列表")
|
|
|
+@Operation(summary = "查询用户未购买声音列表")
|
|
|
@GetMapping("/trackInfo/findPaidTrackInfoList/{trackId}/{trackCount}")
|
|
|
-public Result<List<TrackInfo>> getWaitBuyTrackList(@PathVariable Long trackId, @PathVariable Integer trackCount) {
|
|
|
- //1.从ThreadLocal中获取当前登录用户ID
|
|
|
+public Result<List<TrackInfo>> findWaitBuyTrackInfoList(@PathVariable Long trackId, @PathVariable Integer trackCount) {
|
|
|
Long userId = AuthContextHolder.getUserId();
|
|
|
- //2.调用业务逻辑获取待购声音列表
|
|
|
- List<TrackInfo> list = albumInfoService.getWaitBuyTrackList(userId, trackId, trackCount);
|
|
|
+ List<TrackInfo> list = trackInfoService.findWaitBuyTrackInfoList(userId, trackId, trackCount);
|
|
|
return Result.ok(list);
|
|
|
}
|
|
|
```
|
|
@@ -937,13 +923,12 @@ public Result<List<TrackInfo>> getWaitBuyTrackList(@PathVariable Long trackId, @
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 查询当前用户未购买声音列表
|
|
|
- * @param userId 用户ID
|
|
|
- * @param trackId 点击付费标识声音ID,将该声音作为起始标准
|
|
|
- * @param trackCount 购买数量
|
|
|
- * @return 待购声音列表
|
|
|
+ * 查询用户未购买声音列表
|
|
|
+ * @param trackId 选择购买声音ID,作为起始标准计算未购买声音数量
|
|
|
+ * @param trackCount 限制查询未购买声音数量
|
|
|
+ * @return
|
|
|
*/
|
|
|
-List<TrackInfo> getWaitBuyTrackList(Long userId, Long trackId, Integer trackCount);
|
|
|
+List<TrackInfo> findWaitBuyTrackInfoList(Long userId, Long trackId, Integer trackCount);
|
|
|
```
|
|
|
|
|
|
#### 实现类
|
|
@@ -957,41 +942,34 @@ List<TrackInfo> getWaitBuyTrackList(Long userId, Long trackId, Integer trackCoun
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 查询当前用户未购买声音列表
|
|
|
+ * 查询用户未购买声音列表
|
|
|
*
|
|
|
- * @param userId 用户ID
|
|
|
- * @param trackId 点击付费标识声音ID,将该声音作为起始标准
|
|
|
- * @param trackCount 购买数量
|
|
|
- * @return 待购声音列表
|
|
|
+ * @param trackId 选择购买声音ID,作为起始标准计算未购买声音数量
|
|
|
+ * @param trackCount 限制查询未购买声音数量
|
|
|
+ * @return
|
|
|
*/
|
|
|
@Override
|
|
|
-public List<TrackInfo> getWaitBuyTrackList(Long userId, Long trackId, Integer trackCount) {
|
|
|
- //1.根据声音ID查询到“起始”待购声音记录,得到当前声音序号、所属专辑ID
|
|
|
+public List<TrackInfo> findWaitBuyTrackInfoList(Long userId, Long trackId, Integer trackCount) {
|
|
|
+ //1.根据声音ID查询到“起始”待购声音记录-得到专辑ID及序号
|
|
|
TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
|
|
|
Long albumId = trackInfo.getAlbumId();
|
|
|
Integer orderNum = trackInfo.getOrderNum();
|
|
|
|
|
|
//2.远程调用用户服务获取已购买声音ID列表
|
|
|
- List<Long> userPaidTrackIdList = userFeignClient.getUserPaidTrackIdList(albumId).getData();
|
|
|
-
|
|
|
- //3.获取待购声音列表 查询条件:专辑ID,序号,已购声音ID 。排序字段:序号 。返回数量:购买数量
|
|
|
- LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
- //3.1 等值查询专辑标题
|
|
|
- queryWrapper.eq(TrackInfo::getAlbumId, albumId);
|
|
|
- //3.2 大于等于当前选购声音序号
|
|
|
- queryWrapper.ge(TrackInfo::getOrderNum, orderNum);
|
|
|
- if (CollectionUtil.isNotEmpty(userPaidTrackIdList)) {
|
|
|
- //3.3 如果存在已购买声音,去除已购买声音ID
|
|
|
- queryWrapper.notIn(TrackInfo::getId, userPaidTrackIdList);
|
|
|
+ List<Long> userPaidTrackList = userFeignClient.findUserPaidTrackList(albumId).getData();
|
|
|
+
|
|
|
+ //3.构建查询条件查询未购买声音列表
|
|
|
+ LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<TrackInfo>()
|
|
|
+ .eq(TrackInfo::getAlbumId, albumId)
|
|
|
+ .ge(TrackInfo::getOrderNum, orderNum)
|
|
|
+ .orderByAsc(TrackInfo::getOrderNum)
|
|
|
+ .select(TrackInfo::getId, TrackInfo::getTrackTitle, TrackInfo::getCoverUrl, TrackInfo::getAlbumId)
|
|
|
+ .last("limit " + trackCount);
|
|
|
+ if (CollUtil.isNotEmpty(userPaidTrackList)) {
|
|
|
+ queryWrapper.notIn(TrackInfo::getId, userPaidTrackList);
|
|
|
}
|
|
|
- //3.4 按照声音序号升序
|
|
|
- queryWrapper.orderByAsc(TrackInfo::getOrderNum);
|
|
|
- //3.5 按用户选择购买数量获取声音列表
|
|
|
- queryWrapper.last("LIMIT " + trackCount);
|
|
|
- //3.6 执行查询列:多查询了专辑ID,需要在订单服务进行算价格需要获取专辑中价格
|
|
|
- queryWrapper.select(TrackInfo::getId, TrackInfo::getTrackTitle, TrackInfo::getCoverUrl, TrackInfo::getAlbumId);
|
|
|
- List<TrackInfo> list = trackInfoMapper.selectList(queryWrapper);
|
|
|
- return list;
|
|
|
+ List<TrackInfo> trackInfoList = trackInfoMapper.selectList(queryWrapper);
|
|
|
+ return trackInfoList;
|
|
|
}
|
|
|
```
|
|
|
|
|
@@ -999,22 +977,21 @@ public List<TrackInfo> getWaitBuyTrackList(Long userId, Long trackId, Integer tr
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 查询当前用户未购买声音列表
|
|
|
- *
|
|
|
- * @param trackId 点击付费标识声音ID,将该声音作为起始标准
|
|
|
- * @param trackCount 购买数量
|
|
|
- * @return 待购声音列表
|
|
|
+ * 查询用户未购买声音列表
|
|
|
+ * @param trackId 选择购买声音ID,作为起始标准计算未购买声音数量
|
|
|
+ * @param trackCount 限制查询未购买声音数量
|
|
|
+ * @return
|
|
|
*/
|
|
|
@GetMapping("/trackInfo/findPaidTrackInfoList/{trackId}/{trackCount}")
|
|
|
-public Result<List<TrackInfo>> getWaitBuyTrackList(@PathVariable Long trackId, @PathVariable Integer trackCount);
|
|
|
+public Result<List<TrackInfo>> findWaitBuyTrackInfoList(@PathVariable Long trackId, @PathVariable Integer trackCount);
|
|
|
```
|
|
|
|
|
|
熔断类:
|
|
|
|
|
|
```java
|
|
|
@Override
|
|
|
-public Result<List<TrackInfo>> getWaitBuyTrackList(Long trackId, Integer trackCount) {
|
|
|
- log.error("[专辑服务]远程调用getWaitBuyTrackList执行服务降级");
|
|
|
+public Result<List<TrackInfo>> findWaitBuyTrackInfoList(Long trackId, Integer trackCount) {
|
|
|
+ log.error("【专辑服务】提供findWaitBuyTrackInfoList远程调用失败");
|
|
|
return null;
|
|
|
}
|
|
|
```
|
|
@@ -1023,85 +1000,57 @@ public Result<List<TrackInfo>> getWaitBuyTrackList(Long trackId, Integer trackCo
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
- * 订单确认数据汇总
|
|
|
+ * 三种商品(VIP会员、专辑、声音)订单结算,渲染订单结算页面
|
|
|
*
|
|
|
- * @param userId 用户ID
|
|
|
- * @param tradeVo 选择购买商品交易vo对象
|
|
|
- * @return
|
|
|
+ * @param tradeVo (购买项目类型、购买项目ID、声音数量)
|
|
|
+ * @return 订单VO信息
|
|
|
*/
|
|
|
@Override
|
|
|
-public OrderInfoVo tradeData(Long userId, TradeVo tradeVo) {
|
|
|
- //1.初始化OrderInfoVo
|
|
|
- OrderInfoVo orderInfoVo = new OrderInfoVo();
|
|
|
- //1.1. 初始化相关金额:0.00 此时金额必须是字符串"0.00"
|
|
|
- BigDecimal originalAmount = new BigDecimal("0.00");
|
|
|
- BigDecimal orderAmount = new BigDecimal("0.00");
|
|
|
- BigDecimal derateAmount = new BigDecimal("0.00");
|
|
|
-
|
|
|
- //1.2. 初始化商品及优惠列表
|
|
|
- List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
|
|
|
- List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
|
|
|
-
|
|
|
- //付款项目类型: 1001-专辑 1002-声音 1003-vip会员
|
|
|
+public OrderInfoVo trade(TradeVo tradeVo) {
|
|
|
+ //0.创建订单VO对象
|
|
|
+ //...省略已有代码
|
|
|
+ //获取购买项目类型 1001-专辑 1002-声音 1003-vip会员
|
|
|
String itemType = tradeVo.getItemType();
|
|
|
- //2.处理购买商品类型为:VIP套餐
|
|
|
+ //2.处理购买项目类型:VIP套餐
|
|
|
if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(itemType)) {
|
|
|
- //2.1 ...省略
|
|
|
+ //...省略已有代码
|
|
|
} else if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(itemType)) {
|
|
|
- //3. 处理购买商品类型为:专辑 ...省略
|
|
|
+ //3. 处理购买项目类型:专辑
|
|
|
+ //...省略已有代码
|
|
|
} else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(itemType)) {
|
|
|
- //4.TODO 处理购买商品类型为:声音
|
|
|
- Long trackId = tradeVo.getItemId();
|
|
|
- Integer trackCount = tradeVo.getTrackCount();
|
|
|
- //4.1 远程调用"专辑服务"获取待购买声音列表
|
|
|
- List<TrackInfo> waitBuyTrackList = albumFeignClient.getWaitBuyTrackList(trackId, trackCount).getData();
|
|
|
- Assert.notNull(waitBuyTrackList, "不存在待结算声音");
|
|
|
+ //4.处理购买项目类型:声音
|
|
|
|
|
|
- //4.2 远程调用专辑服务得到专辑信息-得到声音单价
|
|
|
- Long albumId = waitBuyTrackList.get(0).getAlbumId();
|
|
|
- AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();
|
|
|
- Assert.notNull(albumInfo, "专辑:{}不存在", albumId);
|
|
|
+ //4.1 远程调用专辑服务获取待购买声音列表
|
|
|
+ Long trackId = tradeVo.getItemId();
|
|
|
+ List<TrackInfo> trackInfoList = albumFeignClient.findWaitBuyTrackInfoList(trackId, tradeVo.getTrackCount()).getData();
|
|
|
+ Assert.notNull(trackInfoList, "没有需要结算声音");
|
|
|
|
|
|
- //4.3 封装"商品"相关价格 声音单价*列表长度 注意:声音不支持折扣
|
|
|
+ //4.2 远程调用专辑服务获取声音单价-声音不支持折扣
|
|
|
+ AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(trackInfoList.get(0).getAlbumId()).getData();
|
|
|
+ Assert.notNull(albumInfo, "专辑{}不存在", trackInfoList.get(0).getAlbumId());
|
|
|
BigDecimal price = albumInfo.getPrice();
|
|
|
- originalAmount = price.multiply(BigDecimal.valueOf(waitBuyTrackList.size()));
|
|
|
+
|
|
|
+ //4.3 封装相关价格
|
|
|
+ originalAmount = price.multiply(new BigDecimal(trackInfoList.size()));
|
|
|
orderAmount = originalAmount;
|
|
|
|
|
|
- //4.4 封装"商品"列表 将集合泛型从TrackInfo转为OrderDetailVo
|
|
|
- orderDetailVoList = waitBuyTrackList
|
|
|
+ //4.4 将待购买声音作为订单明细,封装成订单明细VO对象,加入到订单明细列表
|
|
|
+ orderDetailVoList = trackInfoList
|
|
|
.stream()
|
|
|
.map(trackInfo -> {
|
|
|
OrderDetailVo orderDetailVo = new OrderDetailVo();
|
|
|
orderDetailVo.setItemId(trackInfo.getId());
|
|
|
- orderDetailVo.setItemName(trackInfo.getTrackTitle());
|
|
|
+ orderDetailVo.setItemName("声音:" + trackInfo.getTrackTitle());
|
|
|
orderDetailVo.setItemUrl(trackInfo.getCoverUrl());
|
|
|
orderDetailVo.setItemPrice(price);
|
|
|
return orderDetailVo;
|
|
|
}).collect(Collectors.toList());
|
|
|
+
|
|
|
}
|
|
|
- //5.封装共有订单VO信息:价格、商品及优惠 TODO 、杂项信息(购买项目类型、流水号、时间戳签名)
|
|
|
- orderInfoVo.setOriginalAmount(originalAmount);
|
|
|
- orderInfoVo.setOrderAmount(orderAmount);
|
|
|
- orderInfoVo.setDerateAmount(derateAmount);
|
|
|
- orderInfoVo.setOrderDetailVoList(orderDetailVoList);
|
|
|
- orderInfoVo.setOrderDerateVoList(orderDerateVoList);
|
|
|
- orderInfoVo.setItemType(itemType);
|
|
|
-
|
|
|
- //5.1 为本次订单产生唯一流水号且存入Redis,将来在提交订单验证流水号
|
|
|
- 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.2 生成时间戳及订单签名
|
|
|
- orderInfoVo.setTimestamp(System.currentTimeMillis());
|
|
|
- //5.2.1 将订单VO转为Map TODO:将付款方式payWay空值属性排除掉 不需要参与签名计算
|
|
|
- Map<String, Object> orderInfoMap = BeanUtil.beanToMap(orderInfoVo, false, true);
|
|
|
- //5.2.2 调用工具类生成签名值
|
|
|
- String sign = SignHelper.getSign(orderInfoMap);
|
|
|
- orderInfoVo.setSign(sign);
|
|
|
-
|
|
|
- //6.响应订单VO对象
|
|
|
+
|
|
|
+ //5.封装订单VO信息共有的信息,价格赋值、商品明细列表赋值、订单减免明细列表赋值、流水号机制、签名机制
|
|
|
+ //...省略已有代码
|
|
|
+ //6.响应订单vo,客户端完成订单页面渲染
|
|
|
return orderInfoVo;
|
|
|
}
|
|
|
```
|