package com.tourguide.modules.order.service;
|
|
import com.tourguide.common.exception.BusinessException;
|
import com.tourguide.common.huifu.RequestSeqUtil;
|
import com.tourguide.modules.order.domain.OrderStatus;
|
import com.tourguide.modules.order.domain.PaymentMethod;
|
import com.tourguide.modules.order.entity.TourOrder;
|
import com.tourguide.modules.order.entity.TourOrderPaymentAttempt;
|
import com.tourguide.modules.order.mapper.TourOrderMapper;
|
import com.tourguide.modules.order.mapper.TourOrderPaymentAttemptMapper;
|
import com.tourguide.modules.order.payment.HuifuPaymentNotice;
|
import com.tourguide.modules.order.payment.OrderPaymentPreparation;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
|
@Service
|
public class TourOrderPaymentService {
|
private static final DateTimeFormatter REQUEST_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
|
private static final String ATTEMPT_CREATED = "CREATED";
|
private static final String ATTEMPT_SUCCEEDED = "SUCCEEDED";
|
|
private final TourOrderMapper orderMapper;
|
private final TourOrderPaymentAttemptMapper paymentAttemptMapper;
|
private final GuideOrderMatchingService matchingService;
|
|
public TourOrderPaymentService(TourOrderMapper orderMapper,
|
TourOrderPaymentAttemptMapper paymentAttemptMapper,
|
GuideOrderMatchingService matchingService) {
|
this.orderMapper = orderMapper;
|
this.paymentAttemptMapper = paymentAttemptMapper;
|
this.matchingService = matchingService;
|
}
|
|
@Transactional
|
public OrderPaymentPreparation prepare(Long visitorId, Long orderId) {
|
TourOrder order = orderMapper.selectForUpdate(orderId);
|
if (order == null || visitorId == null || !visitorId.equals(order.getVisitorId())) {
|
throw new BusinessException(404, "订单不存在");
|
}
|
if (!OrderStatus.PENDING_PAYMENT.matches(order.getStatus())) {
|
throw new BusinessException(409, "当前订单状态不支持支付");
|
}
|
|
LocalDateTime now = LocalDateTime.now();
|
String reqDate = now.format(REQUEST_DATE_FORMAT);
|
String reqSeqId = RequestSeqUtil.generateForBusiness("PY");
|
TourOrderPaymentAttempt attempt = new TourOrderPaymentAttempt();
|
attempt.setOrderId(order.getId());
|
attempt.setReqSeqId(reqSeqId);
|
attempt.setReqDate(reqDate);
|
attempt.setAmount(order.getAmount());
|
attempt.setStatus(ATTEMPT_CREATED);
|
paymentAttemptMapper.insert(attempt);
|
|
order.setPaymentMethod(PaymentMethod.WECHAT.getCode());
|
order.setPaymentOrderNo(reqSeqId);
|
orderMapper.updateById(order);
|
|
String goodsDescription = StringUtils.hasText(order.getPackageName())
|
? order.getScenicName() + "-" + order.getPackageName()
|
: order.getScenicName() + "-讲解服务";
|
return new OrderPaymentPreparation(order.getId(), reqSeqId, reqDate,
|
order.getAmount(), goodsDescription);
|
}
|
|
@Transactional
|
public boolean confirm(HuifuPaymentNotice notice) {
|
TourOrderPaymentAttempt attempt = paymentAttemptMapper.selectByReqSeqIdForUpdate(notice.getReqSeqId());
|
if (attempt == null) throw new BusinessException(404, "支付流水不存在");
|
TourOrder order = orderMapper.selectForUpdate(attempt.getOrderId());
|
if (order == null) throw new BusinessException(404, "支付订单不存在");
|
validateAmount(attempt.getAmount(), notice.getAmount());
|
validateAmount(order.getAmount(), notice.getAmount());
|
if (ATTEMPT_SUCCEEDED.equals(attempt.getStatus())) {
|
return false;
|
}
|
|
LocalDateTime paidAt = notice.getPaidAt() == null ? LocalDateTime.now() : notice.getPaidAt();
|
attempt.setStatus(ATTEMPT_SUCCEEDED);
|
attempt.setProviderTransactionId(notice.getProviderTransactionId());
|
attempt.setPaidAt(paidAt);
|
paymentAttemptMapper.updateById(attempt);
|
|
if (order.getPaymentTime() != null && !OrderStatus.PENDING_PAYMENT.matches(order.getStatus())) {
|
return false;
|
}
|
if (!OrderStatus.PENDING_PAYMENT.matches(order.getStatus())) {
|
throw new BusinessException(409, "订单状态不允许确认支付");
|
}
|
order.setPaymentMethod(PaymentMethod.WECHAT.getCode());
|
order.setPaymentOrderNo(notice.getReqSeqId());
|
order.setPaymentAmount(notice.getAmount());
|
order.setPaymentTime(paidAt);
|
order.setStatus(OrderStatus.PENDING_ACCEPT.getCode());
|
orderMapper.updateById(order);
|
matchingService.match(order.getId());
|
return true;
|
}
|
|
private void validateAmount(BigDecimal expectedAmount, BigDecimal paidAmount) {
|
if (expectedAmount == null || paidAmount == null || expectedAmount.compareTo(paidAmount) != 0) {
|
throw new BusinessException(409, "支付金额与订单金额不一致");
|
}
|
}
|
}
|