Browse Source

转账nft的是单独线程了。

skyfffire 1 month ago
parent
commit
df6fa33c0d

+ 4 - 1
src/main/java/common/jfinal/AppConfig.java

@@ -14,8 +14,11 @@ import modules.hello.HelloController;
 import modules.news.NewsController;
 import modules.nftt.NfttController;
 import modules.order.OrderController;
+import modules.order.OrderService;
+import modules.order.OrderStatusMaintenanceTask;
 import modules.upload.UploadController;
 import modules.user.UserController;
+import modules.user.UserService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.util.concurrent.ExecutorService;
@@ -102,7 +105,7 @@ public class AppConfig extends JFinalConfig {
         // me.set("asyncTaskExecutor", asyncTaskExecutor); // 不推荐直接用put,使用自己的全局Manager
         // 更好的方式是创建一个单例的 TaskScheduler
         TaskScheduler.init(asyncTaskExecutor);
-//        TaskScheduler.submit(new OrderStatusMaintenanceTask(new OrderService()));
+        TaskScheduler.submit(new OrderStatusMaintenanceTask(new OrderService(), new UserService()));
     }
 
     @Override

+ 0 - 9
src/main/java/modules/order/OrderController.java

@@ -153,15 +153,6 @@ public class OrderController extends MyController {
             renderJson(MyRet.fail("订单信息错误,再违规请求将封禁ip"));
             return;
         }
-        
-        // 判断订单状态
-        Order order = Order.dao.findById(orderId);
-        if (order.getOrderStatus() == OrderStatus.COMPLETED.code
-                || order.getOrderStatus() == OrderStatus.CANCELED.code
-                || order.getOrderStatus() == OrderStatus.REFUNDED.code) {
-            renderJson(MyRet.fail("无法取消已完成的订单,请刷新后尝试"));
-            return;
-        }
 
         renderJson(service.cancelByUser(user.getId(), orderId));
     }

+ 17 - 138
src/main/java/modules/order/OrderService.java

@@ -2,19 +2,13 @@ package modules.order;
 
 import com.alibaba.fastjson.JSONObject;
 import com.jfinal.aop.Inject;
-import com.jfinal.kit.StrKit;
 import com.jfinal.plugin.activerecord.Db;
 import com.jfinal.plugin.activerecord.Record;
-import common.jfinal.AppConfig;
-import common.model.Nftt;
 import common.model.Order;
 import common.model.OrderLog;
 import common.model.User;
-import common.utils.bsn.BsnSDK;
 import common.utils.http.MyRet;
 import modules.nftt.NfttService;
