|
|
@@ -46,6 +46,7 @@ import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
|
|
import org.springframework.context.event.EventListener;
|
|
|
import org.springframework.core.env.Environment;
|
|
|
import org.springframework.data.domain.Page;
|
|
|
+import org.springframework.data.redis.core.BoundValueOperations;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
@@ -57,6 +58,7 @@ import java.math.RoundingMode;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
@Service
|
|
|
@AllArgsConstructor
|
|
|
@@ -85,6 +87,7 @@ public class OrderService {
|
|
|
private RedisTemplate<String, Object> redisTemplate;
|
|
|
private SnowflakeIdWorker snowflakeIdWorker;
|
|
|
private SmsService smsService;
|
|
|
+ private ErrorOrderRepo errorOrderRepo;
|
|
|
|
|
|
public Page<Order> all(PageQuery pageQuery) {
|
|
|
return orderRepo.findAll(JpaUtils.toSpecification(pageQuery, Order.class), JpaUtils.toPageRequest(pageQuery));
|
|
|
@@ -471,68 +474,99 @@ public class OrderService {
|
|
|
@Transactional
|
|
|
public void notifyOrder(Long orderId, PayMethod payMethod, String transactionId) {
|
|
|
log.info("订单回调 orderId: {}, payMethod: {}, transactionId: {}", orderId, payMethod, transactionId);
|
|
|
- Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
|
|
|
- Collection collection = collectionRepo.findById(order.getCollectionId())
|
|
|
- .orElseThrow(new BusinessException("藏品不存在"));
|
|
|
- User user = userRepo.findById(order.getUserId()).orElseThrow(new BusinessException("用户不存在"));
|
|
|
- if (order.getStatus() == OrderStatus.NOT_PAID) {
|
|
|
- order.setStatus(OrderStatus.PROCESSING);
|
|
|
- order.setPayTime(LocalDateTime.now());
|
|
|
- order.setTransactionId(transactionId);
|
|
|
- order.setPayMethod(payMethod);
|
|
|
- if (order.getType() == CollectionType.BLIND_BOX) {
|
|
|
- log.info("开始盲盒抽卡 orderId: {}, collectionId: {}", orderId, collection.getId());
|
|
|
- BlindBoxItem winItem = null;
|
|
|
- try {
|
|
|
- winItem = collectionService.draw(collection.getId());
|
|
|
- } catch (BusinessException e) {
|
|
|
- }
|
|
|
- if (winItem == null) {
|
|
|
- log.info("抽卡失败退款 orderId: {}", orderId);
|
|
|
- order.setStatus(OrderStatus.CANCELLED);
|
|
|
- order.setCancelTime(LocalDateTime.now());
|
|
|
-
|
|
|
- Map<String, Object> refundParams = new HashMap<>();
|
|
|
- refundParams.put("refund_amt", order.getTotalPrice().setScale(2, RoundingMode.HALF_UP)
|
|
|
- .toPlainString());
|
|
|
- refundParams.put("refund_order_no", String.valueOf(snowflakeIdWorker.nextId()));
|
|
|
+ BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps("orderLock::" + orderId);
|
|
|
+ Boolean flag = ops.setIfAbsent(1, 1, TimeUnit.DAYS);
|
|
|
+ if (!Boolean.TRUE.equals(flag)) {
|
|
|
+ log.info("订单回调失败 orderId: {} redis锁定", orderId);
|
|
|
+ errorOrderRepo.save(ErrorOrder.builder()
|
|
|
+ .orderId(orderId)
|
|
|
+ .transactionId(transactionId)
|
|
|
+ .payMethod(payMethod)
|
|
|
+ .errorMessage("redis锁定")
|
|
|
+ .build());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ Order order = orderRepo.findById(orderId).orElseThrow(new BusinessException("订单不存在"));
|
|
|
+ Collection collection = collectionRepo.findById(order.getCollectionId())
|
|
|
+ .orElseThrow(new BusinessException("藏品不存在"));
|
|
|
+ User user = userRepo.findById(order.getUserId()).orElseThrow(new BusinessException("用户不存在"));
|
|
|
+ if (order.getStatus() == OrderStatus.NOT_PAID) {
|
|
|
+ order.setStatus(OrderStatus.PROCESSING);
|
|
|
+ order.setPayTime(LocalDateTime.now());
|
|
|
+ order.setTransactionId(transactionId);
|
|
|
+ order.setPayMethod(payMethod);
|
|
|
+ if (order.getType() == CollectionType.BLIND_BOX) {
|
|
|
+ log.info("开始盲盒抽卡 orderId: {}, collectionId: {}", orderId, collection.getId());
|
|
|
+ BlindBoxItem winItem = null;
|
|
|
try {
|
|
|
- Map<String, Object> response = Refund.create(transactionId, refundParams);
|
|
|
- } catch (BaseAdaPayException e) {
|
|
|
- e.printStackTrace();
|
|
|
+ winItem = collectionService.draw(collection.getId());
|
|
|
+ } catch (BusinessException e) {
|
|
|
}
|
|
|
- orderRepo.save(order);
|
|
|
- return;
|
|
|
- }
|
|
|
- log.info("抽卡成功 orderId: {}, collectionId: {}, winCollectionId: {}", orderId, collection.getId(), winItem.getCollectionId());
|
|
|
- order.setWinCollectionId(winItem.getCollectionId());
|
|
|
- orderRepo.save(order);
|
|
|
- assetService.createAsset(winItem, user, order.getId(), order.getPrice(), "出售",
|
|
|
- winItem.getTotal() > 1 ? collectionService.getNextNumber(winItem.getCollectionId()) : null);
|
|
|
- } else {
|
|
|
- if (collection.getSource() == CollectionSource.TRANSFER) {
|
|
|
- Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
|
|
|
- assetService.transfer(asset, order.getPrice(), user, "转让", order.getId());
|
|
|
- collectionRepo.delete(collection);
|
|
|
-
|
|
|
- // 发送短信提醒用户转让成功
|
|
|
- if (asset != null && asset.getUserId() != null) {
|
|
|
- smsService.sellOut(userRepo.findPhoneById(asset.getUserId()));
|
|
|
+ if (winItem == null) {
|
|
|
+ log.info("抽卡失败退款 orderId: {}", orderId);
|
|
|
+ order.setStatus(OrderStatus.CANCELLED);
|
|
|
+ order.setCancelTime(LocalDateTime.now());
|
|
|
+
|
|
|
+ Map<String, Object> refundParams = new HashMap<>();
|
|
|
+ refundParams.put("refund_amt", order.getTotalPrice().setScale(2, RoundingMode.HALF_UP)
|
|
|
+ .toPlainString());
|
|
|
+ refundParams.put("refund_order_no", String.valueOf(snowflakeIdWorker.nextId()));
|
|
|
+ try {
|
|
|
+ Map<String, Object> response = Refund.create(transactionId, refundParams);
|
|
|
+ } catch (BaseAdaPayException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ orderRepo.save(order);
|
|
|
+ return;
|
|
|
}
|
|
|
-
|
|
|
- } else {
|
|
|
+ log.info("抽卡成功 orderId: {}, collectionId: {}, winCollectionId: {}", orderId, collection.getId(), winItem.getCollectionId());
|
|
|
+ order.setWinCollectionId(winItem.getCollectionId());
|
|
|
orderRepo.save(order);
|
|
|
- assetService.createAsset(collection, user, order.getId(), order.getPrice(), "出售",
|
|
|
- collection.getTotal() > 1 ? collectionService.getNextNumber(order.getCollectionId()) : null);
|
|
|
+ assetService.createAsset(winItem, user, order.getId(), order.getPrice(), "出售",
|
|
|
+ winItem.getTotal() > 1 ? collectionService.getNextNumber(winItem.getCollectionId()) : null);
|
|
|
+ } else {
|
|
|
+ if (collection.getSource() == CollectionSource.TRANSFER) {
|
|
|
+ Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
|
|
|
+ assetService.transfer(asset, order.getPrice(), user, "转让", order.getId());
|
|
|
+ collectionRepo.delete(collection);
|
|
|
+
|
|
|
+ // 发送短信提醒用户转让成功
|
|
|
+ if (asset != null && asset.getUserId() != null) {
|
|
|
+ smsService.sellOut(userRepo.findPhoneById(asset.getUserId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ orderRepo.save(order);
|
|
|
+ assetService.createAsset(collection, user, order.getId(), order.getPrice(), "出售",
|
|
|
+ collection.getTotal() > 1 ? collectionService.getNextNumber(order.getCollectionId()) : null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ commission(order);
|
|
|
+ if (collection.getAssetId() == null) {
|
|
|
+ collectionService.increaseSale(order.getCollectionId(), order.getQty());
|
|
|
}
|
|
|
+ } else {
|
|
|
+ throw new BusinessException("状态错误 " + order.getStatus());
|
|
|
}
|
|
|
- commission(order);
|
|
|
- if (collection.getAssetId() == null) {
|
|
|
- collectionService.increaseSale(order.getCollectionId(), order.getQty());
|
|
|
+ } catch (Exception e) {
|
|
|
+ ErrorOrder errorOrder = ErrorOrder.builder()
|
|
|
+ .orderId(orderId)
|
|
|
+ .transactionId(transactionId)
|
|
|
+ .payMethod(payMethod)
|
|
|
+ .build();
|
|
|
+ if (e instanceof BusinessException) {
|
|
|
+ log.error("订单回调出错 orderId: {} {}", orderId, ((BusinessException) e).getError());
|
|
|
+ errorOrder.setErrorMessage(((BusinessException) e).getError());
|
|
|
+ } else {
|
|
|
+ log.error("订单回调出错 orderId: " + orderId, e);
|
|
|
+ errorOrder.setErrorMessage(e.getMessage());
|
|
|
}
|
|
|
- } else {
|
|
|
- log.info("订单回调状态错误 {} {}", orderId, order.getStatus());
|
|
|
+ errorOrderRepo.save(errorOrder);
|
|
|
+
|
|
|
}
|
|
|
+ redisTemplate.delete("orderLock::" + orderId);
|
|
|
}
|
|
|
|
|
|
@EventListener
|
|
|
@@ -571,56 +605,48 @@ public class OrderService {
|
|
|
}
|
|
|
|
|
|
public void cancel(Order order) {
|
|
|
- if (order.getStatus() != OrderStatus.NOT_PAID) {
|
|
|
- throw new BusinessException("已支付订单无法取消");
|
|
|
+ BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps("orderLock::" + order.getId());
|
|
|
+ Boolean flag = ops.setIfAbsent(1, 1, TimeUnit.DAYS);
|
|
|
+ if (!Boolean.TRUE.equals(flag)) {
|
|
|
+ log.error("订单取消失败 {}, redis锁了", order.getId());
|
|
|
+ return;
|
|
|
}
|
|
|
+ try {
|
|
|
+ if (order.getStatus() != OrderStatus.NOT_PAID) {
|
|
|
+ throw new BusinessException("已支付订单无法取消");
|
|
|
+ }
|
|
|
|
|
|
- CollectionSource source = Optional.ofNullable(order.getSource()).orElseGet(() ->
|
|
|
- collectionRepo.findById(order.getCollectionId()).map(Collection::getSource).orElse(null));
|
|
|
+ CollectionSource source = Optional.ofNullable(order.getSource()).orElseGet(() ->
|
|
|
+ collectionRepo.findById(order.getCollectionId()).map(Collection::getSource).orElse(null));
|
|
|
|
|
|
- if (source == CollectionSource.TRANSFER) {
|
|
|
- Asset asset = assetRepo.findById(order.getAssetId()).orElse(null);
|
|
|
- if (asset != null) {
|
|
|
- log.info("set normal cancelOrder {}", order.getId());
|
|
|
- asset.setStatus(AssetStatus.NORMAL);
|
|
|
- assetRepo.save(asset);
|
|
|
+ if (source == CollectionSource.TRANSFER) {
|
|
|
+ Asset asset = assetRepo.findById(order.getAssetId()).orElse(null);
|
|
|
+ if (asset != null) {
|
|
|
+ log.info("set normal cancelOrder {}", order.getId());
|
|
|
+ asset.setStatus(AssetStatus.NORMAL);
|
|
|
+ assetRepo.save(asset);
|
|
|
+ }
|
|
|
+ collectionRepo.setOnShelf(order.getCollectionId(), true);
|
|
|
}
|
|
|
- collectionRepo.setOnShelf(order.getCollectionId(), true);
|
|
|
- }
|
|
|
- collectionService.increaseStock(order.getCollectionId(), order.getQty());
|
|
|
+ collectionService.increaseStock(order.getCollectionId(), order.getQty());
|
|
|
|
|
|
- order.setStatus(OrderStatus.CANCELLED);
|
|
|
- order.setCancelTime(LocalDateTime.now());
|
|
|
- orderRepo.save(order);
|
|
|
-
|
|
|
- if (order.getCouponId() != null) {
|
|
|
- userCouponRepo.findById(order.getCouponId()).ifPresent(coupon -> {
|
|
|
- coupon.setUsed(false);
|
|
|
- coupon.setUseTime(null);
|
|
|
- userCouponRepo.save(coupon);
|
|
|
- });
|
|
|
- }
|
|
|
- rocketMQTemplate.syncSend(generalProperties.getUpdateStockTopic(), order.getCollectionId(), 10000);
|
|
|
- log.info("取消订单{}", order.getId());
|
|
|
- }
|
|
|
+ order.setStatus(OrderStatus.CANCELLED);
|
|
|
+ order.setCancelTime(LocalDateTime.now());
|
|
|
+ orderRepo.save(order);
|
|
|
|
|
|
- @Scheduled(fixedRate = 30000)
|
|
|
- public void batchCancel() {
|
|
|
- if (generalProperties.isNotifyServer()) {
|
|
|
- return;
|
|
|
- }
|
|
|
- if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
|
|
|
- return;
|
|
|
- }
|
|
|
- List<Order> orders = orderRepo.findByStatusAndCreatedAtBeforeAndDelFalse(OrderStatus.NOT_PAID,
|
|
|
- LocalDateTime.now().minusSeconds(210));
|
|
|
- orders.parallelStream().forEach(o -> {
|
|
|
- try {
|
|
|
- cancel(o);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("取消订单错误 " + o.getId(), e);
|
|
|
+ if (order.getCouponId() != null) {
|
|
|
+ userCouponRepo.findById(order.getCouponId()).ifPresent(coupon -> {
|
|
|
+ coupon.setUsed(false);
|
|
|
+ coupon.setUseTime(null);
|
|
|
+ userCouponRepo.save(coupon);
|
|
|
+ });
|
|
|
}
|
|
|
- });
|
|
|
+ rocketMQTemplate.syncSend(generalProperties.getUpdateStockTopic(), order.getCollectionId(), 10000);
|
|
|
+ log.info("取消订单{}", order.getId());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("订单取消错误 orderId: " + order.getId(), e);
|
|
|
+ }
|
|
|
+ redisTemplate.delete("orderLock::" + order.getId());
|
|
|
}
|
|
|
|
|
|
public void refundCancelled(Order order) {
|