|
@@ -0,0 +1,142 @@
|
|
|
|
|
+package modules.withdraw;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.jfinal.plugin.activerecord.Db;
|
|
|
|
|
+import common.model.*;
|
|
|
|
|
+import common.utils.hyg.HygSDK;
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
+
|
|
|
|
|
+public class WithdrawMaintenanceTask implements Runnable {
|
|
|
|
|
+ private static final Logger LOGGER = LoggerFactory.getLogger(WithdrawMaintenanceTask.class);
|
|
|
|
|
+
|
|
|
|
|
+ // 任务是否应该停止的标志
|
|
|
|
|
+ private volatile boolean running = true; // 使用 volatile 确保多线程可见性
|
|
|
|
|
+
|
|
|
|
|
+ public WithdrawMaintenanceTask() {
|
|
|
|
|
+ LOGGER.info("WithdrawMaintenanceTask 实例已创建。");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void run() {
|
|
|
|
|
+ LOGGER.info("WithdrawMaintenanceTask 后台任务开始运行...");
|
|
|
|
|
+ while (running) { // 循环直到收到停止指令
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 每次循环后休眠一段时间,避免CPU空转,并控制检查频率
|
|
|
|
|
+ Thread.sleep(TimeUnit.SECONDS.toMillis(60)); // 每 60 秒检查一次
|
|
|
|
|
+
|
|
|
|
|
+ // 只处理已通过审批的
|
|
|
|
|
+ String sql = "SELECT id FROM t_withdraw WHERE state=20";
|
|
|
|
|
+ flushWithdrawState(Withdraw.dao.find(sql));
|
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
|
+ LOGGER.warn("WithdrawMaintenanceTask 因中断而停止。");
|
|
|
|
|
+ Thread.currentThread().interrupt(); // 重新设置中断状态
|
|
|
|
|
+ running = false; // 退出循环
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ // 捕获所有其他异常,记录日志,但保持线程继续运行
|
|
|
|
|
+ LOGGER.error("WithdrawMaintenanceTask 执行异常: {}", e.getMessage(), e);
|
|
|
|
|
+ // 可以在这里添加告警,或在短时间后重试
|
|
|
|
|
+ try {
|
|
|
|
|
+ Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // 发生错误时短暂休眠,避免错误日志刷屏
|
|
|
|
|
+ } catch (InterruptedException ie) {
|
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
|
+ running = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ LOGGER.info("WithdrawMaintenanceTask 后台任务已停止运行。");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void flushWithdrawState(List<Withdraw> withdrawList) throws InterruptedException {
|
|
|
|
|
+ // 未给用户转账的进行转账
|
|
|
|
|
+ for (Withdraw w : withdrawList) {
|
|
|
|
|
+ // 1秒最多检查1个提现请求,防止超频
|
|
|
|
|
+ Thread.sleep(TimeUnit.SECONDS.toMillis(1));
|
|
|
|
|
+
|
|
|
|
|
+ // 使用事务锁定
|
|
|
|
|
+ Db.tx(() -> {
|
|
|
|
|
+ User user = User.dao.findFirst("SELECT * FROM t_user WHERE id=? FOR UPDATE", w.getUserId());
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ JSONObject hygRst = HygSDK.signalQuery(w.getWithdrawSn());
|
|
|
|
|
+
|
|
|
|
|
+ // 失败的等能获取再说
|
|
|
|
|
+ if (!hygRst.getString("statusCode").equals("000000")) {
|
|
|
|
|
+ LOGGER.error("请求提现订单时失败{}", hygRst);
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取真实结构体
|
|
|
|
|
+ JSONObject data = hygRst.getJSONObject("data");
|
|
|
|
|
+
|
|
|
|
|
+ int distributeStatus = data.getInteger("distributeStatus"); // 状态码
|
|
|
|
|
+ String remark = data.getString("remark"); // 备注
|
|
|
|
|
+
|
|
|
|
|
+ // 下发状态
|
|
|
|
|
+ // 9-待验证,
|
|
|
|
|
+ // 10-验证成功,
|
|
|
|
|
+ // 20-验证失败,
|
|
|
|
|
+ // 30-已取消,
|
|
|
|
|
+ // 40-待打款,
|
|
|
|
|
+ // 50-打款中,
|
|
|
|
|
+ // 60-打款成功,
|
|
|
|
|
+ // 70-打款失败,
|
|
|
|
|
+ // 75-已退款,
|
|
|
|
|
+ // 80-退票中,
|
|
|
|
|
+ // 90-已退票
|
|
|
|
|
+
|
|
|
|
|
+ // 这些状态视为失败的
|
|
|
|
|
+ if (distributeStatus == 20
|
|
|
|
|
+ || distributeStatus == 30
|
|
|
|
|
+ || distributeStatus == 70
|
|
|
|
|
+ || distributeStatus == 75
|
|
|
|
|
+ || distributeStatus == 80
|
|
|
|
|
+ || distributeStatus == 90) {
|
|
|
|
|
+ // 1. 处理单据的状态
|
|
|
|
|
+ w.setState(40);
|
|
|
|
|
+ w.setHygOrigin(hygRst.toString());
|
|
|
|
|
+ w.setReason(remark);
|
|
|
|
|
+ w.setUpdateTime(System.currentTimeMillis());
|
|
|
|
|
+ w.update();
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 处理用户的状态
|
|
|
|
|
+ user.setBalance(user.getBalance() + w.getAmount());
|
|
|
|
|
+ user.update();
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 资金流水处理
|
|
|
|
|
+ DepositLog l = new DepositLog();
|
|
|
|
|
+ l.set("create_time", System.currentTimeMillis());
|
|
|
|
|
+ l.set("is_deleted", 0);
|
|
|
|
|
+ l.set("description", "提现失败退还,慧用工原因:" + remark); // 描述中带上百分比
|
|
|
|
|
+ l.set("amount", w.getAmount());
|
|
|
|
|
+ l.set("user_id", user.getLong("id"));
|
|
|
|
|
+ l.save();
|
|
|
|
|
+
|
|
|
|
|
+ LOGGER.info("慧用工提现失败:{}", w);
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 这个逻辑视为打款成功的
|
|
|
|
|
+ if (distributeStatus == 60) {
|
|
|
|
|
+ w.setState(30);
|
|
|
|
|
+ w.setHygOrigin(hygRst.toString());
|
|
|
|
|
+ w.update();
|
|
|
|
|
+
|
|
|
|
|
+ LOGGER.info("慧用工提现已成功:{}", w);
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ LOGGER.error("提现状态获取失败:{}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|