优化 agent 对账文件处理机制
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/agent/Constant.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/agent/Constant.java
new file mode 100644
index 0000000..c135d58
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/agent/Constant.java
@@ -0,0 +1,22 @@
+package com.supwisdom.dlpay.api.agent;
+
+public class Constant {
+  public static final String FLAG_PAY = "pay";
+  public static final String FLAG_REFUND = "refund";
+  public static final String STATUS_SUCCESS = "success";
+  public static final String STATUS_FAIL = "fail";
+
+  public static final String CHKFILE_DELIMITER = ",";
+
+
+  /////////////////////////////////////////////////////////////////
+  public static final String COL_REFNO = "refno";
+  public static final String COL_AGENT_REFNO = "agentrefno";
+  public static final String COL_AMOUNT = "amount";
+  public static final String COL_PAYERID = "payerid";
+  public static final String COL_PAYEEID = "payeeid";
+  public static final String COL_SUMMARY = "summary";
+  public static final String COL_AGENT_DATE = "agentdate";
+  public static final String COL_STATUS = "status";
+  public static final String COL_FLAG = "flag";
+}
diff --git a/payapi/build.gradle b/payapi/build.gradle
index 419a470..e2cdedd 100644
--- a/payapi/build.gradle
+++ b/payapi/build.gradle
@@ -58,6 +58,8 @@
     implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
     implementation 'commons-codec:commons-codec:1.12'
     implementation 'org.apache.commons:commons-lang3:3.9'
+    implementation 'net.javacrumbs.shedlock:shedlock-spring:2.5.0'
+    implementation 'net.javacrumbs.shedlock:shedlock-provider-redis-spring:2.5.0'
 
     implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery:2.1.2.RELEASE'
 
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index b6f81aa..d0e6f9c 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -2,6 +2,8 @@
 
 import com.supwisdom.dlpay.framework.tenant.TenantCacheKeyGen
 import io.lettuce.core.ReadFrom
+import net.javacrumbs.shedlock.core.LockProvider
+import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.SpringApplication
 import org.springframework.boot.autoconfigure.SpringBootApplication
@@ -50,6 +52,11 @@
     fun createTenantCacheableKey(): KeyGenerator {
         return TenantCacheKeyGen()
     }
+
+    @Bean
+    fun lockProvider(connectionFactory: RedisConnectionFactory): LockProvider {
+        return RedisLockProvider(connectionFactory, "prod")
+    }
 }
 
 @Configuration
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt
index 096d924..7d93474 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt
@@ -13,6 +13,7 @@
 import com.supwisdom.dlpay.framework.util.ApplicationUtil
 import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.util.ConstantUtil
+import net.javacrumbs.shedlock.core.SchedulerLock
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.context.ApplicationContext
 import org.springframework.scheduling.annotation.Scheduled
