|
|
@@ -3,14 +3,16 @@ package com.izouma.nineth.service;
|
|
|
import com.alibaba.excel.util.StringUtils;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.google.zxing.WriterException;
|
|
|
+import com.izouma.nineth.config.GeneralProperties;
|
|
|
+import com.izouma.nineth.config.RedisKeys;
|
|
|
+import com.izouma.nineth.domain.Asset;
|
|
|
import com.izouma.nineth.domain.DomainOrder;
|
|
|
import com.izouma.nineth.domain.FileObject;
|
|
|
import com.izouma.nineth.domain.User;
|
|
|
import com.izouma.nineth.dto.PageQuery;
|
|
|
import com.izouma.nineth.dto.excel.DomainCountDTO;
|
|
|
-import com.izouma.nineth.enums.CollectionStatus;
|
|
|
-import com.izouma.nineth.enums.OrderStatus;
|
|
|
-import com.izouma.nineth.enums.PayMethod;
|
|
|
+import com.izouma.nineth.enums.*;
|
|
|
+import com.izouma.nineth.event.OrderNotifyEvent;
|
|
|
import com.izouma.nineth.exception.BusinessException;
|
|
|
import com.izouma.nineth.repo.AssetRepo;
|
|
|
import com.izouma.nineth.repo.DomainOrderRepo;
|
|
|
@@ -19,16 +21,20 @@ import com.izouma.nineth.service.storage.StorageService;
|
|
|
import com.izouma.nineth.utils.ImageUtils;
|
|
|
import com.izouma.nineth.utils.JpaUtils;
|
|
|
import com.izouma.nineth.utils.SecurityUtils;
|
|
|
+import com.sun.xml.bind.v2.TODO;
|
|
|
import lombok.AllArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.lang3.RandomStringUtils;
|
|
|
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
|
|
import org.springframework.cache.annotation.Cacheable;
|
|
|
import org.springframework.data.annotation.Transient;
|
|
|
import org.springframework.data.domain.Page;
|
|
|
import org.springframework.data.domain.PageRequest;
|
|
|
import org.springframework.data.domain.Pageable;
|
|
|
import org.springframework.data.domain.Sort;
|
|
|
+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;
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
@@ -43,6 +49,7 @@ import java.text.SimpleDateFormat;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.util.*;
|
|
|
import java.util.List;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.regex.Pattern;
|
|
|
@@ -62,6 +69,9 @@ public class DomainOrderService {
|
|
|
private AssetRepo assetRepo;
|
|
|
private RedisTemplate<String, Object> redisTemplate;
|
|
|
private CacheService cacheService;
|
|
|
+ private UserBalanceService userBalanceService;
|
|
|
+ private GeneralProperties generalProperties;
|
|
|
+ private RocketMQTemplate rocketMQTemplate;
|
|
|
|
|
|
public Page<DomainOrder> all(PageQuery pageQuery) {
|
|
|
return domainOrderRepo
|
|
|
@@ -298,6 +308,13 @@ public class DomainOrderService {
|
|
|
|
|
|
@Transient
|
|
|
public void notify(Long id, PayMethod payMethod, String transactionId) throws FontFormatException, IOException, WriterException {
|
|
|
+ // 取消订单与订单回调不能同时进行,需要抢锁
|
|
|
+ if (!getOrderLock(id)) {
|
|
|
+ log.info("订单回调失败 orderId: {} redis锁定, 重新发送到队列", id);
|
|
|
+ rocketMQTemplate.syncSend(generalProperties.getOrderNotifyTopic(),
|
|
|
+ new OrderNotifyEvent(id, payMethod, transactionId, System.currentTimeMillis()));
|
|
|
+ return;
|
|
|
+ }
|
|
|
DomainOrder domainOrder = domainOrderRepo.findById(id).orElseThrow(new BusinessException("未找到星图"));
|
|
|
if (!domainOrder.getOrderStatus().equals(OrderStatus.NOT_PAID)) {
|
|
|
throw new BusinessException("订单已经处理");
|
|
|
@@ -317,21 +334,30 @@ public class DomainOrderService {
|
|
|
domainOrder.setPayMethod(payMethod);
|
|
|
domainOrder.setPic(Collections.singletonList(fileObject));
|
|
|
domainOrder.setTransactionId(transactionId);
|
|
|
- domainOrder.setStatus(CollectionStatus.SUCCESS);
|
|
|
+// domainOrder.setStatus(CollectionStatus.SUCCESS);
|
|
|
domainOrder.setCreateAssetId(createAsset(domainOrder));
|
|
|
domainOrder.setEndTime(LocalDateTime.now().plusYears(domainOrder.getYears()));
|
|
|
domainOrderRepo.save(domainOrder);
|
|
|
|
|
|
rockRecordService.addRock(domainOrder.getUserId(), domainOrder.getPrice(), "购买");
|
|
|
+
|
|
|
+ releaseOrderLock(id);
|
|
|
}
|
|
|
|
|
|
public void cancel(DomainOrder domainOrder) {
|
|
|
+ log.info("尝试取消订单 {}", domainOrder.getId());
|
|
|
+ // 取消订单与订单回调不能同时进行,需要抢锁
|
|
|
+ if (!getOrderLock(domainOrder.getId())) {
|
|
|
+ log.error("订单取消失败 {}, redis锁了", domainOrder.getId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
domainOrder.setOrderStatus(OrderStatus.CANCELLED);
|
|
|
domainOrder.setStatus(CollectionStatus.FAIL);
|
|
|
if (domainOrder.getPicName().length() < 5) {
|
|
|
decreaseCount(domainOrder);
|
|
|
}
|
|
|
domainOrderRepo.save(domainOrder);
|
|
|
+ releaseOrderLock(domainOrder.getId());
|
|
|
}
|
|
|
|
|
|
public Long createAsset(DomainOrder domainOrder) {
|
|
|
@@ -464,4 +490,57 @@ public class DomainOrderService {
|
|
|
return jsonArray.toJavaList(DomainCountDTO.class);
|
|
|
}
|
|
|
|
|
|
+ // 获取订单锁,有效时间1小时
|
|
|
+ public boolean getOrderLock(Long orderId) {
|
|
|
+ BoundValueOperations<String, Object> ops = redisTemplate.boundValueOps(RedisKeys.DOMAIN_LOCK + orderId);
|
|
|
+ Boolean flag = ops.setIfAbsent(1, 1, TimeUnit.HOURS);
|
|
|
+ return Boolean.TRUE.equals(flag);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 释放订单锁
|
|
|
+ public void releaseOrderLock(Long orderId) {
|
|
|
+ redisTemplate.delete(RedisKeys.DOMAIN_LOCK + orderId);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void pass(Long id) {
|
|
|
+ domainOrderRepo.findById(id).ifPresent(domainOrder -> {
|
|
|
+ domainOrder.setStatus(CollectionStatus.SUCCESS);
|
|
|
+ assetRepo.findById(domainOrder.getCreateAssetId()).ifPresent(asset1 -> {
|
|
|
+ asset1.setStatus(AssetStatus.NORMAL);
|
|
|
+ domainOrderRepo.save(domainOrder);
|
|
|
+ assetRepo.save(asset1);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void deny(Long id, String result) {
|
|
|
+ domainOrderRepo.findById(id).ifPresent(domainOrder -> {
|
|
|
+ domainOrder.setStatus(CollectionStatus.FAIL);
|
|
|
+ domainOrder.setOrderStatus(OrderStatus.CANCELLED);
|
|
|
+ domainOrder.setResult(result);
|
|
|
+ assetRepo.findById(domainOrder.getCreateAssetId()).ifPresent(asset1 -> {
|
|
|
+ asset1.setStatus(AssetStatus.DESTROYED);
|
|
|
+ domainOrderRepo.save(domainOrder);
|
|
|
+ assetRepo.save(asset1);
|
|
|
+ });
|
|
|
+ //退款
|
|
|
+ userBalanceService.addBalance(domainOrder.getUserId(), domainOrder.getPrice(), domainOrder
|
|
|
+ .getId(), BalanceType.REFUND);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Scheduled(cron = "0 0/60 9-20 * * ?")
|
|
|
+ public void batchPass() {
|
|
|
+ LocalDateTime lastTime = LocalDateTime.now().minusHours(72L);
|
|
|
+ List<DomainOrder> domainOrders = domainOrderRepo
|
|
|
+ .findAllByStatusAndCreatedAtBeforeAndOrderStatus(CollectionStatus.PENDING, lastTime, OrderStatus.FINISH);
|
|
|
+ domainOrders.forEach(domainOrder -> {
|
|
|
+ try {
|
|
|
+ pass(domainOrder.getId());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.info("自动通过出错" + domainOrder.getDomainName());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
}
|