mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-23 05:00:25 +08:00
fix:小程序认证错误修复
This commit is contained in:
parent
503fba04e7
commit
490a934869
@ -1,6 +1,7 @@
|
||||
package com.youlai.mall.oms.pojo.dto;
|
||||
|
||||
import com.youlai.mall.oms.pojo.vo.OrderItemVO;
|
||||
import com.youlai.mall.ums.pojo.domain.UmsAddress;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
@ -25,8 +26,9 @@ public class OrderSubmitDTO {
|
||||
// 验价前台传值
|
||||
private Long totalPrice;
|
||||
|
||||
@NotBlank(message = "请选择收货地址")
|
||||
private String addressId;
|
||||
// 收货地址
|
||||
private UmsAddress deliveryAddress;
|
||||
|
||||
|
||||
@Size(max = 500, message = "订单备注长度不能超过500")
|
||||
private String remark;
|
||||
|
@ -13,7 +13,7 @@ import lombok.Data;
|
||||
*/
|
||||
@ApiModel("支付订单详情模型")
|
||||
@Data
|
||||
public class PayInfoVO extends BaseVO {
|
||||
public class PayVO extends BaseVO {
|
||||
|
||||
/**
|
||||
* 支付金额
|
@ -26,11 +26,11 @@ import java.util.Map;
|
||||
public class RabbitMQConfig {
|
||||
|
||||
/**
|
||||
* 定义交换机,订单业务统一使用 order-exchange 交换机
|
||||
* 定义交换机,订单业务统一使用 order.exchange 交换机
|
||||
*/
|
||||
@Bean
|
||||
public Exchange exchange() {
|
||||
return new TopicExchange("order-exchange", true, false);
|
||||
return new TopicExchange("order.exchange", true, false);
|
||||
}
|
||||
/**
|
||||
* 延时队列
|
||||
@ -39,7 +39,7 @@ public class RabbitMQConfig {
|
||||
public Queue delayQueue() {
|
||||
// 延时队列的消息过期了,会自动触发消息的转发,根据routingKey发送到指定的exchange中,exchange路由到死信队列
|
||||
Map<String, Object> args = new HashMap<>();
|
||||
args.put("x-dead-letter-exchange", "order-exchange");
|
||||
args.put("x-dead-letter-exchange", "order.exchange");
|
||||
args.put("x-dead-letter-routing-key", "order:close"); // 死信路由Key
|
||||
args.put("x-message-ttl", 60000); // 单位:毫秒,配置1分钟测试使用
|
||||
return new Queue("order.delay.queue", true, false, false, args);
|
||||
@ -52,7 +52,7 @@ public class RabbitMQConfig {
|
||||
*/
|
||||
@Bean
|
||||
public Binding delayQueueBinding() {
|
||||
return new Binding("order.delay.queue", Binding.DestinationType.QUEUE,"order-exchange","order.create",null);
|
||||
return new Binding("order.delay.queue", Binding.DestinationType.QUEUE,"order.exchange","order.create",null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +69,7 @@ public class RabbitMQConfig {
|
||||
*/
|
||||
@Bean
|
||||
public Binding closeOrderQueueBinding() {
|
||||
return new Binding("order.close.queue", Binding.DestinationType.QUEUE,"order-exchange","order:close",null);
|
||||
return new Binding("order.close.queue", Binding.DestinationType.QUEUE,"order.exchange","order:close",null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.youlai.mall.oms.controller.app;
|
||||
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.mall.oms.enums.PayTypeEnum;
|
||||
import com.youlai.mall.oms.pojo.vo.PayInfoVO;
|
||||
import com.youlai.mall.oms.pojo.vo.PayVO;
|
||||
import com.youlai.mall.oms.service.IOrderPayService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
@ -55,7 +55,7 @@ public class PayController {
|
||||
// TODO
|
||||
break;
|
||||
case BALANCE:
|
||||
orderPayService.payWithBalance(orderId);
|
||||
orderPayService.pay(orderId);
|
||||
break;
|
||||
default:
|
||||
return Result.failed("系统暂不支持该支付方式~");
|
||||
@ -66,7 +66,7 @@ public class PayController {
|
||||
@ApiOperation(value = "获取订单支付详情")
|
||||
@GetMapping("/orderId/{orderId}")
|
||||
public Result detail(@PathVariable Long orderId) {
|
||||
PayInfoVO payInfo = orderPayService.getPayInfo(orderId);
|
||||
PayVO payInfo = orderPayService.getByOrderId(orderId);
|
||||
return Result.success(payInfo);
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,7 @@ package com.youlai.mall.oms.service;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import com.youlai.mall.oms.pojo.domain.OmsOrderPay;
|
||||
import com.youlai.mall.oms.pojo.vo.PayInfoVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.youlai.mall.oms.pojo.vo.PayVO;
|
||||
|
||||
/**
|
||||
* 支付信息表
|
||||
@ -16,8 +15,8 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
public interface IOrderPayService extends IService<OmsOrderPay> {
|
||||
|
||||
void payWithBalance(Long orderId);
|
||||
void pay(Long orderId);
|
||||
|
||||
PayInfoVO getPayInfo(Long orderId);
|
||||
PayVO getByOrderId(Long orderId);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import com.youlai.mall.oms.enums.PayTypeEnum;
|
||||
import com.youlai.mall.oms.pojo.domain.OmsOrder;
|
||||
import com.youlai.mall.oms.pojo.domain.OmsOrderItem;
|
||||
import com.youlai.mall.oms.pojo.domain.OmsOrderPay;
|
||||
import com.youlai.mall.oms.pojo.vo.PayInfoVO;
|
||||
import com.youlai.mall.oms.pojo.vo.PayVO;
|
||||
import com.youlai.mall.oms.service.IOrderItemService;
|
||||
import com.youlai.mall.oms.service.IOrderPayService;
|
||||
import com.youlai.mall.oms.service.IOrderService;
|
||||
@ -33,14 +33,12 @@ public class OrderPayServiceImpl extends ServiceImpl<OrderPayMapper, OmsOrderPay
|
||||
|
||||
private IOrderService orderService;
|
||||
private UmsMemberFeignService memberFeignService;
|
||||
|
||||
private IOrderItemService orderItemService;
|
||||
|
||||
private PmsSkuFeignService skuFeignService;
|
||||
|
||||
@Override
|
||||
@GlobalTransactional(rollbackFor = Exception.class)
|
||||
public void payWithBalance(Long orderId) {
|
||||
public void pay(Long orderId) {
|
||||
|
||||
// 查询订单状态
|
||||
OmsOrder order = orderService.getByOrderId(orderId);
|
||||
@ -86,19 +84,19 @@ public class OrderPayServiceImpl extends ServiceImpl<OrderPayMapper, OmsOrderPay
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayInfoVO getPayInfo(Long orderId) {
|
||||
PayInfoVO payInfoVO = new PayInfoVO();
|
||||
public PayVO getByOrderId(Long orderId) {
|
||||
PayVO payVO = new PayVO();
|
||||
|
||||
// 1、获取订单应支付金额
|
||||
OmsOrder omsOrder = orderService.getByOrderId(orderId);
|
||||
payInfoVO.setPayAmount(omsOrder.getPayAmount());
|
||||
payVO.setPayAmount(omsOrder.getPayAmount());
|
||||
|
||||
// 2、获取会员余额
|
||||
Long userId = RequestUtils.getUserId();
|
||||
Long balance = memberFeignService.getBalance(userId).getData();
|
||||
payInfoVO.setBalance(balance);
|
||||
payVO.setBalance(balance);
|
||||
|
||||
return payInfoVO;
|
||||
return payVO;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,50 +1,46 @@
|
||||
package com.youlai.mall.oms.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import com.youlai.common.web.exception.BizException;
|
||||
import com.youlai.common.web.util.BeanMapperUtils;
|
||||
import com.youlai.common.web.util.RequestUtils;
|
||||
import com.youlai.mall.oms.enums.OrderStatusEnum;
|
||||
import com.youlai.mall.oms.enums.OrderTypeEnum;
|
||||
import com.youlai.mall.oms.mapper.OrderMapper;
|
||||
import com.youlai.mall.oms.pojo.bo.app.OrderBO;
|
||||
import com.youlai.mall.oms.pojo.domain.OmsOrder;
|
||||
import com.youlai.mall.oms.pojo.domain.OmsOrderDelivery;
|
||||
import com.youlai.mall.oms.pojo.domain.OmsOrderItem;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderConfirmDTO;
|
||||
import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO;
|
||||
import com.youlai.mall.oms.pojo.vo.*;
|
||||
import com.youlai.mall.oms.service.*;
|
||||
import com.youlai.mall.oms.service.ICartService;
|
||||
import com.youlai.mall.oms.service.IOrderItemService;
|
||||
import com.youlai.mall.oms.service.IOrderLogService;
|
||||
import com.youlai.mall.oms.service.IOrderService;
|
||||
import com.youlai.mall.pms.api.app.PmsSkuFeignService;
|
||||
import com.youlai.mall.pms.pojo.domain.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuLockDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.SkuDTO;
|
||||
import com.youlai.mall.ums.api.UmsAddressFeignService;
|
||||
import com.youlai.mall.ums.api.UmsMemberFeignService;
|
||||
import com.youlai.mall.ums.pojo.domain.UmsAddress;
|
||||
import io.seata.spring.annotation.GlobalTransactional;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.stream.Collectors;
|
||||
@ -56,31 +52,18 @@ import static com.youlai.mall.oms.constant.OmsConstants.*;
|
||||
@Service
|
||||
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> implements IOrderService {
|
||||
|
||||
private static final ThreadLocal<OrderSubmitDTO> threadLocal = new ThreadLocal<>();
|
||||
|
||||
private ICartService cartService;
|
||||
|
||||
private PmsSkuFeignService skuFeignService;
|
||||
|
||||
private UmsMemberFeignService memberFeignService;
|
||||
|
||||
private UmsAddressFeignService addressFeignService;
|
||||
|
||||
private AsyncTaskExecutor executor;
|
||||
|
||||
private IOrderItemService orderItemService;
|
||||
|
||||
private IOrderDeliveryService orderDeliveryService;
|
||||
|
||||
private IOrderLogService orderLogService;
|
||||
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
private ThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
|
||||
/**
|
||||
* 订单确认
|
||||
*/
|
||||
@Override
|
||||
public OrderConfirmVO confirm(OrderConfirmDTO orderConfirmDTO) {
|
||||
OrderConfirmVO orderConfirmVO = new OrderConfirmVO();
|
||||
@ -132,6 +115,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
return orderConfirmVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单提交
|
||||
*/
|
||||
@Override
|
||||
@GlobalTransactional
|
||||
public OrderSubmitVO submit(OrderSubmitDTO submitDTO) {
|
||||
@ -177,7 +163,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
throw new BizException(Result.failed().getMsg());
|
||||
}
|
||||
|
||||
// 保存订单
|
||||
// 创建订单(状态:待支付)
|
||||
OmsOrder order = new OmsOrder();
|
||||
order.setOrderSn(IdWorker.getTimeId())
|
||||
.setStatus(OrderStatusEnum.PENDING_PAYMENT.getCode())
|
||||
@ -186,7 +172,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
.setRemark(submitDTO.getRemark());
|
||||
this.save(order);
|
||||
|
||||
// 保存订单商品
|
||||
// 创建订单商品
|
||||
List<OmsOrderItem> orderItemList = orderItems.stream().map(item -> OmsOrderItem.builder()
|
||||
.orderId(order.getId())
|
||||
.skuId(item.getSkuId())
|
||||
@ -197,15 +183,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
orderItemService.saveBatch(orderItemList);
|
||||
|
||||
// 将订单放入延时队列,超时未支付系统自动关单
|
||||
rabbitTemplate.convertAndSend("order-exchange", "order:create", orderToken);
|
||||
|
||||
// 记录发货 TODO
|
||||
rabbitTemplate.convertAndSend("order.exchange", "order:create", orderToken);
|
||||
|
||||
OrderSubmitVO submitVO = new OrderSubmitVO();
|
||||
submitVO.setId(order.getId());
|
||||
submitVO.setOrderSn(order.getOrderSn());
|
||||
return submitVO;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -230,7 +213,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
}
|
||||
order.setStatus(OrderStatusEnum.USER_CANCEL.getCode());
|
||||
this.updateById(order);
|
||||
orderLogService.addOrderLogs(order.getId(), order.getStatus(), OrderStatusEnum.USER_CANCEL.getText());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -244,7 +226,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
throw new BizException("订单状态不允许删除");
|
||||
}
|
||||
this.removeById(id);
|
||||
orderLogService.addOrderLogs(order.getId(), order.getStatus(), "会员删除订单");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -291,7 +272,4 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -100,7 +100,6 @@
|
||||
<artifactId>seata-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
|
@ -6,6 +6,7 @@ package com.youlai.mall.pms.common.constant;
|
||||
*/
|
||||
public interface PmsConstants {
|
||||
|
||||
String PMS_STOCK_LOCK_PREFIX = "pms:stock:lock:";
|
||||
String STOCK_LOCKED_PREFIX = "stock:locked:";
|
||||
|
||||
String LOCK_SKU_PREFIX="lock:sku:";
|
||||
}
|
||||
|
@ -21,16 +21,16 @@ public class SkuController {
|
||||
|
||||
private IPmsSkuService iPmsSkuService;
|
||||
|
||||
@ApiOperation(value = "商品库存详情", httpMethod = "GET")
|
||||
@ApiImplicitParam(name = "id", value = "商品库存ID", required = true, paramType = "path", dataType = "Long")
|
||||
@ApiOperation(value = "商品详情", httpMethod = "GET")
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}")
|
||||
public Result getById(@PathVariable Long id) {
|
||||
public Result detail(@PathVariable Long id) {
|
||||
PmsSku sku = iPmsSkuService.getById(id);
|
||||
return Result.success(sku);
|
||||
}
|
||||
|
||||
@ApiOperation("获取商品的库存数量")
|
||||
@ApiImplicitParam(name = "id", value = "商品库存ID", required = true, paramType = "path", dataType = "Long")
|
||||
@ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long")
|
||||
@GetMapping("/{id}/stock")
|
||||
public Result<Integer> getStockById(@PathVariable Long id) {
|
||||
Integer stock = iPmsSkuService.getStockById(id);
|
||||
@ -38,8 +38,8 @@ public class SkuController {
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "锁定库存", httpMethod = "PUT")
|
||||
@ApiImplicitParam(name = "list", value = "锁定库存", required = true, paramType = "body", dataType = "InventoryNumDTO")
|
||||
@ApiOperation(value = "批量锁定库存", httpMethod = "PUT")
|
||||
@ApiImplicitParam(name = "list", value = "商品列表", required = true, paramType = "body", dataType = "SkuLockDTO")
|
||||
@PutMapping("/batch/lock_stock")
|
||||
public Result<Boolean> lockStock(@RequestBody List<SkuLockDTO> list) {
|
||||
boolean result = iPmsSkuService.lockStock(list);
|
||||
@ -47,25 +47,24 @@ public class SkuController {
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "解锁库存", httpMethod = "PUT")
|
||||
@ApiImplicitParam(name = "list", value = "释放库存", required = true, paramType = "body", dataType = "InventoryNumDTO")
|
||||
@ApiOperation(value = "批量解锁库存", httpMethod = "PUT")
|
||||
@ApiImplicitParam(name = "list", value = "商品列表", required = true, paramType = "body", dataType = "SkuLockDTO")
|
||||
@PutMapping("/batch/unlock_stock")
|
||||
public Result<Boolean> unlockStock(@RequestBody List<SkuLockDTO> list) {
|
||||
boolean result = iPmsSkuService.unlockStock(list);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "扣减库存", httpMethod = "PUT")
|
||||
@ApiImplicitParam(name = "list", value = "释放库存", required = true, paramType = "body", dataType = "InventoryNumDTO")
|
||||
@ApiOperation(value = "批量扣减库存", httpMethod = "PUT")
|
||||
@ApiImplicitParam(name = "list", value = "商品列表", required = true, paramType = "body", dataType = "SkuLockDTO")
|
||||
@PutMapping("/batch/deduct_stock")
|
||||
public Result<Boolean> deductStock(@RequestBody List<SkuLockDTO> list) {
|
||||
boolean result = iPmsSkuService.deductStock(list);
|
||||
return Result.judge(result);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "库存列表", httpMethod = "GET")
|
||||
@ApiImplicitParam(name = "skuIds", value = "库存ID集合", required = true, paramType = "body", dataType = "String")
|
||||
@ApiOperation(value = "商品列表", httpMethod = "GET")
|
||||
@ApiImplicitParam(name = "skuIds", value = "商品ID集合", required = true, paramType = "body", dataType = "String")
|
||||
@GetMapping
|
||||
public Result list(@RequestParam List<Long> ids) {
|
||||
List<SkuDTO> list = iPmsSkuService.listBySkuIds(ids);
|
||||
|
@ -11,33 +11,27 @@ public interface IPmsSkuService extends IService<PmsSku> {
|
||||
|
||||
/**
|
||||
* 锁定库存
|
||||
* @param list
|
||||
* @return 库存锁定结果
|
||||
*/
|
||||
boolean lockStock(List<SkuLockDTO> list);
|
||||
|
||||
/**
|
||||
* 解锁库存
|
||||
* @param list
|
||||
* @return 解锁库存结果
|
||||
*/
|
||||
boolean unlockStock(List<SkuLockDTO> list);
|
||||
boolean unlockStock(String orderToken);
|
||||
|
||||
/**
|
||||
* 扣减库存
|
||||
*/
|
||||
boolean deductStock(String orderToken);
|
||||
|
||||
/**
|
||||
* 获取商品库存数量
|
||||
* @param id 库存ID
|
||||
* @return
|
||||
*/
|
||||
Integer getStockById(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 获取库存列表
|
||||
* @param ids
|
||||
* @return
|
||||
* 获取商品列表
|
||||
*/
|
||||
List<SkuDTO> listBySkuIds(List<Long> ids);
|
||||
|
||||
boolean deductStock(List<SkuLockDTO> list);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.youlai.mall.pms.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
@ -15,14 +16,16 @@ import com.youlai.mall.pms.pojo.dto.SkuLockDTO;
|
||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.youlai.mall.pms.common.constant.PmsConstants.PMS_STOCK_LOCK_PREFIX;
|
||||
import static com.youlai.mall.pms.common.constant.PmsConstants.LOCK_SKU_PREFIX;
|
||||
import static com.youlai.mall.pms.common.constant.PmsConstants.STOCK_LOCKED_PREFIX;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@ -30,76 +33,107 @@ import static com.youlai.mall.pms.common.constant.PmsConstants.PMS_STOCK_LOCK_PR
|
||||
public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> implements IPmsSkuService {
|
||||
|
||||
|
||||
private RedisTemplate redisTemplate;
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
* 创建订单时锁定库存
|
||||
*/
|
||||
@Override
|
||||
public boolean lockStock(List<SkuLockDTO> skuLockList) {
|
||||
|
||||
if (CollectionUtil.isNotEmpty(skuLockList)) {
|
||||
throw new BizException("锁定商品为空");
|
||||
throw new BizException("锁定的商品列表为空");
|
||||
}
|
||||
|
||||
// 锁定商品
|
||||
skuLockList.forEach(item -> {
|
||||
RLock lock = redissonClient.getLock(LOCK_SKU_PREFIX + item.getSkuId()); // 获取商品的分布式锁
|
||||
lock.lock();
|
||||
boolean result = this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
.setSql("locked_stock = locked_stock + " + item.getCount())
|
||||
.eq(PmsSku::getId, item.getSkuId())
|
||||
.apply("stock >= locked_stock + {0}", item.getCount())
|
||||
.apply("stock - locked_stock >= {0}", item.getCount())
|
||||
);
|
||||
if (result) {
|
||||
item.setLocked(true);
|
||||
} else {
|
||||
item.setLocked(false);
|
||||
}
|
||||
lock.unlock();
|
||||
});
|
||||
|
||||
// 锁定失败的商品集合
|
||||
List<SkuLockDTO> unlockSkus = skuLockList.stream().filter(item -> !item.getLocked()).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(unlockSkus)) {
|
||||
List<SkuLockDTO> unlockSkuList = skuLockList.stream().filter(item -> !item.getLocked()).collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(unlockSkuList)) {
|
||||
// 恢复已被锁定的库存
|
||||
List<SkuLockDTO> lockSkus = skuLockList.stream().filter(SkuLockDTO::getLocked).collect(Collectors.toList());
|
||||
this.unlockStock(lockSkus);
|
||||
|
||||
List<Long> ids = unlockSkus.stream().map(SkuLockDTO::getSkuId).collect(Collectors.toList());
|
||||
List<SkuLockDTO> lockSkuList = skuLockList.stream().filter(SkuLockDTO::getLocked).collect(Collectors.toList());
|
||||
lockSkuList.forEach(item ->
|
||||
this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
.eq(PmsSku::getId, item.getSkuId())
|
||||
.setSql("locked_stock = locked_stock - " + item.getCount()))
|
||||
);
|
||||
// 提示订单哪些商品库存不足
|
||||
List<Long> ids = unlockSkuList.stream().map(SkuLockDTO::getSkuId).collect(Collectors.toList());
|
||||
throw new BizException("商品" + ids.toString() + "库存不足");
|
||||
}
|
||||
|
||||
// 将锁定的商品保存至Redis中
|
||||
String orderToken = skuLockList.get(0).getOrderToken();
|
||||
stringRedisTemplate.opsForValue().set(PMS_STOCK_LOCK_PREFIX+orderToken, JSONUtil.toJsonStr(skuLockList));
|
||||
redisTemplate.opsForValue().set(STOCK_LOCKED_PREFIX + orderToken, JSONUtil.toJsonStr(skuLockList));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单超时关单解锁库存
|
||||
*/
|
||||
@Override
|
||||
public boolean unlockStock(List<SkuLockDTO> skuList) {
|
||||
skuList.forEach(item -> {
|
||||
boolean result = this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
.eq(PmsSku::getId, item.getSkuId())
|
||||
.setSql("locked_stock = locked_stock - " + item.getCount())
|
||||
);
|
||||
if (!result) {
|
||||
throw new BizException("解锁库存失败,库存ID:" + item.getSkuId() + ",数量:" + item.getCount());
|
||||
}
|
||||
});
|
||||
public boolean unlockStock(String orderToken) {
|
||||
String json = redisTemplate.opsForValue().get(STOCK_LOCKED_PREFIX + orderToken);
|
||||
if (StrUtil.isNotBlank(json)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<SkuLockDTO> skuLockList = JSONUtil.toList(json, SkuLockDTO.class);
|
||||
|
||||
skuLockList.forEach(item ->
|
||||
this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
.eq(PmsSku::getId, item.getSkuId())
|
||||
.setSql("locked_stock = locked_stock - " + item.getCount()))
|
||||
);
|
||||
|
||||
// 删除redis中锁定的库存
|
||||
redisTemplate.opsForValue().decrement(STOCK_LOCKED_PREFIX + orderToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 支付成功时扣减库存
|
||||
*/
|
||||
@Override
|
||||
public boolean deductStock(List<SkuLockDTO> inventories) {
|
||||
inventories.forEach(item -> {
|
||||
public boolean deductStock(String orderToken) {
|
||||
String json = redisTemplate.opsForValue().get(STOCK_LOCKED_PREFIX + orderToken);
|
||||
if (StrUtil.isNotBlank(json)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<SkuLockDTO> skuLockList = JSONUtil.toList(json, SkuLockDTO.class);
|
||||
|
||||
skuLockList.forEach(item -> {
|
||||
boolean result = this.update(new LambdaUpdateWrapper<PmsSku>()
|
||||
.eq(PmsSku::getId, item.getSkuId())
|
||||
.setSql("stock = stock - " + item.getCount()) // 扣减库存
|
||||
.setSql("locked_stock = locked_stock - " + item.getCount())
|
||||
.setSql("stock = stock - " + item.getCount())
|
||||
);
|
||||
if (!result) {
|
||||
throw new BizException("扣减库存失败");
|
||||
throw new BizException("扣减库存失败,商品" + item.getSkuId() + "库存不足");
|
||||
}
|
||||
});
|
||||
return false;
|
||||
|
||||
// 删除redis中锁定的库存
|
||||
redisTemplate.opsForValue().decrement(STOCK_LOCKED_PREFIX + orderToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -115,7 +149,7 @@ public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> impleme
|
||||
public Integer getStockById(Long id) {
|
||||
Integer stock = 0;
|
||||
// 读->缓存
|
||||
Object cacheVal = redisTemplate.opsForValue().get(PMS_STOCK_LOCK_PREFIX + id);
|
||||
Object cacheVal = redisTemplate.opsForValue().get(STOCK_LOCKED_PREFIX + id);
|
||||
if (cacheVal != null) {
|
||||
stock = Convert.toInt(cacheVal);
|
||||
return stock;
|
||||
@ -129,7 +163,7 @@ public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> impleme
|
||||
if (pmsSku != null) {
|
||||
stock = pmsSku.getStock();
|
||||
// 写->缓存
|
||||
redisTemplate.opsForValue().set(PmsConstants.PMS_STOCK_LOCK_PREFIX + id, stock);
|
||||
redisTemplate.opsForValue().set(PmsConstants.STOCK_LOCKED_PREFIX + id, String.valueOf(stock));
|
||||
}
|
||||
|
||||
return stock;
|
||||
|
@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@FeignClient(name = "ums-address")
|
||||
@FeignClient(name = "mall-ums",contextId = "address")
|
||||
public interface UmsAddressFeignService {
|
||||
|
||||
/**
|
||||
|
@ -7,7 +7,7 @@ import com.youlai.mall.ums.pojo.dto.MemberDTO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@FeignClient(name = "ums-member")
|
||||
@FeignClient(name = "mall-ums",contextId = "member")
|
||||
public interface UmsMemberFeignService {
|
||||
|
||||
@PostMapping("/api.app/v1/users")
|
||||
|
9
pom.xml
9
pom.xml
@ -46,7 +46,7 @@
|
||||
<seata.version>1.4.1</seata.version>
|
||||
<commons-pool2.version>2.9.0</commons-pool2.version>
|
||||
<knife4j.version>2.0.8</knife4j.version>
|
||||
<redisson.version>3.11.1</redisson.version>
|
||||
<redisson.version>3.15.1</redisson.version>
|
||||
<logstash-logback-encoder.version>6.6</logstash-logback-encoder.version>
|
||||
<elasticsearch.version>7.10.1</elasticsearch.version>
|
||||
<ip2region.version>1.7.2</ip2region.version>
|
||||
@ -159,6 +159,7 @@
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ELK -->
|
||||
<dependency>
|
||||
<groupId>net.logstash.logback</groupId>
|
||||
<artifactId>logstash-logback-encoder</artifactId>
|
||||
@ -183,12 +184,14 @@
|
||||
<version>${elasticsearch.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 分布式锁 -->
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson</artifactId>
|
||||
<version>${redisson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- IP转地区工具 -->
|
||||
<dependency>
|
||||
<groupId>org.lionsoul</groupId>
|
||||
<artifactId>ip2region</artifactId>
|
||||
@ -207,8 +210,6 @@
|
||||
<version>${swagger.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.youlai</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
@ -244,8 +245,6 @@
|
||||
<artifactId>common-web</artifactId>
|
||||
<version>${youlai.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user