赞
踩
@RestController
@Tag(name = "订单管理模块", description = "订单管理模块")
@RequestMapping("/api/order/orderInfo")
public class OrderController {
@Operation(summary = "提交订单")
@PostMapping("/auth/submitOrder")
public Result submitOrder(@RequestBody OrderSubmitDto orderSubmitDto) {
Long orderId = orderService.submitOrder(orderSubmitDto);
return Result.ok(orderId);
}
}
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService {
@Resource
private CartClient cartClient;
@Resource
private ProductClient productClient;
@Resource
private UserClient userClient;
@Resource
private OrderItemService orderItemService;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Transactional(rollbackFor = Exception.class)
@Override
public Long submitOrder(OrderSubmitDto orderSubmitDto) {
//1、幂等性保证:用户订单确认页提交的相同的请求只处理一次
//获取前端提交的token
List<OrderItem> orderItemList = orderSubmitDto.getOrderItemList();
if (CollectionUtils.isEmpty(orderItemList)) {
//没有订单项
throw new SpzxException(ResultCodeEnum.FAIL,null);
}
Long token = orderItemList.get(0).getOrderId();
//获取redis缓存的token,如果存在删除
Boolean delete = stringRedisTemplate.delete("spzx:order:" + token.toString());
if (!delete) {
//幂等性保证:用户订单确认页提交的相同的请求只处理一次
throw new SpzxException(ResultCodeEnum.ORDER_SUBMIT_REPEAT,null);
}
//2、保证订单中商品价格正确、库存足够
//远程调用:service-product 验证前端提交的每个orderItem的价格 和skuId对应的商品当前价格是否一样 和库存是否足够
orderItemList.forEach(orderItem -> {
Result<ProductSku> skuResult = productClient.getById(orderItem.getSkuId());
if (skuResult.getCode() != 200) {
throw new SpzxException(ResultCodeEnum.FAIL,null);
}
ProductSku sku = skuResult.getData();
if (sku.getSalePrice().compareTo(orderItem.getSkuPrice()) != 0) {
//价格不一致
throw new SpzxException(ResultCodeEnum.ORDER_ITEM_PRICE_ERROR,null);
}
if (sku.getStockNum() < orderItem.getSkuNum()) {
//库存不足
throw new SpzxException(ResultCodeEnum.ORDER_ITEM_STOCK_ERROR,null);
}
});
Result<UserAddress> userAddressResult = userClient.findUserAddressById(orderSubmitDto.getUserAddressId());
if (userAddressResult.getCode() != 200) {
//用户收件人地址信息查询失败
throw new SpzxException(ResultCodeEnum.FAIL,null);
}
//3、创建订单持久化
OrderInfo orderInfo = new OrderInfo();
UserInfo userInfo = SpzxServiceAuthInterceptor.THREAD_LOCAL.get();
orderInfo.setUserId(userInfo.getId());
orderInfo.setNickName(userInfo.getNickName());
//订单号:展示给用户的唯一订单编号
String orderNo = IdUtil.getSnowflake(1, 1).nextIdStr();
orderInfo.setOrderNo(orderNo);
orderInfo.setCouponId(0L);
//计算订单总金额,并返回总金额
BigDecimal totalAmount = orderItemList.stream().map(orderItem -> {
return orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum()));
}).reduce(BigDecimal::add).get();
orderInfo.setTotalAmount(totalAmount);
orderInfo.setCouponAmount(new BigDecimal("0"));
orderInfo.setOriginalTotalAmount(totalAmount);
orderInfo.setFreightFee(orderSubmitDto.getFreightFee());
//orderInfo.setPayType(0);
orderInfo.setOrderStatus(0);
//收件人信息
UserAddress userAddress = userAddressResult.getData();
orderInfo.setReceiverName(userAddress.getName());
orderInfo.setReceiverPhone(userAddress.getPhone());
orderInfo.setReceiverTagName(userAddress.getTagName());
orderInfo.setReceiverProvince(userAddress.getProvinceCode());
orderInfo.setReceiverCity(userAddress.getCityCode());
orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
orderInfo.setReceiverAddress(userAddress.getAddress());
orderInfo.setPaymentTime(new Date());
orderInfo.setDeliveryTime(new Date());
orderInfo.setReceiveTime(new Date());
orderInfo.setCancelTime(new Date());
orderInfo.setCancelReason("");
orderInfo.setRemark(orderSubmitDto.getRemark());
this.save(orderInfo);
Long orderId = orderInfo.getId();
//4、保存订单的所有的订单项列表
//订单项关联订单 id 保存
orderItemList.forEach(orderItem -> {
orderItem.setOrderId(orderId);
});
orderItemService.saveBatch(orderItemList);
//5、删除购物车中已创建订单的购物项
//远程调用:service-cart 删除当前用户选中的购物项
cartClient.delCheckedCartInfos();
//异步:购物车清空无需阻塞订单创建的业务 解耦合:订单创建业务不需要耦合购物车的操作
//order服务是生产者发送消息
//cart服务是消费者消费消息:根据userId获取他的购物车 再删除选中的购物项
//发送订单创建成功的消息到kafka中:购物车需要userId 如果还有其他的业务需要使用订单创建成功的消息,也可以携带其他的数据
//userId 幂等性校验使用订单id order信息
/*HashMap<String, Object> params = new HashMap<>();
params.put("userId",userInfo.getId());
params.put("orderId", orderId);
params.put("totalAmount", orderInfo.getTotalAmount());
params.put("type", "1");//type表示订单的类型 1、创建订单 2、取消订单 3、更新订单状态
//将对象转为json字符串
String json = JSON.toJSONString(params);
kafkaTemplate.send(SpzxConst.SPZX_ORDER_TOPIC, json);*/
/*Map<String,Object> params = new HashMap<String,Object>();
params.put("userId" , userInfo.getId());
params.put("orderId" , orderId);
params.put("totalAmount" , orderInfo.getTotalAmount());
params.put("type","1");//type表示订单操作的类型 1创建订单 2取消订单 3更新订单状态
//将对象转为json字符串
String paramsJson = JSON.toJSONString(params);
kafkaTemplate.send(SpzxConst.SPZX_ORDER_TOPIC ,paramsJson );*/
//6、返回订单id
return orderId;
}
}
@RestController
@Tag(name = "商品模块")
@RequestMapping(value = "/api/product")
public class ProductController {
@Operation(summary = "根据id查询sku商品详情")
@GetMapping("getById/{skuId}")
public Result getById(@PathVariable("skuId") Long skuId) {
ProductSku productSku = productSkuService.getById(skuId);
return Result.ok(productSku);
}
}
@FeignClient(value = "service-product")
public interface ProductClient {
//因为远程调用时data存的是 sku对象
@GetMapping("/api/product/getById/{skuId}")
public Result<ProductSku> getById(@PathVariable("skuId") Long skuId);
@PutMapping("/api/product/updateSkuSaleAndStock/{skuId}/{skuNum}")
public Result updateSkuSaleAndStock(@PathVariable Long skuId, @PathVariable Integer skuNum);
}
@RestController
@Tag(name = "用户地址管理模块", description = "用户地址管理模块")
@RequestMapping("/api/user/userAddress")
public class UserAddressController {
@Operation(summary = "获取地址信息")
@GetMapping("/getUserAddress/{id}")
public Result findUserAddressById(@PathVariable("id") Long id) {
UserAddress userAddress = userAddressService.getById(id);
return Result.ok(userAddress);
}
}
@FeignClient(value = "service-user")
public interface UserClient {
@Operation(summary = "获取地址信息")
@GetMapping("/api/user/userAddress/getUserAddress/{id}")
public Result<UserAddress> findUserAddressById(@PathVariable("id") Long id);
}
@RestController
@RequestMapping("/api/order/cart")
@Tag(name = "购物车模块")
public class CartController {
@Resource
private CartService cartService;
@Operation(summary = "删除购物车选中购物项")
@DeleteMapping("/auth/delCheckedCartInfos")
public Result delCheckedCartInfos()
{
cartService.deleteCheckedCartInfos();
return Result.ok();
}
}
@FeignClient(value = "service-cart")
public interface CartClient {
@GetMapping("/api/order/cart/auth/checkedCartInfos")
public Result<List<CartInfo>> checkedCartInfos();
@DeleteMapping("/api/order/cart/auth/delCheckedCartInfos")
public Result<Void> delCheckedCartInfos();
}
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService {
public Long submitOrder(OrderSubmitDto orderSubmitDto) {
List<OrderItem> orderItemList = orderSubmitDto.getOrderItemList();
if (CollectionUtils.isEmpty(orderItemList)) {
//没有订单项
throw new SpzxException(ResultCodeEnum.FAIL,null);
}
//2、保证订单中商品价格正确、库存足够
//远程调用:service-product 验证前端提交的每个orderItem的价格 和skuId对应的商品当前价格是否一样 和库存是否足够
orderItemList.forEach(orderItem -> {
Result<ProductSku> skuResult = productClient.getById(orderItem.getSkuId());
if (skuResult.getCode() != 200) {
throw new SpzxException(ResultCodeEnum.FAIL,null);
}
ProductSku sku = skuResult.getData();
if (sku.getSalePrice().compareTo(orderItem.getSkuPrice()) != 0) {
//价格不一致
throw new SpzxException(ResultCodeEnum.ORDER_ITEM_PRICE_ERROR,null);
}
if (sku.getStockNum() < orderItem.getSkuNum()) {
//库存不足
throw new SpzxException(ResultCodeEnum.ORDER_ITEM_STOCK_ERROR,null);
}
});
}
}
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService {
public Long submitOrder(OrderSubmitDto orderSubmitDto) {
Result<UserAddress> userAddressResult = userClient.findUserAddressById(orderSubmitDto.getUserAddressId());
if (userAddressResult.getCode() != 200) {
//用户收件人地址信息查询失败
throw new SpzxException(ResultCodeEnum.FAIL,null);
}
//3、创建订单持久化
OrderInfo orderInfo = new OrderInfo();
UserInfo userInfo = SpzxServiceAuthInterceptor.THREAD_LOCAL.get();
orderInfo.setUserId(userInfo.getId());
orderInfo.setNickName(userInfo.getNickName());
//订单号:展示给用户的唯一订单编号
String orderNo = IdUtil.getSnowflake(1, 1).nextIdStr();
orderInfo.setOrderNo(orderNo);
orderInfo.setCouponId(0L);
//计算订单总金额,并返回总金额
BigDecimal totalAmount = orderItemList.stream().map(orderItem -> {
return orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum()));
}).reduce(BigDecimal::add).get();
orderInfo.setTotalAmount(totalAmount);
orderInfo.setCouponAmount(new BigDecimal("0"));
orderInfo.setOriginalTotalAmount(totalAmount);
orderInfo.setFreightFee(orderSubmitDto.getFreightFee());
//orderInfo.setPayType(0);
orderInfo.setOrderStatus(0);
//收件人信息
UserAddress userAddress = userAddressResult.getData();
orderInfo.setReceiverName(userAddress.getName());
orderInfo.setReceiverPhone(userAddress.getPhone());
orderInfo.setReceiverTagName(userAddress.getTagName());
orderInfo.setReceiverProvince(userAddress.getProvinceCode());
orderInfo.setReceiverCity(userAddress.getCityCode());
orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
orderInfo.setReceiverAddress(userAddress.getAddress());
orderInfo.setPaymentTime(new Date());
orderInfo.setDeliveryTime(new Date());
orderInfo.setReceiveTime(new Date());
orderInfo.setCancelTime(new Date());
orderInfo.setCancelReason("");
orderInfo.setRemark(orderSubmitDto.getRemark());
this.save(orderInfo);
Long orderId = orderInfo.getId();
//4、保存订单的所有的订单项列表
//订单项关联订单 id 保存
orderItemList.forEach(orderItem -> {
orderItem.setOrderId(orderId);
});
orderItemService.saveBatch(orderItemList);
}
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService {
@Transactional(rollbackFor = Exception.class)
@Override
public Long submitOrder(OrderSubmitDto orderSubmitDto) {
//5、删除购物车中已创建订单的购物项
//远程调用:service-cart 删除当前用户选中的购物项
cartClient.delCheckedCartInfos();
}
}
@RestController
@Tag(name = "订单管理模块", description = "订单管理模块")
@RequestMapping("/api/order/orderInfo")
public class OrderController {
@Operation(summary = "立即购买:商品详情页立即购买按钮")
@GetMapping("/auth/buy/{skuId}")
public Result buy(@PathVariable("skuId") Long skuId) {
TradeVo tradeVo = orderService.buy(skuId);
return Result.ok(tradeVo);
}
}
@Override
public TradeVo buy(Long skuId) {
Result<ProductSku> skuResult = productClient.getById(skuId);
if (skuResult.getCode() != 200) {
//商品信息查询失败
throw new SpzxException(ResultCodeEnum.FAIL,null);
}
ProductSku sku = skuResult.getData();
Long token = IdUtil.getSnowflake(1,1).nextId();
//将token存到redis:redis的大key问题
stringRedisTemplate.opsForValue().set("spzx:order:"+token.toString(), "1", 30, TimeUnit.MINUTES);
OrderItem orderItem = new OrderItem();
orderItem.setOrderId(token);
orderItem.setSkuNum(1);
orderItem.setSkuPrice(sku.getSalePrice());
orderItem.setThumbImg(sku.getThumbImg());
orderItem.setSkuId(skuId);
orderItem.setSkuName(sku.getSkuName());
TradeVo tradeVo = new TradeVo();
tradeVo.setTotalAmount(orderItem.getSkuPrice());
tradeVo.setOrderItemList(List.of(orderItem));
return tradeVo;
}
幂等性如何保证:相同的请求多次提交如果处理的结果一致
解决思路:和防止表单重复提交一样
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。