订单服务 - raymond-zhao/cat-mall GitHub Wiki
订单服务
防重操作
下单操作
@Transactional
@Override
public SubmitOrderResponseVO submitOrder(OrderSubmitVO submitVO) {
confirmVOThreadLocal.set(submitVO);
SubmitOrderResponseVO responseVO = new SubmitOrderResponseVO();
MemberResponseVO memberResponseVO = LoginUserInterceptor.loginUser.get();
responseVO.setCode(0);
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
String orderToken = submitVO.getOrderToken();
// 原子性操作验证和删除令牌
Long result = stringRedisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberResponseVO.getId()), orderToken);
if (result == 0) {
// 令牌验证失败
responseVO.setCode(1);
return responseVO;
} else {
// 验证成功 下单 去创建订单 验证令牌 核算价格 锁定库存
OrderCreateTO orderCreateTO = createOrder();
// 验价
BigDecimal payAmount = orderCreateTO.getOrderEntity().getPayAmount();
BigDecimal payPrice = submitVO.getPayPrice();
if (Math.abs(payAmount.subtract(payPrice).doubleValue()) < 0.01) {
// 金额对比
// 保存订单
saveOrder(orderCreateTO);
// 锁定库存 只要有异常就回滚数据
WareSkuLockVO lockVO = new WareSkuLockVO();
lockVO.setOrderSn(orderCreateTO.getOrderEntity().getOrderSn());
List<OrderItemVO> locks = orderCreateTO.getOrderItems().stream().map(o -> {
OrderItemVO itemVO = new OrderItemVO();
itemVO.setSkuId(o.getSkuId());
itemVO.setCount(o.getSkuQuantity());
itemVO.setTitle(o.getSkuName());
return itemVO;
}).collect(Collectors.toList());
lockVO.setLocks(locks);
R r = wareFeign.lockOrder(lockVO);
if (r.getCode() == 0) {
// 锁定成功
responseVO.setOrderEntity(orderCreateTO.getOrderEntity());
rabbitTemplate.convertAndSend("order-event-exchange", "order.create.order", orderCreateTO.getOrderEntity());
return responseVO;
} else {
// 锁定失败
throw new NoStockException((String) r.get("msg"));
}
} else {
responseVO.setCode(2);
return responseVO;
}
}
}