|
|
@@ -90,7 +90,6 @@ import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
|
|
|
import com.fs.huifuPay.service.HuiFuService;
|
|
|
import com.fs.live.domain.*;
|
|
|
import com.fs.live.dto.LiveOrderComputeDTO;
|
|
|
-import com.fs.live.dto.LiveOrderCustomerExportDTO;
|
|
|
import com.fs.live.dto.LiveOrderDeliveryNoteDTO;
|
|
|
import com.fs.live.dto.LiveOrderItemDTO;
|
|
|
import com.fs.live.enums.LiveAfterSalesStatusEnum;
|
|
|
@@ -203,6 +202,9 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
@Autowired
|
|
|
private LiveUserLotteryRecordMapper liveUserLotteryRecordMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private IFsStoreProductPurchaseLimitScrmService purchaseLimitService;
|
|
|
+
|
|
|
@Autowired
|
|
|
ICompanyUserService companyUserService;
|
|
|
|
|
|
@@ -299,6 +301,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
|
|
|
@Autowired
|
|
|
private FsWxExpressTaskMapper fsWxExpressTaskMapper;
|
|
|
+ @Autowired
|
|
|
+ private LiveCouponUserMapper liveCouponUserMapper;
|
|
|
|
|
|
//ERP 类型到服务的映射
|
|
|
private Map<Integer, IErpOrderService> erpServiceMap;
|
|
|
@@ -697,8 +701,27 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
@Override
|
|
|
@Transactional
|
|
|
public String payConfirm(Integer type,Long orderId,String payCode,String tradeNo,String bankTransactionId,String bankSerialNo) {
|
|
|
+ // 使用 Redis setNx 加分布式锁,基于订单ID或支付单号
|
|
|
+ String lockKey;
|
|
|
+ if (type.equals(1) && StringUtils.isNotEmpty(payCode)) {
|
|
|
+ lockKey = "livePayConfirm:lock:" + payCode;
|
|
|
+ } else if (orderId != null) {
|
|
|
+ lockKey = "livePayConfirm:lock:" + orderId;
|
|
|
+ } else {
|
|
|
+ lockKey = "livePayConfirm:lock:" + System.currentTimeMillis();
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean lockAcquired = false;
|
|
|
Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
|
|
|
try {
|
|
|
+ // 尝试获取锁,锁过期时间设置为30秒
|
|
|
+ lockAcquired = redisCache.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
|
|
|
+ if (!lockAcquired) {
|
|
|
+ // 如果获取锁失败,说明有其他线程正在处理该订单,直接返回
|
|
|
+ log.info("支付确认处理中,订单ID: {}, 支付单号: {}", orderId, payCode);
|
|
|
+ return "SUCCESS";
|
|
|
+ }
|
|
|
+
|
|
|
LiveOrder order=null;
|
|
|
if(type.equals(1)){
|
|
|
LiveOrderPayment storePayment = liveOrderPaymentMapper.selectLiveOrderPaymentByPaymentCode(payCode);
|
|
|
@@ -762,6 +785,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
baseMapper.updateLiveOrder(order);
|
|
|
try {
|
|
|
this.updateLiveWatchLog(order);
|
|
|
+ // 记录限购数量(订单创建成功后记录)
|
|
|
+ purchaseLimitService.increasePurchaseLimit(order.getProductId(), Long.valueOf(order.getUserId()), Integer.valueOf(order.getTotalNum()));
|
|
|
this.createOmsOrderCall(order);
|
|
|
} catch (Exception e) {
|
|
|
log.error("推送erp失败:{}",e.getMessage());
|
|
|
@@ -777,6 +802,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
err.setMsg("支付错误:"+e.getMessage());
|
|
|
err.setCreateTime(DateUtils.getNowDate());
|
|
|
liveOrderPaymentErrorMapper.insertLiveOrderPaymentError(err);
|
|
|
+ } finally {
|
|
|
+ // 释放锁
|
|
|
+ if (lockAcquired) {
|
|
|
+ redisCache.deleteObject(lockKey);
|
|
|
+ }
|
|
|
}
|
|
|
return "SUCCESS";
|
|
|
}
|
|
|
@@ -1161,15 +1191,15 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
|
|
|
|
|
|
//模板消息支付成功发布事件
|
|
|
- TemplateBean templateBean = TemplateBean.builder()
|
|
|
- .orderId(order.getOrderId().toString())
|
|
|
- .orderCode(order.getOrderCode().toString())
|
|
|
- .remark("您的订单已签收成功")
|
|
|
- .finishTime(order.getFinishTime())
|
|
|
- .userId(Long.valueOf(order.getUserId()))
|
|
|
- .templateType(TemplateListenEnum.TYPE_3.getValue())
|
|
|
- .build();
|
|
|
- publisher.publishEvent(new TemplateEvent(this, templateBean));
|
|
|
+// TemplateBean templateBean = TemplateBean.builder()
|
|
|
+// .orderId(order.getOrderId().toString())
|
|
|
+// .orderCode(order.getOrderCode().toString())
|
|
|
+// .remark("您的订单已签收成功")
|
|
|
+// .finishTime(order.getFinishTime())
|
|
|
+// .userId(Long.valueOf(order.getUserId()))
|
|
|
+// .templateType(TemplateListenEnum.TYPE_3.getValue())
|
|
|
+// .build();
|
|
|
+// publisher.publishEvent(new TemplateEvent(this, templateBean));
|
|
|
return R.ok("操作成功");
|
|
|
} else {
|
|
|
return R.error("非法操作");
|
|
|
@@ -1402,6 +1432,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
userService.subTuiMoney(storeOrder);
|
|
|
}
|
|
|
}
|
|
|
+ // 删除限购记录
|
|
|
+ deletePurchaseLimitRecordsForLiveOrder(order);
|
|
|
|
|
|
return R.ok();
|
|
|
}
|
|
|
@@ -1621,6 +1653,14 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
userService.subLiveTuiMoney(liveOrder);
|
|
|
}
|
|
|
}
|
|
|
+ //优惠券返回
|
|
|
+ if(order.getUserCouponId()!=null){
|
|
|
+ // 退券
|
|
|
+ order.setCouponUserId(Long.parseLong(order.getUserId()));
|
|
|
+ this.refundCoupon(order);
|
|
|
+ }
|
|
|
+ // 删除限购记录
|
|
|
+ deletePurchaseLimitRecordsForLiveOrder(order);
|
|
|
|
|
|
return R.ok();
|
|
|
}
|
|
|
@@ -3628,6 +3668,20 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
this.payConfirm(1, null, payment.getPayCode(), payment.getTradeNo(), payment.getBankSerialNo(), payment.getBankSerialNo());
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public void updateTime(LiveOrder order) {
|
|
|
+ LiveOrder liveOrder = new LiveOrder();
|
|
|
+ liveOrder.setOrderId(order.getOrderId());
|
|
|
+ liveOrder.setUpdateTime(order.getUpdateTime());
|
|
|
+ liveOrderMapper.updateLiveOrder(liveOrder);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void deStockIncSale(List<FsStoreCartQueryVO> cartInfo) {
|
|
|
+ for (FsStoreCartQueryVO storeCartVO : cartInfo) {
|
|
|
+ fsStoreProductService.decProductStock(storeCartVO.getProductId(),
|
|
|
+ storeCartVO.getProductAttrValueId(), storeCartVO.getCartNum());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
|
|
|
@@ -3657,22 +3711,19 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
if(!"1".equals(fsStoreProduct.getIsAudit()) ) return R.error("商品已下架,购买失败");
|
|
|
if(liveOrder.getTotalNum() == null || StringUtils.isEmpty(liveOrder.getTotalNum())) liveOrder.setTotalNum("1");
|
|
|
if(goods.getStock() == null) return R.error("直播间商品库存不足");
|
|
|
- if(fsStoreProduct.getStock() < Integer.parseInt(liveOrder.getTotalNum()) || goods.getStock() < Integer.parseInt(liveOrder.getTotalNum())) return R.error("抱歉,这款商品已被抢光,暂时无库存~");
|
|
|
-
|
|
|
- FsStoreProductAttrValueScrm attrValue = null;
|
|
|
- if (!Objects.isNull(liveOrder.getAttrValueId())) {
|
|
|
- attrValue = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueById(liveOrder.getAttrValueId());
|
|
|
- }
|
|
|
- if (attrValue != null) {
|
|
|
- attrValue.setStock(attrValue.getStock() - Integer.parseInt(liveOrder.getTotalNum()));
|
|
|
- attrValue.setSales(attrValue.getSales() + Integer.parseInt(liveOrder.getTotalNum()));
|
|
|
- fsStoreProductAttrValueMapper.updateFsStoreProductAttrValue(attrValue);
|
|
|
+ FsStoreProductAttrValueScrm attrValue = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueById(liveOrder.getAttrValueId());
|
|
|
+ if(fsStoreProduct.getStock() < Integer.parseInt(liveOrder.getTotalNum()) || goods.getStock() < Integer.parseInt(liveOrder.getTotalNum()) || attrValue.getStock() < Integer.parseInt(liveOrder.getTotalNum())){
|
|
|
+ return R.error("抱歉,这款商品已被抢光,暂时无库存~");
|
|
|
}
|
|
|
- // 更改店铺库存
|
|
|
- fsStoreProduct.setStock(fsStoreProduct.getStock()-Integer.parseInt(liveOrder.getTotalNum()));
|
|
|
- fsStoreProduct.setSales(fsStoreProduct.getSales()+Integer.parseInt(liveOrder.getTotalNum()));
|
|
|
- fsStoreProductScrmMapper.incStockDecSales(Long.valueOf("-" + liveOrder.getTotalNum()),fsStoreProduct.getProductId());
|
|
|
|
|
|
+
|
|
|
+ // 检查限购
|
|
|
+ Long userId = Long.parseLong(liveOrder.getUserId());
|
|
|
+ Integer purchaseNum = Integer.parseInt(liveOrder.getTotalNum());
|
|
|
+ checkPurchaseLimitForLiveOrder(userId, liveOrder.getProductId(), purchaseNum);
|
|
|
+
|
|
|
+ // 使用 deStockIncSale 方法处理库存和销量
|
|
|
+ deStockIncSale(liveOrder.getProductId(), liveOrder.getAttrValueId(), purchaseNum);
|
|
|
// 更新直播间库存
|
|
|
goods.setStock(goods.getStock()-Integer.parseInt(liveOrder.getTotalNum()));
|
|
|
goods.setSales(goods.getSales()+Integer.parseInt(liveOrder.getTotalNum()));
|
|
|
@@ -3700,6 +3751,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
BigDecimal payPrice = fsStoreProduct.getPrice().multiply(new BigDecimal(liveOrder.getTotalNum()));
|
|
|
if (attrValue != null) {
|
|
|
payPrice = attrValue.getPrice().multiply(new BigDecimal(liveOrder.getTotalNum()));
|
|
|
+ fsStoreProduct.setPrice(payPrice);
|
|
|
}
|
|
|
// 直播不需要服务费 0915 1735 左
|
|
|
// String config=configService.selectConfigByKey("store.config");
|
|
|
@@ -3758,11 +3810,13 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
dto.setBarCode(fsStoreProductAttrValue.getBarCode());
|
|
|
dto.setGroupBarCode(fsStoreProductAttrValue.getGroupBarCode());
|
|
|
}
|
|
|
+ dto.setPrice(fsStoreProduct.getPrice());
|
|
|
if (attrValue != null) {
|
|
|
dto.setBarCode(attrValue.getBarCode());
|
|
|
dto.setGroupBarCode(attrValue.getGroupBarCode());
|
|
|
+ dto.setPrice(attrValue.getPrice());
|
|
|
}
|
|
|
- dto.setPrice(fsStoreProduct.getPrice());
|
|
|
+ //dto.setPrice(fsStoreProduct.getPrice());
|
|
|
dto.setProductName(fsStoreProduct.getProductName());
|
|
|
dto.setNum(Long.valueOf(liveOrder.getTotalNum()));
|
|
|
|
|
|
@@ -3773,6 +3827,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
liveOrderItem.setNum(Long.valueOf(liveOrder.getTotalNum()));
|
|
|
liveOrderItem.setJsonInfo(JSON.toJSONString(dto));
|
|
|
liveOrderItemMapper.insertLiveOrderItem(liveOrderItem);
|
|
|
+
|
|
|
+
|
|
|
redisCache.deleteObject("orderKey:" + liveOrder.getOrderKey());
|
|
|
//添加支付到期时间
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
|
@@ -3943,6 +3999,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
goods.setStock(goods.getStock()+Long.parseLong(liveOrder.getTotalNum()));
|
|
|
// 更新商品库存
|
|
|
liveGoodsMapper.updateLiveGoods(goods);
|
|
|
+
|
|
|
// 退券
|
|
|
this.refundCoupon(order);
|
|
|
TemplateBean templateBean = TemplateBean.builder()
|
|
|
@@ -3960,6 +4017,57 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 检查限购(用于直播订单)
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @param productId 商品ID
|
|
|
+ * @param num 购买数量
|
|
|
+ */
|
|
|
+ /**
|
|
|
+ * 减库存加销量(直播订单)
|
|
|
+ */
|
|
|
+ private void deStockIncSale(Long productId, Long attrValueId, Integer num) {
|
|
|
+ // 使用 productService.decProductStock 方法,该方法已包含库存检查逻辑
|
|
|
+ fsStoreProductService.decProductStock(productId, attrValueId, num);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkPurchaseLimitForLiveOrder(Long userId, Long productId, Integer num) {
|
|
|
+ // 查询商品信息
|
|
|
+ FsStoreProductScrm product = fsStoreProductService.selectFsStoreProductById(productId);
|
|
|
+ if (product == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果商品没有设置限购,直接返回
|
|
|
+ if (product.getPurchaseLimit() == null || product.getPurchaseLimit() <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询用户已购买的数量
|
|
|
+ FsStoreProductPurchaseLimitScrm purchaseLimit = purchaseLimitService.selectByProductIdAndUserId(productId, userId);
|
|
|
+ int purchasedNum = 0;
|
|
|
+ if (purchaseLimit != null) {
|
|
|
+ purchasedNum = purchaseLimit.getNum();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否超过限购数量
|
|
|
+ if (purchasedNum + num > product.getPurchaseLimit()) {
|
|
|
+ int productTotalNum = purchasedNum + num;
|
|
|
+ throw new CustomException("该商品限购" + product.getPurchaseLimit() + "件,您已购买" + productTotalNum + "件,无法继续购买");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除限购记录(用于直播订单)
|
|
|
+ * @param liveOrder 订单
|
|
|
+ */
|
|
|
+ private void deletePurchaseLimitRecordsForLiveOrder(LiveOrder liveOrder) {
|
|
|
+ // 减少限购数量
|
|
|
+ Long userId = Long.parseLong(liveOrder.getUserId());
|
|
|
+ Integer num = Integer.parseInt(liveOrder.getTotalNum());
|
|
|
+ purchaseLimitService.decreasePurchaseLimit(liveOrder.getProductId(), userId, num);
|
|
|
+ }
|
|
|
+
|
|
|
private void refundCoupon(LiveOrder order) {
|
|
|
if(order.getCouponUserId()!=null){
|
|
|
LiveCouponUser couponUser=liveCouponUserService.selectLiveCouponUserById(order.getUserCouponId());
|