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 orderService; UserService userService; // 任务是否应该停止的标志 private volatile boolean running = true; // 使用 volatile 确保多线程可见性 public OrderStatusMaintenanceTask(OrderService orderService, UserService userService) { this.orderService = orderService; this.userService = userService; LOGGER.info("OrderStatusMaintenanceTask 实例已创建,注入 OrderService。{}", orderService.hashCode()); } @Override public void run() { LOGGER.info("OrderStatusMaintenanceTask 后台任务开始运行..."); while (running) { // 循环直到收到停止指令 try { // 每次循环后休眠一段时间,避免CPU空转,并控制检查频率 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(); // 重新设置中断状态 running = false; // 退出循环 } catch (Exception e) { // 捕获所有其他异常,记录日志,但保持线程继续运行 LOGGER.error("OrderStatusMaintenanceTask 执行异常: {}", e.getMessage(), e); // 可以在这里添加告警,或在短时间后重试 try { Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // 发生错误时短暂休眠,避免错误日志刷屏 } catch (InterruptedException ie) { Thread.currentThread().interrupt(); running = false; } } } LOGGER.info("OrderStatusMaintenanceTask 后台任务已停止运行。"); } private void doNftTransfer(List 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; }); } } }