-import modules.user.UserService;
-import modules.user.UserTeamShareTask;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -23,8 +17,6 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 public class OrderService {
-    @Inject
-    UserService userService;
     @Inject
     NfttService nfttService;
     
@@ -120,7 +112,16 @@ public class OrderService {
         try {
             Db.tx(() -> {
                 // 1. 获取order和nfttId
-                Order order = Order.dao.findById(orderId);
+                String sql = "SELECT * FROM t_order WHERE id=? FOR UPDATE";
+                Order order = Order.dao.findFirst(sql, orderId);
+
+                // 订单状态判断
+                if (order.getOrderStatus() == OrderController.OrderStatus.COMPLETED.code
+                        || order.getOrderStatus() == OrderController.OrderStatus.CANCELED.code
+                        || order.getOrderStatus() == OrderController.OrderStatus.REFUNDED.code) {
+                    throw new RuntimeException("无法取消已完成的订单,请刷新后尝试");
+                }
+                
                 long nfttId = order.getNfttId();
                 
                 // 2. 更新库存(在锁定的行上进行)
@@ -168,8 +169,8 @@ public class OrderService {
     public MyRet findOrderById(long orderId, long userId) {
         List<Order> orderList = Order.dao.find("SELECT * FROM t_order WHERE id=? and user_id=?", orderId, userId);
 
-        // 给用户转账NFT
-        doNftTransfer(userId, orderList);
+//        // 给用户转账NFT
+//        doNftTransfer(userId, orderList);
         
         // 给用户订单封装商品信息
         for (Order order : orderList) {
@@ -189,9 +190,9 @@ public class OrderService {
         String columns = "id, nftt_id, order_status, order_type, delivery_status, delivery_time, nft_mint_status, bsn_transfer_code, bsn_transfer_status";
         String sql = "SELECT " + columns + " FROM t_order WHERE user_id = ? ORDER BY create_time DESC";
         List<Order> allOrderList = Order.dao.find(sql, userId);
-        
-        // 给用户转账NFT
-        doNftTransfer(userId, allOrderList);
+//        
+//        // 给用户转账NFT
+//        doNftTransfer(userId, allOrderList);
 
         // 创建一个新的列表来存储过滤后的订单
         List<Order> filteredOrders = new ArrayList<>();
@@ -236,8 +237,8 @@ public class OrderService {
             return MyRet.ok("查询成功").setData(new ArrayList<Map<String, Object>>());
         }
 
-        // 给用户转账NFT
-        doNftTransfer(userId, allOrderList);
+//        // 给用户转账NFT
+//        doNftTransfer(userId, allOrderList);
         
         // 只需要指定状态的status
         List<Order> filteredOrderList = new ArrayList<>();
@@ -338,128 +339,6 @@ public class OrderService {
 
         return MyRet.ok("查询成功").setData(response);
     }
-
-    private void doNftTransfer(long userId, List<Order> orderList) {
-        User user = User.dao.findById(userId);
-        
-        // 未给用户转账的进行转账
-        for (Order order : orderList) {
-            // 已经交付完成或交付失败就不用看状态了
-            if (order.getOrderStatus() == OrderController.OrderStatus.COMPLETED.code
-                    || order.getOrderStatus() == OrderController.OrderStatus.CANCELED.code
-                    || order.getOrderStatus() == OrderController.OrderStatus.REFUNDED.code) {
-                continue;
-            }
-            
-            // 已经执行过转账的查看是否确权,查看状态
-            if (StrKit.notBlank(order.getBsnTransferCode())) {
-                try {
-                    JSONObject searchResponse = BsnSDK.search(order.getBsnTransferCode());
-
-                    if (searchResponse.getInteger("code") == 0) {
-                        JSONObject data = searchResponse.getJSONObject("data");
-
-                        // status为1时才是交付成功,其它要么是pending要么是交付失败
-                        if (data.getInteger("status") == 1) {
-                            OrderLog log = new OrderLog();
-                            log.set("order_id", order.getId());
-                            log.set("from_status", order.getOrderStatus());
-                            log.set("to_status", OrderController.OrderStatus.COMPLETED.code);
-                            log.set("operator_id", userId);
-                            log.set("operator_type", 3);
-                            log.set("change_reason", "系统确权成功");
-                            log.set("create_time", System.currentTimeMillis());
-                            log.save();
-
-                            order.setOrderStatus(OrderController.OrderStatus.COMPLETED.code);// 该笔订单已完成
-                            order.setBsnTransferStatus(searchResponse.toJSONString());
-                            order.setNftMintStatus(4);// nft已确权转移
-                            order.setDeliveryStatus(1);// 交付成功
-                            order.setDeliveryTime(System.currentTimeMillis());
-                            order.setRefundStatus(0);
-                            order.setClosedTime(System.currentTimeMillis());
-                            order.setUpdateTime(System.currentTimeMillis());
-
-                            order.update();
-                            AppConfig.LOGGER.info("该订单已确权:{}", order);
-                            
-                            // 该用户如果没有标记为有效账户进行标记
-                            if (user.getIsEffective() == 0) {
-                                user.setIsEffective(1);
-                                user.setEffectiveTime(System.currentTimeMillis());
-                                user.update();
-                            }
-
-                            // 异步执行分润过程
-                            AppConfig.TaskScheduler.submit(new UserTeamShareTask(order, userService));
-                        }
-
-                        // status为2时是交付失败,自动执行退款
-                        if (data.getInteger("status") == 2) {
-                            // 记录日志
-                            OrderLog log = new OrderLog();
-                            log.set("order_id", order.getId());
-                            log.set("from_status", order.getOrderStatus());
-                            log.set("to_status", OrderController.OrderStatus.REFUNDED.code);
-                            log.set("operator_id", userId);
-                            log.set("operator_type", 3);
-                            log.set("change_reason", "系统确权失败");
-                            log.set("create_time", System.currentTimeMillis());
-                            log.save();
-
-                            // 更新用户余额
-                            user.setBalance(user.getBalance() + order.getTotalPrice());
-                            user.update();
-
-                            // 更新订单状态
-                            order.setOrderStatus(OrderController.OrderStatus.REFUNDED.code);// 该笔订单已退款
-                            order.setBsnTransferStatus(searchResponse.toJSONString());
-                            order.setNftMintStatus(2);// nft是铸造成功了的,但是确权失败
-                            order.setDeliveryStatus(2);// 交付失败
-                            order.setRefundStatus(2);// 退款成功
-                            order.setClosedTime(System.currentTimeMillis());
-                            order.setUpdateTime(System.currentTimeMillis());
-                            order.update();
-
-                            AppConfig.LOGGER.error("该订单确权失败:{}", order);
-                        }
-                    } else {
-                        throw new RuntimeException(searchResponse.toJSONString());
-                    }
-                } catch (Exception e) {
-                    AppConfig.LOGGER.error("查询转账信息执行失败:{}", e.getMessage());
-                }
-            }
-            // 未转账的先进行转账
-            else {
-                Nftt nftt = Nftt.dao.findById(order.getNfttId());
-                // 订单是预购订单并且:如果还未转为正式销售的nft先不转帐
-                if (order.getOrderType() == 2 && System.currentTimeMillis() < nftt.getBuyingStartTime()) {
-                    continue;
-                }
-
-                // 转账参数整理
-                String address = user.getBsnAccountAddress();
-                int quantity = order.getQuantity();
-                String tokenId = nftt.getBsnTokenId();
-                String bsnTransferCode = "DLTBH_ORDER_" + order.getId();
-
-                try {
-                    JSONObject transferResponse = BsnSDK.sendNft(address, quantity, tokenId, bsnTransferCode);
-
-                    if (transferResponse.getInteger("code") == 0) {
-                        order.setBsnTransferCode(bsnTransferCode);
-
-                        order.update();
-                    } else {
-                        throw new RuntimeException(transferResponse.toJSONString());
-                    }
-                } catch (Exception e) {
-                    AppConfig.LOGGER.error("转账执行失败:{}", e.getMessage());
-                }
-            }
-        }
-    }
     
     /**
      * 【重用方法】封装订单列表及其状态流转日志

+ 157 - 7
src/main/java/modules/order/OrderStatusMaintenanceTask.java

@@ -1,22 +1,38 @@
 package modules.order;
 
+import com.alibaba.fastjson.JSONObject;
+import com.jfinal.kit.StrKit;
+import com.jfinal.plugin.activerecord.Db;
+import com.sun.org.apache.xpath.internal.operations.Or;
+import common.jfinal.AppConfig;
+import common.model.Nftt;
+import common.model.Order;
+import common.model.OrderLog;
+import common.model.User;
+import common.utils.bsn.BsnSDK;
+import modules.user.UserService;
+import modules.user.UserTeamShareTask;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 public class OrderStatusMaintenanceTask implements Runnable {
     private static final Logger LOGGER = LoggerFactory.getLogger(OrderStatusMaintenanceTask.class);
 
     // 通过构造函数注入
-    OrderService service;
+    OrderService orderService;
+    UserService userService;
 
     // 任务是否应该停止的标志
     private volatile boolean running = true; // 使用 volatile 确保多线程可见性
     
-    public OrderStatusMaintenanceTask(OrderService service) {
-        this.service = service;
-        LOGGER.info("OrderStatusMaintenanceTask 实例已创建,注入 OrderService。{}", service.hashCode());
+    public OrderStatusMaintenanceTask(OrderService orderService, UserService userService) {
+        this.orderService = orderService;
+        this.userService = userService;
+        
+        LOGGER.info("OrderStatusMaintenanceTask 实例已创建,注入 OrderService。{}", orderService.hashCode());
     }
     
     @Override
@@ -24,10 +40,13 @@ public class OrderStatusMaintenanceTask implements Runnable {
         LOGGER.info("OrderStatusMaintenanceTask 后台任务开始运行...");
         while (running) { // 循环直到收到停止指令
             try {
-                LOGGER.info("{}", service.countOrders(60));
-                
                 // 每次循环后休眠一段时间,避免CPU空转,并控制检查频率
-                Thread.sleep(TimeUnit.SECONDS.toMillis(10)); // 例如每 60 秒检查一次
+                Thread.sleep(TimeUnit.SECONDS.toMillis(10)); // 每 10 秒检查一次
+                
+                // 只处理已支付但未确权的
+                String sql = "SELECT id FROM t_order" +
+                        " WHERE order_status=40";
+                doNftTransfer(Order.dao.find(sql));
             } catch (InterruptedException e) {
                 LOGGER.warn("OrderStatusMaintenanceTask 因中断而停止。");
                 Thread.currentThread().interrupt(); // 重新设置中断状态
@@ -46,4 +65,135 @@ public class OrderStatusMaintenanceTask implements Runnable {
         }
         LOGGER.info("OrderStatusMaintenanceTask 后台任务已停止运行。");
     }
+
+    private void doNftTransfer(List<Order> orderList) throws InterruptedException {
+        // 未给用户转账的进行转账
+        for (Order o : orderList) {
+            // 1秒最多检查1个订单,防止超频
+            Thread.sleep(TimeUnit.SECONDS.toMillis(1));
+
+            // 使用事务锁定
+            Db.tx(() -> {
+                Order order = Order.dao.findFirst("SELECT * FROM t_order WHERE id=? FOR UPDATE", o.getId());
+                User user = User.dao.findById(order.getUserId());
+
+                // 已经交付完成或交付失败就不用看状态了
+                if (order.getOrderStatus() == OrderController.OrderStatus.COMPLETED.code
+                        || order.getOrderStatus() == OrderController.OrderStatus.CANCELED.code
+                        || order.getOrderStatus() == OrderController.OrderStatus.REFUNDED.code) {
+                    return true;
+                }
+    
+                // 已经执行过转账的查看是否确权,查看状态
+                if (StrKit.notBlank(order.getBsnTransferCode())) {
+                    try {
+                        JSONObject searchResponse = BsnSDK.search(order.getBsnTransferCode());
+    
+                        if (searchResponse.getInteger("code") == 0) {
+                            JSONObject data = searchResponse.getJSONObject("data");
+    
+                            // status为1时才是交付成功,其它要么是pending要么是交付失败
+                            if (data.getInteger("status") == 1) {
+                                OrderLog log = new OrderLog();
+                                log.set("order_id", order.getId());
+                                log.set("from_status", order.getOrderStatus());
+                                log.set("to_status", OrderController.OrderStatus.COMPLETED.code);
+                                log.set("operator_id", 0);
+                                log.set("operator_type", 3);
+                                log.set("change_reason", "系统确权成功");
+                                log.set("create_time", System.currentTimeMillis());
+                                log.save();
+    
+                                order.setOrderStatus(OrderController.OrderStatus.COMPLETED.code);// 该笔订单已完成
+                                order.setBsnTransferStatus(searchResponse.toJSONString());
+                                order.setNftMintStatus(4);// nft已确权转移
+                                order.setDeliveryStatus(1);// 交付成功
+                                order.setDeliveryTime(System.currentTimeMillis());
+                                order.setRefundStatus(0);
+                                order.setClosedTime(System.currentTimeMillis());
+                                order.setUpdateTime(System.currentTimeMillis());
+    
+                                order.update();
+                                AppConfig.LOGGER.info("该订单已确权:{}", order);
+    
+                                // 该用户如果没有标记为有效账户进行标记
+                                if (user.getIsEffective() == 0) {
+                                    user.setIsEffective(1);
+                                    user.setEffectiveTime(System.currentTimeMillis());
+                                    user.update();
+                                }
+    
+                                // 异步执行分润过程
+                                AppConfig.TaskScheduler.submit(new UserTeamShareTask(order, userService));
+                            }
+    
+                            // status为2时是交付失败,自动执行退款
+                            if (data.getInteger("status") == 2) {
+                                // 记录日志
+                                OrderLog log = new OrderLog();
+                                log.set("order_id", order.getId());
+                                log.set("from_status", order.getOrderStatus());
+                                log.set("to_status", OrderController.OrderStatus.REFUNDED.code);
+                                log.set("operator_id", 0);
+                                log.set("operator_type", 3);
+                                log.set("change_reason", "系统确权失败");
+                                log.set("create_time", System.currentTimeMillis());
+                                log.save();
+    
+                                // 更新用户余额
+                                user.setBalance(user.getBalance() + order.getTotalPrice());
+                                user.update();
+    
+                                // 更新订单状态
+                                order.setOrderStatus(OrderController.OrderStatus.REFUNDED.code);// 该笔订单已退款
+                                order.setBsnTransferStatus(searchResponse.toJSONString());
+                                order.setNftMintStatus(2);// nft是铸造成功了的,但是确权失败
+                                order.setDeliveryStatus(2);// 交付失败
+                                order.setRefundStatus(2);// 退款成功
+                                order.setClosedTime(System.currentTimeMillis());
+                                order.setUpdateTime(System.currentTimeMillis());
+                                order.update();
+    
+                                AppConfig.LOGGER.error("该订单确权失败:{}", order);
+                            }
+                        } else {
+                            throw new RuntimeException(searchResponse.toJSONString());
+                        }
+                    } catch (Exception e) {
+                        AppConfig.LOGGER.error("查询转账信息执行失败:{}", e.getMessage());
+                    }
+                }
+                // 未转账的先进行转账
+                else {
+                    Nftt nftt = Nftt.dao.findById(order.getNfttId());
+                    // 订单是预购订单并且:如果还未转为正式销售的nft先不转帐
+                    if (order.getOrderType() == 2 && System.currentTimeMillis() < nftt.getBuyingStartTime()) {
+                        return true;
+                    }
+    
+                    // 转账参数整理
+                    String address = user.getBsnAccountAddress();
+                    int quantity = order.getQuantity();
+                    String tokenId = nftt.getBsnTokenId();
+                    String bsnTransferCode = "DLTBH_ORDER_" + order.getId();
+    
+                    try {
+                        JSONObject transferResponse = BsnSDK.sendNft(address, quantity, tokenId, bsnTransferCode);
+    
+                        if (transferResponse.getInteger("code") == 0) {
+                            order.setBsnTransferCode(bsnTransferCode);
+    
+                            order.update();
+                        } else {
+                            throw new RuntimeException(transferResponse.toJSONString());
+                        }
+                    } catch (Exception e) {
+                        AppConfig.LOGGER.error("转账执行失败:{}", e.getMessage());
+                    }
+                }
+                
+                return true;
+            });
+        }
+    }
 }

+ 1 - 1
src/test/rest/OrderControllerTest.http

@@ -17,7 +17,7 @@ Content-Type: application/json
 dl-token: {{dl_token_var}}
 
 {
-  "order_id": 6
+  "order_id": 9
 }
 
 ### 用户根据订单号查找订单