You've already forked FrameTour-BE
订单支付
This commit is contained in:
@@ -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<Map<String, Object>> 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<OrderItemEntity> orderItems = new ArrayList<>();
|
||||
OrderItemEntity orderItem = new OrderItemEntity();
|
||||
orderItem.setGoodsId(createOrderReqVO.getGoodsId());
|
||||
orderItem.setGoodsType(createOrderReqVO.getGoodsType());
|
||||
orderItem.setOrderId(order.getId());
|
||||
orderItems.add(orderItem);
|
||||
List<OrderItemEntity> 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<String, Object> data = new HashMap<>();
|
||||
data.put("needPay", false);
|
||||
return ApiResponse.success(data);
|
||||
} else {
|
||||
// 发起支付(事务外调用外部服务)
|
||||
try {
|
||||
Map<String, Object> 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<OrderItemEntity> 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<String, Object> data = new HashMap<>();
|
||||
data.put("needPay", false);
|
||||
return ApiResponse.success(data);
|
||||
} else {
|
||||
Map<String, Object> wxPayRespVO = initiatePayment(order, orderItems);
|
||||
return ApiResponse.success(wxPayRespVO);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user