From 5a85d2418dc455984bcb4919786a1567c4c095fe Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 1 Aug 2025 17:41:58 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/pc/impl/OrderServiceImpl.java | 226 +++++++++++------- 1 file changed, 138 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java index d0662d2..312a460 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java @@ -56,6 +56,8 @@ import com.ycwl.basic.utils.SnowFlakeUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -76,10 +78,14 @@ import java.util.stream.Collectors; */ @Slf4j @Service +@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public class OrderServiceImpl implements OrderService { @Autowired private OrderMapper orderMapper; + + @Autowired + private OrderServiceImpl self; @Autowired private SourceMapper sourceMapper; @Autowired @@ -493,110 +499,154 @@ public class OrderServiceImpl implements OrderService { } @Override - @Transactional(rollbackFor = Exception.class) public ApiResponse> createOrder(Long userId, CreateOrderReqVO createOrderReqVO) throws Exception { - IsBuyRespVO isBuy = orderBiz.isBuy(userId, createOrderReqVO.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); - if (isBuy.isBuy()) { - return ApiResponse.fail("您已购买此内容,无需重复购买!"); - } - // 看看有没有之前购买的订单 - OrderEntity order = orderMapper.getUserOrderItem(userId, createOrderReqVO.getScenicId(), 0, null, createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); - boolean haveOldOrder = order != null; - if (order != null) { - if (order.getStatus() != OrderStateEnum.PAID.getState() && order.getStatus() != OrderStateEnum.UNPAID.getState()) { - haveOldOrder = false; - } - if (!DateUtil.isSameDay(order.getCreateAt(), new Date())) { - haveOldOrder = false; - } - } - if (!haveOldOrder) { - order = new OrderEntity(); - order.setId(SnowFlakeUtil.getLongId()); - order.setMemberId(userId); - MemberRespVO member = memberMapper.getById(userId); - order.setOpenId(member.getOpenId()); - order.setScenicId(createOrderReqVO.getScenicId()); + // 防重复提交检查:基于用户ID、景区ID、商品类型、商品ID生成唯一键 + String orderKey = String.format("createOrder:%d:%d:%d:%d", + userId, createOrderReqVO.getScenicId(), + createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); - PriceObj priceObj = orderBiz.queryPrice(order.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); - order.setSlashPrice(priceObj.getSlashPrice()); - order.setPrice(priceObj.getPrice()); - // 判断是否是本人数据 - FaceEntity goodsFace = faceRepository.getFace(priceObj.getFaceId()); - if (goodsFace != null && !goodsFace.getMemberId().equals(userId)) { - return ApiResponse.fail("您无权购买此内容!"); + // 使用synchronized确保同一用户对同一商品的订单创建操作串行化 + synchronized (orderKey.intern()) { + IsBuyRespVO isBuy = orderBiz.isBuy(userId, createOrderReqVO.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); + if (isBuy.isBuy()) { + return ApiResponse.fail("您已购买此内容,无需重复购买!"); } - // promo code - order.setPayPrice(priceObj.getPrice()); - order.setFaceId(priceObj.getFaceId()); - if (order.getPayPrice().equals(BigDecimal.ZERO)) { - order.setStatus(OrderStateEnum.PAID.getState()); - order.setPayAt(new Date()); - } else { - order.setStatus(OrderStateEnum.UNPAID.getState()); + // 看看有没有之前购买的订单 + OrderEntity order = orderMapper.getUserOrderItem(userId, createOrderReqVO.getScenicId(), 0, null, createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); + boolean haveOldOrder = false; + if (order != null) { + // 如果订单已支付,直接返回错误,不允许重复购买 + if (order.getStatus() == OrderStateEnum.PAID.getState()) { + return ApiResponse.fail("您已购买此内容,无需重复购买!"); + } + // 只有未支付的订单才允许复用 + if (order.getStatus() == OrderStateEnum.UNPAID.getState() + && DateUtil.isSameDay(order.getCreateAt(), new Date())) { + haveOldOrder = true; + } } - } - // coupon - CouponRecordQueryResp couponRecord = null; - switch (createOrderReqVO.getGoodsType()) { - case 0: // vlog - VideoEntity video = videoRepository.getVideo(createOrderReqVO.getGoodsId()); - TaskEntity taskById = videoTaskRepository.getTaskById(video.getTaskId()); - if (taskById != null) { - couponRecord = couponBiz.queryUserCouponRecord(order.getScenicId(), userId, order.getFaceId(), taskById.getTemplateId().toString()); + if (!haveOldOrder) { + order = new OrderEntity(); + order.setId(SnowFlakeUtil.getLongId()); + order.setMemberId(userId); + MemberRespVO member = memberMapper.getById(userId); + order.setOpenId(member.getOpenId()); + order.setScenicId(createOrderReqVO.getScenicId()); + + PriceObj priceObj = orderBiz.queryPrice(order.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); + order.setSlashPrice(priceObj.getSlashPrice()); + order.setPrice(priceObj.getPrice()); + // 判断是否是本人数据 + FaceEntity goodsFace = faceRepository.getFace(priceObj.getFaceId()); + if (goodsFace != null && !goodsFace.getMemberId().equals(userId)) { + return ApiResponse.fail("您无权购买此内容!"); } - break; - case 1: - case 2: - couponRecord = couponBiz.queryUserCouponRecord(order.getScenicId(), userId, order.getFaceId(), String.valueOf(createOrderReqVO.getGoodsType())); - break; - } - order.setCouponPrice(BigDecimal.ZERO); - order.setCouponRecordId(null); - order.setCouponId(null); - if (couponRecord != null) { - if (couponRecord.isUsable()) { - log.info("优惠券可用,优惠券记录ID:{},优惠券ID:{}", couponRecord.getId(), couponRecord.getCouponId()); - order.setCouponId(couponRecord.getCouponId()); - order.setCouponRecordId(couponRecord.getId()); - order.setCouponPrice(couponRecord.getCoupon().calculateDiscountPrice(order.getPrice())); - order.setPayPrice(order.getPayPrice().subtract(order.getCouponPrice())); - if (order.getPayPrice().compareTo(BigDecimal.ZERO) < NumberConstant.ZERO) { - // 至少需要支付0.01 - order.setPayPrice(BigDecimal.valueOf(0.01)); + // promo code + order.setPayPrice(priceObj.getPrice()); + order.setFaceId(priceObj.getFaceId()); + if (order.getPayPrice().equals(BigDecimal.ZERO)) { + order.setStatus(OrderStateEnum.PAID.getState()); + order.setPayAt(new Date()); + } else { + order.setStatus(OrderStateEnum.UNPAID.getState()); + } + } + + // 只有新订单才计算优惠券,避免重复处理 + if (!haveOldOrder) { + // coupon + CouponRecordQueryResp couponRecord = null; + switch (createOrderReqVO.getGoodsType()) { + case 0: // vlog + VideoEntity video = videoRepository.getVideo(createOrderReqVO.getGoodsId()); + TaskEntity taskById = videoTaskRepository.getTaskById(video.getTaskId()); + if (taskById != null) { + couponRecord = couponBiz.queryUserCouponRecord(order.getScenicId(), userId, order.getFaceId(), taskById.getTemplateId().toString()); + } + break; + case 1: + case 2: + couponRecord = couponBiz.queryUserCouponRecord(order.getScenicId(), userId, order.getFaceId(), String.valueOf(createOrderReqVO.getGoodsType())); + break; } - } else { - log.info("优惠券不可用,优惠券记录ID:{},优惠券ID:{}", couponRecord.getId(), couponRecord.getCouponId()); - order.setCouponId(null); - order.setCouponRecordId(null); order.setCouponPrice(BigDecimal.ZERO); + order.setCouponRecordId(null); + order.setCouponId(null); + if (couponRecord != null) { + if (couponRecord.isUsable()) { + log.info("优惠券可用,优惠券记录ID:{},优惠券ID:{}", couponRecord.getId(), couponRecord.getCouponId()); + order.setCouponId(couponRecord.getCouponId()); + order.setCouponRecordId(couponRecord.getId()); + order.setCouponPrice(couponRecord.getCoupon().calculateDiscountPrice(order.getPrice())); + order.setPayPrice(order.getPayPrice().subtract(order.getCouponPrice())); + if (order.getPayPrice().compareTo(BigDecimal.ZERO) < NumberConstant.ZERO) { + // 至少需要支付0.01 + order.setPayPrice(BigDecimal.valueOf(0.01)); + } + } else { + log.info("优惠券不可用,优惠券记录ID:{},优惠券ID:{}", couponRecord.getId(), couponRecord.getCouponId()); + order.setCouponId(null); + order.setCouponRecordId(null); + order.setCouponPrice(BigDecimal.ZERO); + } + } } - } - List orderItems = new ArrayList<>(); - OrderItemEntity orderItem = new OrderItemEntity(); - orderItem.setGoodsId(createOrderReqVO.getGoodsId()); - orderItem.setGoodsType(createOrderReqVO.getGoodsType()); - orderItem.setOrderId(order.getId()); - orderItems.add(orderItem); + List orderItems = new ArrayList<>(); + OrderItemEntity orderItem = new OrderItemEntity(); + orderItem.setGoodsId(createOrderReqVO.getGoodsId()); + orderItem.setGoodsType(createOrderReqVO.getGoodsType()); + orderItem.setOrderId(order.getId()); + orderItems.add(orderItem); + // 在事务中保存订单数据 + try { + self.saveOrderInTransaction(order, orderItems, haveOldOrder); + } catch (Exception e) { + log.error("保存订单失败", e); + return ApiResponse.fail("订单创建失败"); + } + + // 判断是否需要支付(事务外处理) + if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) { + // 只有新创建的订单才需要执行支付完成逻辑 + if (!haveOldOrder) { + try { + orderBiz.paidOrder(order.getId()); + } catch (Exception e) { + log.error("处理免费订单失败", e); + return ApiResponse.fail("订单处理失败"); + } + } + HashMap data = new HashMap<>(); + data.put("needPay", false); + return ApiResponse.success(data); + } else { + // 发起支付(事务外调用外部服务) + try { + Map wxPayRespVO = initiatePayment(order, orderItems); + return ApiResponse.success(wxPayRespVO); + } catch (Exception e) { + log.error("发起支付失败", e); + return ApiResponse.fail("支付发起失败,请重试"); + } + } + } // synchronized 块结束 + } + + /** + * 在事务中保存订单数据 + */ + @Transactional(rollbackFor = Exception.class) + protected void saveOrderInTransaction(OrderEntity order, List orderItems, boolean haveOldOrder) { if (!haveOldOrder) { orderMapper.add(order); int addOrderItems = orderMapper.addOrderItems(orderItems); if (addOrderItems == NumberConstant.ZERO) { - log.error("订单明细添加失败"); - return ApiResponse.fail("订单添加失败"); + throw new RuntimeException("订单明细添加失败"); } } else { + // 对于旧订单,只更新价格相关字段,不重复处理业务逻辑 orderMapper.updateOrderPrice(order); } - if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) { - orderBiz.paidOrder(order.getId()); - HashMap data = new HashMap<>(); - data.put("needPay", false); - return ApiResponse.success(data); - } else { - Map wxPayRespVO = initiatePayment(order, orderItems); - return ApiResponse.success(wxPayRespVO); - } } @Override