diff --git a/xdclass-order-service/src/main/java/net/jieyuu/feign/CouponFeignService.java b/xdclass-order-service/src/main/java/net/jieyuu/feign/CouponFeignService.java index 769ac6b..965ed39 100644 --- a/xdclass-order-service/src/main/java/net/jieyuu/feign/CouponFeignService.java +++ b/xdclass-order-service/src/main/java/net/jieyuu/feign/CouponFeignService.java @@ -1,18 +1,31 @@ package net.jieyuu.feign; +import io.swagger.annotations.ApiParam; +import net.jieyuu.request.LockCouponRecordRequest; import net.jieyuu.utils.JsonData; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; @FeignClient(name = "xdclass-coupon-service") public interface CouponFeignService { /** * 查询用户的优惠券是否可用,注意防止水平越权 + * * @param recordId * @return */ @GetMapping("/api/coupon_record/v1/detail/{record_id}") JsonData findUserCouponRecordById(@PathVariable("record_id") long recordId); + /** + * 锁定优惠券 + * + * @param lockCouponRecordRequest + * @return + */ + @PostMapping("/api/coupon_record/v1/lock_records") + JsonData lockCouponRecords(@ApiParam("锁定优惠券请求对象") @RequestBody LockCouponRecordRequest lockCouponRecordRequest); } diff --git a/xdclass-order-service/src/main/java/net/jieyuu/feign/ProductFeignService.java b/xdclass-order-service/src/main/java/net/jieyuu/feign/ProductFeignService.java index a15cb72..9f1a823 100644 --- a/xdclass-order-service/src/main/java/net/jieyuu/feign/ProductFeignService.java +++ b/xdclass-order-service/src/main/java/net/jieyuu/feign/ProductFeignService.java @@ -1,8 +1,12 @@ package net.jieyuu.feign; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import net.jieyuu.request.LockProductRequest; import net.jieyuu.utils.JsonData; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; @@ -19,4 +23,13 @@ public interface ProductFeignService { @PostMapping("/api/cart/v1/confirm_order_cart_items") public JsonData confirmOrderCartItems(@RequestBody List<Long> productIdList); + /** + * 锁定商品购物项库存 + * + * @param lockProductRequest + * @return + */ + @PostMapping("/api/product/v1/lock_products") + public JsonData lockProductStocks(@RequestBody LockProductRequest lockProductRequest); + } diff --git a/xdclass-order-service/src/main/java/net/jieyuu/request/LockCouponRecordRequest.java b/xdclass-order-service/src/main/java/net/jieyuu/request/LockCouponRecordRequest.java new file mode 100644 index 0000000..efbb580 --- /dev/null +++ b/xdclass-order-service/src/main/java/net/jieyuu/request/LockCouponRecordRequest.java @@ -0,0 +1,26 @@ +package net.jieyuu.request; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel(value = "优惠券锁定对象", description = "优惠券锁定对象") +@Data +public class LockCouponRecordRequest { + + /** + * 优惠券记录id列表 + */ + @ApiModelProperty(value = "优惠券锁定数组", example = "[1,2,3]") + private List<Long> lockCouponRecordIds; + + /** + * 订单号 + */ + @ApiModelProperty(value = "订单号", example = "32位uuid") + private String orderOutTradeNo; + +} diff --git a/xdclass-order-service/src/main/java/net/jieyuu/request/LockProductRequest.java b/xdclass-order-service/src/main/java/net/jieyuu/request/LockProductRequest.java new file mode 100644 index 0000000..cde9866 --- /dev/null +++ b/xdclass-order-service/src/main/java/net/jieyuu/request/LockProductRequest.java @@ -0,0 +1,24 @@ +package net.jieyuu.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.util.List; + +@ApiModel(value = "商品锁定对象", description = "商品锁定对象协议") +@Data +public class LockProductRequest { + + + @ApiModelProperty(value = "订单id", example = "1233332131231321") + @JsonProperty("order_out_trade_no") + private String orderOutTradeNo; + + @ApiModelProperty(value = "订单项") + @JsonProperty("order_item_list") + private List<OrderItemRequest> orderItemList; + + +} + diff --git a/xdclass-order-service/src/main/java/net/jieyuu/request/OrderItemRequest.java b/xdclass-order-service/src/main/java/net/jieyuu/request/OrderItemRequest.java new file mode 100644 index 0000000..f1e82fd --- /dev/null +++ b/xdclass-order-service/src/main/java/net/jieyuu/request/OrderItemRequest.java @@ -0,0 +1,20 @@ +package net.jieyuu.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("商品子项") +@Data +public class OrderItemRequest { + + @ApiModelProperty(value = "商品id",example = "1") + @JsonProperty("product_id") + private long productId; + + @ApiModelProperty(value = "购买数量",example = "1") + @JsonProperty("buy_num") + private int buyNum; + +} \ No newline at end of file diff --git a/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java b/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java index 1346cc2..5e848d6 100644 --- a/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java +++ b/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java @@ -15,6 +15,9 @@ import net.jieyuu.model.OrderItemVO; import net.jieyuu.model.ProductOrderDO; import net.jieyuu.mapper.ProductOrderMapper; import net.jieyuu.request.ConfirmOrderRequest; +import net.jieyuu.request.LockCouponRecordRequest; +import net.jieyuu.request.LockProductRequest; +import net.jieyuu.request.OrderItemRequest; import net.jieyuu.service.ProductOrderService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import net.jieyuu.utils.CommonUtil; @@ -25,7 +28,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * <p> @@ -89,10 +94,70 @@ public class ProductOrderServiceImpl extends ServiceImpl<ProductOrderMapper, Pro } // 验证价格 this.checkPrice(orderItemList, orderRequest); + // 锁定优惠券 + this.lockCouponRecords(orderRequest, orderOutTradeNo); + + // 锁定库存 + this.lockProductStocks(orderItemList, orderOutTradeNo); + + // 创建订单 todo + + //创建支付 todo return null; } + /** + * 锁定商品库存 + * + * @param orderItemList + * @param orderOutTradeNo + */ + private void lockProductStocks(List<OrderItemVO> orderItemList, String orderOutTradeNo) { + + List<OrderItemRequest> itemRequestLis = orderItemList.stream().map(obj -> { + OrderItemRequest request = new OrderItemRequest(); + request.setBuyNum(obj.getBuyNum()); + request.setProductId(obj.getProductId()); + return request; + }).collect(Collectors.toList()); + + LockProductRequest lockProductRequest = new LockProductRequest(); + lockProductRequest.setOrderItemList(itemRequestLis); + lockProductRequest.setOrderOutTradeNo(orderOutTradeNo); + + JsonData jsonData = productFeignService.lockProductStocks(lockProductRequest); + + if (jsonData.getCode() != 0) { + log.error("锁定商品库存失败:{}", lockProductRequest); + throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL); + } + } + + /** + * 锁定优惠券记录 + * 可以使用异步的方式 + * + * @param orderOutTradeNo + * @param orderRequest + */ + private void lockCouponRecords(ConfirmOrderRequest orderRequest, String orderOutTradeNo) { + List<Long> lockCouponRecordIds = new ArrayList<>(); + if (orderRequest.getCouponRecordId() > 0) { + lockCouponRecordIds.add(orderRequest.getCouponRecordId()); + + LockCouponRecordRequest lockCouponRecordRequest = new LockCouponRecordRequest(); + lockCouponRecordRequest.setLockCouponRecordIds(lockCouponRecordIds); + lockCouponRecordRequest.setOrderOutTradeNo(orderOutTradeNo); + // 发送优惠券请求 + JsonData jsonData = couponFeignService.lockCouponRecords(lockCouponRecordRequest); + if (jsonData.getCode() != 0) { + throw new BizException(BizCodeEnum.COUPON_RECORD_LOCK_FAIL); + } + } + + } + /** * 验证价格 * 1)统计所有商品价格 @@ -124,14 +189,14 @@ public class ProductOrderServiceImpl extends ServiceImpl<ProductOrderMapper, Pro if (couponRecordVO.getPrice().compareTo(realPayAmount) > 0) { // 防止出现优惠券抵扣超过商品价格 realPayAmount = BigDecimal.ZERO; - }else{ - realPayAmount= realPayAmount.subtract(couponRecordVO.getPrice()); + } else { + realPayAmount = realPayAmount.subtract(couponRecordVO.getPrice()); } } // 验价 - if(realPayAmount.compareTo(orderRequest.getTotalAmount())!=0){ - log.error("订单验价失败:{}" , orderRequest); + if (realPayAmount.compareTo(orderRequest.getTotalAmount()) != 0) { + log.error("订单验价失败:{}", orderRequest); throw new BizException(BizCodeEnum.ORDER_CONFIRM_PRICE_FAIL); } } diff --git a/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java b/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java index 9ac2d64..608b3dd 100644 --- a/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java +++ b/xdclass-product-service/src/main/java/net/jieyuu/controller/ProductController.java @@ -66,7 +66,7 @@ public class ProductController { * @return */ @ApiOperation("商品库存锁定") - @PutMapping("lock_products") + @PostMapping("lock_products") public JsonData lockProduct(@ApiParam("商品库存锁定") @RequestBody LockProductRequest lockProductRequest) { JsonData jsonData = productService.lockProductStock(lockProductRequest); return jsonData; diff --git a/xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java b/xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java index cde9866..5929ea5 100644 --- a/xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java +++ b/xdclass-product-service/src/main/java/net/jieyuu/request/LockProductRequest.java @@ -18,7 +18,5 @@ public class LockProductRequest { @ApiModelProperty(value = "订单项") @JsonProperty("order_item_list") private List<OrderItemRequest> orderItemList; - - }