@@ -23,41 +24,17 @@
 class MySchedulerTask {
     @Autowired
     private lateinit var shopaccService: ShopaccService
-    @Autowired
-    private lateinit var systemUtilService: SystemUtilService
 
     fun doShopBlanceUpdate(dtl: TShopdtl) {
         shopaccService.recalcShopBalance(dtl.refno, true)
     }
 
     @Scheduled(cron = "\${shopbalance.updater.cron:-}")
+    @SchedulerLock(name = "dealShopUnupdatedDtl")
     fun dealShopUnupdatedDtl() {
-        var tasklock = TTaskLock()
-        try {
-            //集群控制
-            try {
-                tasklock = systemUtilService.doLockTask("SHOPBLANCEUPDATETASK", 10, "更新账户余额任务")
-                if (tasklock == null) {
-                    return
-                }
-            } catch (e: Exception) {
-                return
-            }
-
-            shopaccService.findUnupdatedShopDtl(100).forEach {
-                doShopBlanceUpdate(it)
-            }
-        } catch (ex: Exception) {
-            ex.printStackTrace()
-        } finally {
-            if (tasklock?.taskcode.isNotEmpty()) {
-                tasklock.taskstatus = 0
-                tasklock.tasktime = systemUtilService.sysdatetime.hostdatetime
-                systemUtilService.updateTaskLock(tasklock)
-            }
+        shopaccService.findUnupdatedShopDtl(100).forEach {
+            doShopBlanceUpdate(it)
         }
-
-
     }
 }
 
@@ -78,35 +55,15 @@
     private lateinit var applicationContext: ApplicationContext
 
     @Scheduled(cron = "\${query.third.transdtl.result.cron:-}")
+    @SchedulerLock(name = "DtlQueryResultSchedulerTask")
     fun queryThirdTransdtlResult() {
-        var tasklock = TTaskLock()
-        try {
-            //集群控制
+        //仅查询当天数据,查询次数在规定次数之下
+        dtlQueryResultService.getNeedQueryRecords(systemUtilService.accdate, ConstantUtil.QUERY_MAX_COUNT).forEach {
             try {
-                tasklock = systemUtilService.doLockTask("QUERYTHIRDTRANSDTLRESULTTASK", 10, "查询第三方流水状态任务")
-                if (tasklock == null) {
-                    return
-                }
-            } catch (e: Exception) {
-                return
-            }
-
-            //仅查询当天数据,查询次数在规定次数之下
-            dtlQueryResultService.getNeedQueryRecords(systemUtilService.accdate, ConstantUtil.QUERY_MAX_COUNT).forEach {
-                try {
-                    doQuery(it)
-                } catch (exp: Exception) {
-                    it.qcnt = it.qcnt + 1
-                    dtlQueryResultService.saveOrUpdateDtlQuery(it) //次数加一
-                }
-            }
-        } catch (ex: Exception) {
-            ex.printStackTrace()
-        } finally {
-            if (tasklock?.taskcode.isNotEmpty()) {
-                tasklock.taskstatus = 0
-                tasklock.tasktime = systemUtilService.sysdatetime.hostdatetime
-                systemUtilService.updateTaskLock(tasklock)
+                doQuery(it)
+            } catch (exp: Exception) {
+                it.qcnt = it.qcnt + 1
+                dtlQueryResultService.saveOrUpdateDtlQuery(it) //次数加一
             }
         }
     }
diff --git a/ynrcc-agent/build.gradle b/ynrcc-agent/build.gradle
index a00c65d..4387052 100644
--- a/ynrcc-agent/build.gradle
+++ b/ynrcc-agent/build.gradle
@@ -51,6 +51,8 @@
     implementation 'org.dom4j:dom4j:2.1.1'
     implementation 'commons-beanutils:commons-beanutils:1.9.3'
 
+    implementation project(':payapi-common')
+
     testImplementation 'org.springframework.boot:spring-boot-starter-test'
     testImplementation 'io.rest-assured:rest-assured:3.3.0'
     testImplementation 'io.rest-assured:spring-mock-mvc:3.3.0'
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/CheckFileHeader.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/CheckFileHeader.java
deleted file mode 100644
index d19df54..0000000
--- a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/CheckFileHeader.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.supwisdom.agent.api.bean;
-
-/**
- * 第一行:总笔数|总金额|代扣总笔数|代扣总金额|退款总笔数|退款总金额|
- */
-public class CheckFileHeader {
-  private int totalCount;
-  private int totalAmount;
-  private int payCount;
-  private int payAmount;
-  private int refundCount;
-  private int refundAmount;
-
-  public int getTotalCount() {
-    return totalCount;
-  }
-
-  public void setTotalCount(int totalCount) {
-    this.totalCount = totalCount;
-  }
-
-  public int getTotalAmount() {
-    return totalAmount;
-  }
-
-  public void setTotalAmount(int totalAmount) {
-    this.totalAmount = totalAmount;
-  }
-
-  public int getPayCount() {
-    return payCount;
-  }
-
-  public void setPayCount(int payCount) {
-    this.payCount = payCount;
-  }
-
-  public int getPayAmount() {
-    return payAmount;
-  }
-
-  public void setPayAmount(int payAmount) {
-    this.payAmount = payAmount;
-  }
-
-  public int getRefundCount() {
-    return refundCount;
-  }
-
-  public void setRefundCount(int refundCount) {
-    this.refundCount = refundCount;
-  }
-
-  public int getRefundAmount() {
-    return refundAmount;
-  }
-
-  public void setRefundAmount(int refundAmount) {
-    this.refundAmount = refundAmount;
-  }
-
-  public boolean isZero() {
-    return (totalAmount == 0 && totalCount == 0
-        && payAmount == 0 && payCount == 0 && refundAmount == 0 && refundCount == 0);
-  }
-
-  @Override
-  public String toString() {
-    return totalCount +
-        ", " + totalAmount +
-        ", " + payCount +
-        ", " + payAmount +
-        ", " + refundCount +
-        ", " + refundAmount;
-  }
-}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/controller/YnrccApiController.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/controller/YnrccApiController.java
index 52fa611..508b297 100644
--- a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/controller/YnrccApiController.java
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/controller/YnrccApiController.java
@@ -4,12 +4,12 @@
 import com.supwisdom.agent.Util.DlpayUtil;
 import com.supwisdom.agent.Util.ErrorCode;
 import com.supwisdom.agent.Util.StringUtil;
-import com.supwisdom.agent.api.bean.CheckFileHeader;
 import com.supwisdom.agent.api.bean.CheckFileLine;
 import com.supwisdom.agent.api.bean.DlpayReq;
 import com.supwisdom.agent.api.bean.DlpayResp;
 import com.supwisdom.agent.api.service.YnrccApiService;
 import com.supwisdom.agent.api.service.YnrccParamCheckService;
+import com.supwisdom.dlpay.api.agent.Constant;
 import org.apache.commons.beanutils.BeanUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -38,10 +38,10 @@
    * 第一行:总笔数|总金额|代扣总笔数|代扣总金额|退款总笔数|退款总金额|
    * 第二行及以后:交易日期|交易时间|报文业务类型|业务系统流水号|银行流水号|付款银行卡号|收款商户银行卡号|核心记账日期|交易金额|交易摘要|
    */
-  private static final String[] chkFileColumnList = new String[]{"transdate", "transtime", "flag", "refno", "agentrefno",
-      "payerid", "payeeid", "agentdate", "amount", "summary"};
-  private static final String[] chkFileHeaderColumnList = new String[]{"totalCount", "totalAmount", "payCount",
-      "payAmount", "refundCount", "refundAmount"};
+  private static final String[] chkFileColumnList = new String[]{"transdate", "transtime", Constant.COL_FLAG,
+      Constant.COL_REFNO, Constant.COL_AGENT_REFNO, Constant.COL_PAYERID, Constant.COL_PAYEEID,
+      Constant.COL_AGENT_DATE, Constant.COL_AMOUNT, Constant.COL_SUMMARY};
+
   private static final String chkFileDelimiter = "|";
   private static final String FLAG_WITHHOLD = "BC5512";
   private static final String FLAG_REFUND = "BC5513";
@@ -394,7 +394,7 @@
   }
 
   private <T> void populate(String[] fields, String[] column, T bean) {
-    if (fields.length != column.length) {
+    if (fields.length < column.length) {
       throw new IllegalArgumentException("错误的列定义");
     }
     try {
@@ -413,6 +413,7 @@
     try {
       T bean = beanClass.newInstance();
       populate(fields, column, bean);
+      return bean;
     } catch (InstantiationException e) {
       e.printStackTrace();
     } catch (IllegalAccessException e) {
@@ -421,10 +422,10 @@
     throw new IllegalArgumentException("错误的列定义");
   }
 
-  private void writeLine(OutputStream output, String delimiter, Object... columns) throws IOException {
+  private void writeLine(OutputStream output, Object... columns) throws IOException {
     for (Object item : columns) {
       output.write(item.toString().getBytes(StandardCharsets.UTF_8));
-      output.write(delimiter.getBytes());
+      output.write(Constant.CHKFILE_DELIMITER.getBytes(StandardCharsets.UTF_8));
     }
     output.write("\n".getBytes());
   }
@@ -440,13 +441,15 @@
         throw new IllegalArgumentException("数据文件内容为空");
       }
 
-      CheckFileHeader fileHeader = populate(chkFileHeaderColumnList,
+      CheckFileHeader fileHeader = populate(CheckFileHeader.chkFileHeaderColumnList,
           header.split(chkFileDelimiter), CheckFileHeader.class);
 
 
       CheckFileLine record = new CheckFileLine();
-      writeLine(output, ",", "refno", "agentrefno", "agentdate", "flag", "payerid",
-          "payeeid", "amount", "summary");
+      writeLine(output, Constant.COL_REFNO, Constant.COL_AGENT_REFNO,
+          Constant.COL_AGENT_DATE, Constant.COL_FLAG, Constant.COL_PAYERID,
+          Constant.COL_PAYEEID, Constant.COL_STATUS,
+          Constant.COL_AMOUNT, Constant.COL_SUMMARY);
       while (true) {
         String line = reader.readLine();
         if (line == null) {
@@ -459,12 +462,12 @@
         String flag;
         if (FLAG_WITHHOLD.equals(record.getFlag())) {
           amount = -record.getAmount();
-          flag = "pay";
+          flag = Constant.FLAG_PAY;
           fileHeader.setPayCount(fileHeader.getPayCount() - 1);
           fileHeader.setPayAmount(fileHeader.getPayAmount() - record.getAmount());
         } else if (FLAG_REFUND.equals(record.getFlag())) {
           amount = +record.getAmount();
-          flag = "refund";
+          flag = Constant.FLAG_REFUND;
           fileHeader.setRefundCount(fileHeader.getRefundCount() - 1);
           fileHeader.setRefundAmount(fileHeader.getRefundAmount() - record.getAmount());
         } else {
@@ -472,9 +475,8 @@
         }
         fileHeader.setTotalCount(fileHeader.getTotalCount() - 1);
         fileHeader.setTotalAmount(fileHeader.getTotalAmount() - record.getAmount());
-        writeLine(output, ",", record.getRefno(),
-            record.getAgentrefno(), record.getAgentdate(),
-            flag, record.getPayerid(), record.getPayeeid(),
+        writeLine(output, record.getRefno(), record.getAgentrefno(), record.getAgentdate(),
+            flag, record.getPayerid(), record.getPayeeid(), Constant.STATUS_SUCCESS,
             amount, record.getSummary());
       }
       if (!fileHeader.isZero()) {
@@ -495,4 +497,73 @@
       response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value(), e.getMessage());
     }
   }
+
+
+  /**
+   * 第一行:总笔数|总金额|代扣总笔数|代扣总金额|退款总笔数|退款总金额|
+   */
+  private static class CheckFileHeader {
+    static final String[] chkFileHeaderColumnList = new String[]{"totalCount", "totalAmount", "payCount",
+        "payAmount", "refundCount", "refundAmount"};
+
+    private int totalCount;
+    private int totalAmount;
+    private int payCount;
+    private int payAmount;
+    private int refundCount;
+    private int refundAmount;
+
+    int getTotalCount() {
+      return totalCount;
+    }
+
+    void setTotalCount(int totalCount) {
+      this.totalCount = totalCount;
+    }
+
+    int getTotalAmount() {
+      return totalAmount;
+    }
+
+    void setTotalAmount(int totalAmount) {
+      this.totalAmount = totalAmount;
+    }
+
+    int getPayCount() {
+      return payCount;
+    }
+
+    void setPayCount(int payCount) {
+      this.payCount = payCount;
+    }
+
+    int getPayAmount() {
+      return payAmount;
+    }
+
+    void setPayAmount(int payAmount) {
+      this.payAmount = payAmount;
+    }
+
+    int getRefundCount() {
+      return refundCount;
+    }
+
+    void setRefundCount(int refundCount) {
+      this.refundCount = refundCount;
+    }
+
+    int getRefundAmount() {
+      return refundAmount;
+    }
+
+    void setRefundAmount(int refundAmount) {
+      this.refundAmount = refundAmount;
+    }
+
+    boolean isZero() {
+      return (totalAmount == 0 && totalCount == 0
+          && payAmount == 0 && payCount == 0 && refundAmount == 0 && refundCount == 0);
+    }
+  }
 }