农商行下载对账单
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/YnrccChkfileBean.java b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/YnrccChkfileBean.java
new file mode 100644
index 0000000..bdfc228
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/YnrccChkfileBean.java
@@ -0,0 +1,85 @@
+package com.supwisdom.dlpay.api.bean;
+
+public class YnrccChkfileBean {
+  private String refno; //本地流水号
+  private String agentrefno; //银行流水号
+  private String agentdate; //yin
+  private Integer amount;
+  private String payerid;
+  private String payeeid;
+  private String summary;
+  private String status;
+  private String flag;
+
+  public String getRefno() {
+    return refno;
+  }
+
+  public void setRefno(String refno) {
+    this.refno = refno;
+  }
+
+  public String getAgentrefno() {
+    return agentrefno;
+  }
+
+  public void setAgentrefno(String agentrefno) {
+    this.agentrefno = agentrefno;
+  }
+
+  public String getAgentdate() {
+    return agentdate;
+  }
+
+  public void setAgentdate(String agentdate) {
+    this.agentdate = agentdate;
+  }
+
+  public Integer getAmount() {
+    return amount;
+  }
+
+  public void setAmount(Integer amount) {
+    this.amount = amount;
+  }
+
+  public String getPayerid() {
+    return payerid;
+  }
+
+  public void setPayerid(String payerid) {
+    this.payerid = payerid;
+  }
+
+  public String getPayeeid() {
+    return payeeid;
+  }
+
+  public void setPayeeid(String payeeid) {
+    this.payeeid = payeeid;
+  }
+
+  public String getSummary() {
+    return summary;
+  }
+
+  public void setSummary(String summary) {
+    this.summary = summary;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public String getFlag() {
+    return flag;
+  }
+
+  public void setFlag(String flag) {
+    this.flag = flag;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java
index 63058e8..88a6f56 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionChkdtlDao.java
@@ -1,10 +1,20 @@
 package com.supwisdom.dlpay.api.dao;
 
 import com.supwisdom.dlpay.api.domain.TTransactionChkdtl;
+import com.supwisdom.dlpay.framework.data.CountAmountBean;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 
 @Repository
 public interface TransactionChkdtlDao extends JpaRepository<TTransactionChkdtl, String> {
 
+  @Modifying
+  @Query("delete from TTransactionChkdtl t where t.accdate=?1 and t.sourcetype=?2 ")
+  void deleteByAccdateAndSorucetype(String accdate, String sourcetype);
+
+  @Query("select count(t.id) as totalcnt,sum(t.amount) as totalamt from TTransactionChkdtl t where t.accdate=?1 and t.sourcetype=?2 ")
+  CountAmountBean getTransactionSumInfo(String accdate, String sourcetype);
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java
index d230036..bc8d7ea 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkdtl.java
@@ -7,7 +7,7 @@
 
 @Entity
 @Table(name = "TB_TRANSACTION_CHKDTL",
-    indexes = {@Index(name = "uk_transaction_chkdtl", unique = true, columnList = "accdate,sourcetype,seqno")})
+    indexes = {@Index(name = "UK_TRANSACTION_CHKDTL", unique = true, columnList = "ACCDATE,SOURCETYPE,THIRD_REFNO,LOCAL_REFNO")})
 public class TTransactionChkdtl {
   @Id
   @GenericGenerator(name = "idGenerator", strategy = "uuid")
@@ -21,9 +21,6 @@
   @Column(name = "SOURCETYPE", nullable = false, length = 20)
   private String sourcetype;
 
-  @Column(name = "SEQNO", nullable = false, precision = 9)
-  private Integer seqno;
-
   @Column(name = "AMOUNT", nullable = false, precision = 9, scale = 2)
   private Double amount;
 
@@ -36,6 +33,9 @@
   @Column(name = "THIRD_ACCDATE", nullable = false, length = 8)
   private String thirdAccdate; //第三方记账日期
 
+  @Column(name = "TRANSTYPE", length = 20)
+  private String transtype; // pay-支付|refund-退款|cancel-撤销
+
   @Column(name = "THIRD_STATUS", length = 20)
   private String thirdStatus; //第三方流水状态
 
@@ -45,10 +45,10 @@
   @Column(name = "EXTDATA", length = 200)
   private String extdata;
 
-  @Column(name = "CHKRESULT", nullable = false, length = 20)
+  @Column(name = "CHKRESULT", length = 20)
   private String chkresult;
 
-  @Column(name = "RESOLVED", nullable = false, length = 20)
+  @Column(name = "RESOLVED", length = 20)
   private String resolved;
 
   @Column(name = "LASTSAVED")
@@ -81,14 +81,6 @@
     this.sourcetype = sourcetype;
   }
 
-  public Integer getSeqno() {
-    return seqno;
-  }
-
-  public void setSeqno(Integer seqno) {
-    this.seqno = seqno;
-  }
-
   public Double getAmount() {
     return amount;
   }
@@ -121,6 +113,14 @@
     this.thirdAccdate = thirdAccdate;
   }
 
+  public String getTranstype() {
+    return transtype;
+  }
+
+  public void setTranstype(String transtype) {
+    this.transtype = transtype;
+  }
+
   public String getThirdStatus() {
     return thirdStatus;
   }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkfile.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkfile.java
index 2cdc0f4..6517f21 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkfile.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionChkfile.java
@@ -7,7 +7,7 @@
 
 @Entity
 @Table(name = "TB_TRANSACTION_CHKFILE",
-    indexes = {@Index(name = "uk_transaction_chkfile", unique = true, columnList = "accdate,sourcetype,")})
+    indexes = {@Index(name = "uk_transaction_chkfile", unique = true, columnList = "accdate,sourcetype,tenantid")})
 public class TTransactionChkfile {
   @Id
   @GenericGenerator(name = "idGenerator", strategy = "uuid")
@@ -24,6 +24,9 @@
   @Column(name = "STATUS", nullable = false, length = 20)
   private String status;
 
+  @Column(name = "RESULT", nullable = false, length = 20)
+  private String result;
+
   @Column(name = "REMARK", length = 600)
   private String remark;
 
@@ -39,6 +42,7 @@
   @Column(name = "LOCALAMT", nullable = false, precision = 15, scale = 2)
   private Double localamt;
 
+  @Version
   @Column(name = "LASTSAVED")
   private Timestamp lastsaved;
 
@@ -77,6 +81,14 @@
     this.status = status;
   }
 
+  public String getResult() {
+    return result;
+  }
+
+  public void setResult(String result) {
+    this.result = result;
+  }
+
   public String getRemark() {
     return remark;
   }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java
index 368bf8e..86fb351 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java
@@ -2,6 +2,8 @@
 
 import com.supwisdom.dlpay.framework.domain.TSettleLog;
 import com.supwisdom.dlpay.framework.service.DayendSettleService;
+import com.supwisdom.dlpay.framework.tenant.TenantContext;
+import com.supwisdom.dlpay.framework.util.Constants;
 import com.supwisdom.dlpay.framework.util.StringUtil;
 import net.javacrumbs.shedlock.core.SchedulerLock;
 import org.slf4j.Logger;
@@ -25,6 +27,8 @@
     if (logger.isDebugEnabled()) logger.debug("进入日结算任务!");
     settleLog = dayendSettleService.doCreateSettleLog(); //记录日志
     try {
+      if (null == TenantContext.getTenantSchema()) TenantContext.setTenantSchema(Constants.DEFAULT_TENANTID);
+
       //step1: 账户校验(fixme: 清算任务?)
       long t1 = System.currentTimeMillis();
       if (!checkAccounts()) {
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/BusinessparaDao.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/BusinessparaDao.java
index 8f8be9c..4b8addc 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/BusinessparaDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/BusinessparaDao.java
@@ -3,10 +3,7 @@
 import com.supwisdom.dlpay.framework.domain.TBusinesspara;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Lock;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.jpa.repository.QueryHints;
+import org.springframework.data.jpa.repository.*;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.LockModeType;
@@ -26,4 +23,8 @@
   TBusinesspara findByParakeyForUpdateNowait(String parakey);
 
   Page<TBusinesspara> findAllByParakeyContaining(String parakey, Pageable pageable);
+
+  @Modifying
+  @Query("update TBusinesspara t set t.paraval=?2 where t.parakey=?1 ")
+  void updateBusinessparaValue(String parakey, String paraval);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/data/CountAmountBean.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/data/CountAmountBean.java
new file mode 100644
index 0000000..2fc13b8
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/data/CountAmountBean.java
@@ -0,0 +1,6 @@
+package com.supwisdom.dlpay.framework.data;
+
+public interface CountAmountBean {
+  Integer getTotalcnt();
+  Double getTotalamt();
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
index 3c7b5de..c7b479c 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
@@ -33,4 +33,38 @@
   public static final String QUERYTYPE_NEED_QUERY = "query";
   public static final String QUERYTYPE_QUERY_FINISH = "finish";
   public static final int QUERY_MAX_COUNT = 10;
+
+  /**
+   * 对账文件状态
+   * */
+  public static final String CHKFILE_STATUS_INIT = "init"; //初始化
+  public static final String CHKFILE_STATUS_UNCHECK = "uncheck"; //待对账
+  public static final String CHKFILE_STATUS_finish = "finish"; //对账完成
+  public static final String CHKFILE_STATUS_ERROR = "error"; //对账异常
+
+  /**
+   * 对账文件结果状态
+   * */
+  public static final String CHKFILE_RESULT_NONE = "none"; //未对账 -
+  public static final String CHKFILE_RESULT_EQUAL = "equal"; //对账一致,平
+  public static final String CHKFILE_RESULT_UNEQUAL = "unequal"; //对账不一致,不平
+
+  /**
+   * 对账明细状态
+   * */
+  public static final String CHKDTL_CHKRESULT_UNCHECK= "uncheck"; //未检查
+  public static final String CHKDTL_CHKRESULT_NEGATION= "negation"; //交易流水不存在
+  public static final String CHKDTL_CHKRESULT_NOCHARGE = "nocharge"; //支付未记账
+  public static final String CHKDTL_CHKRESULT_DIFF = "diff"; //金额不相等
+
+  /**
+   * 对账明细解决状态
+   * */
+  public static final String CHKDTL_RESOLVED_ADD ="add"; //补账
+  public static final String CHKDTL_RESOLVED_PROCESSED = "processed"; //已处理
+  public static final String CHKDTL_RESOLVED_FAIL = "fail"; //补账失败
+  public static final String CHKDTL_RESOLVED_EQUAL = "equal";  //一致,相等
+  public static final String CHKDTL_RESOLVED_HANGUP="hangup"; //挂起
+
+
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt
index e721a02..e2fbcda 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_ynrccchk_task.kt
@@ -15,6 +15,19 @@
 import org.springframework.stereotype.Component
 import org.springframework.web.client.RestTemplate
 
+import com.sun.jersey.api.client.Client
+import com.sun.jersey.api.client.ClientResponse
+import com.supwisdom.dlpay.api.bean.YnrccChkfileBean
+import com.supwisdom.dlpay.api.domain.TTransactionChkfile
+import com.supwisdom.dlpay.framework.tenant.TenantContext
+import com.supwisdom.dlpay.framework.util.Constants
+import com.supwisdom.dlpay.framework.util.StringUtil
+import com.supwisdom.dlpay.util.ConstantUtil
+import java.io.BufferedReader
+import java.io.InputStream
+import java.io.InputStreamReader
+import javax.ws.rs.core.MediaType
+
 
 /**
  * 第三方对账任务
@@ -31,8 +44,6 @@
     private lateinit var transactionReconciliationService: TransactionReconciliationService
     @Autowired
     private lateinit var sourceTypeService: SourceTypeService
-    @Autowired
-    private lateinit var restTemplate: RestTemplate
 
     private val logger = KotlinLogging.logger { }
 
@@ -41,6 +52,8 @@
     @SchedulerLock(name = "DownloadYnrccChkfileSchedulerTask", lockAtMostForString = "PT10M")
     fun doDownloadYnrccChkfile() {
         try {
+            if(null==TenantContext.getTenantSchema()) TenantContext.setTenantSchema(Constants.DEFAULT_TENANTID)
+
             //下载对账单逻辑
             val hostdate = systemUtilService.sysdatetime.hostdate
             val downloadLastdate = ynrccBusinessService.getLastDownloadBillDate()
@@ -50,24 +63,25 @@
             for (i in 1 until diffDays) {
                 val billDate = DateUtil.getNewDay(downloadLastdate, i) //要取对账单的日期
 
-                var chkfile = transactionReconciliationService.getTransactionChkfile(billDate, TradeDict.PAYTYPE_CITIZEN_CARD)
-                if (null != chkfile) {
-                    continue // 已经存在对账单
-                }
+                var chkfile = transactionReconciliationService.doInitTransactionChkfile(billDate, TradeDict.PAYTYPE_CITIZEN_CARD)
 
                 val resp = citizencardPayService.getChkfilename(billDate, null)
                 if (YnrccUtil.CODE_SUCCESS == resp.code) {
                     val agentConfig = sourceTypeService.getChargePaytypeConfig(TradeDict.PAYTYPE_CITIZEN_CARD, true)
-                    val agentUrl = agentConfig[YnrccUtil.YNRCC_ANGENT_URL] + "/download"
+                    val agentUrl = agentConfig[YnrccUtil.YNRCC_ANGENT_URL] + "/download?filename=" + resp.filename
                     //根据filename 取文件数据
-
+                    downloadYnrccBills(billDate, agentUrl, chkfile)
 
                 } else if (YnrccUtil.NO_RECORDS_TODAY == resp.code) {
                     //当日无交易明细,也创建空记录
+                    transactionReconciliationService.doSuccessTransactionChkfile(chkfile,"请求银行返回:当日无交易明细")
 
                 } else {
                     //报错,退出对账单拉取
                     logger.error("大理农商行对账单下载[$billDate]报错:${resp.message}")
+                    chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+                    chkfile.remark = "请求前置获取对账文件报错:${resp.message}"
+                    transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
                     break
                 }
             }
@@ -77,4 +91,82 @@
         }
     }
 
+    private fun downloadYnrccBills(accdate: String, agentUrl: String, chkfile: TTransactionChkfile) {
+        val client = Client.create()
+        client.setConnectTimeout(30000)
+        val respClient = client.resource(agentUrl).type(MediaType.APPLICATION_OCTET_STREAM_TYPE).get(ClientResponse::class.java)
+        if (200 == respClient.status) {
+            val stream = respClient.getEntity(InputStream::class.java)
+            BufferedReader(InputStreamReader(stream)).use { reader ->
+                val header = reader.readLine()
+                val fields = header.split(",").mapNotNull { if (it.isNotEmpty()) it else null }
+                val batchSize = 10000 //每次保存的数目
+                var totalcnt = 0
+                var failcnt = 0
+
+                val datalist = ArrayList<YnrccChkfileBean>()
+                while (true) {
+                    val line = reader.readLine() ?: break
+                    if (line.isEmpty()) continue
+                    val columns = line.split(",").mapNotNull { if (it.isNotEmpty()) it else null }
+                    val bean = YnrccChkfileBean()
+                    StringUtil.transforToBean(fields, columns, bean)
+                    datalist.add(bean)
+                    totalcnt++
+                    if (datalist.size >= batchSize) {
+                        val fcnt = doBatchSaveYnrccCheckDetails(accdate, datalist) //保存
+                        failcnt += fcnt
+                        datalist.clear()
+                        if (failcnt > 0) break
+                    }
+
+                }
+                //保存最后的不足batchSize的记录
+                if (datalist.size > 0) {
+                    val fcnt = doBatchSaveYnrccCheckDetails(accdate, datalist) //保存
+                    failcnt += fcnt
+                }
+
+                if (failcnt > 0) {
+                    //该天对账单保存错误
+                    transactionReconciliationService.deleteTransactionChkDtlByAccdateAndSourcetype(accdate, TradeDict.PAYTYPE_CITIZEN_CARD) //删除已存明细
+                    chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+                    chkfile.remark = "对账单数据入库失败,请下载的检查数据"
+                    transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
+                    return
+                }
+
+                //成功
+                transactionReconciliationService.doSuccessTransactionChkfile(chkfile,"对账单数据下载成功")
+
+            }
+        } else {
+            logger.error("请求前置download[$accdate]对账单返回失败:httpStatus=[${respClient.status}]。获取对账文件数据失败")
+            chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+            chkfile.remark = "请求前置获取对账单数据失败,download返回:httpStatus=${respClient.status}"
+            transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
+        }
+    }
+
+    private fun doBatchSaveYnrccCheckDetails(accdate: String, list: ArrayList<YnrccChkfileBean>): Int {
+        try {
+            transactionReconciliationService.doBatchSaveYnrccTransactionChkDtl(TradeDict.PAYTYPE_CITIZEN_CARD, accdate, list)
+            return 0  //批量保存成功,无失败
+        } catch (e1: Exception) {
+        }
+
+        //批量保存有异常,逐笔保存
+        var failcnt = 0
+        for (bean in list) {
+            try {
+                transactionReconciliationService.saveYnrccTransactionChkDtl(TradeDict.PAYTYPE_CITIZEN_CARD, accdate, bean)
+            } catch (e2: Exception) {
+                failcnt++
+                e2.printStackTrace()
+                continue
+            }
+        }
+        return failcnt
+    }
+
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt
index f334403..d43e051 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_reconciliation_service_impl.kt
@@ -1,9 +1,18 @@
 package com.supwisdom.dlpay.api.service.impl
 
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
+import com.supwisdom.dlpay.api.bean.YnrccChkfileBean
 import com.supwisdom.dlpay.api.dao.TransactionChkdtlDao
 import com.supwisdom.dlpay.api.dao.TransactionChkfileDao
+import com.supwisdom.dlpay.api.domain.TTransactionChkdtl
 import com.supwisdom.dlpay.api.domain.TTransactionChkfile
 import com.supwisdom.dlpay.api.service.TransactionReconciliationService
+import com.supwisdom.dlpay.exception.TransactionCheckException
+import com.supwisdom.dlpay.framework.dao.BusinessparaDao
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.tenant.TenantContext
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import com.supwisdom.dlpay.util.ConstantUtil
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
 
@@ -13,10 +22,81 @@
     private lateinit var transactionChkfileDao: TransactionChkfileDao
     @Autowired
     private lateinit var transactionChkdtlDao: TransactionChkdtlDao
+    @Autowired
+    private lateinit var systemUtilService: SystemUtilService
+    @Autowired
+    private lateinit var businessparaDao: BusinessparaDao
 
     override fun getTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile? {
         return transactionChkfileDao.getByAccdateAndSourcetype(accdate, sourcetype)
     }
 
+    override fun doInitTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile {
+        return transactionChkfileDao.getByAccdateAndSourcetype(accdate, sourcetype).let {
+            if (it != null) {
+                if (ConstantUtil.CHKFILE_STATUS_INIT != it.status)
+                    throw TransactionCheckException(TradeErrorCode.BUSINESS_DEAL_ERROR, "accdate=$accdate,sourcetype=$sourcetype 的chkfile已经存在")
+                it
+            } else {
+                transactionChkfileDao.save(TTransactionChkfile().apply {
+                    this.accdate = accdate
+                    this.sourcetype = sourcetype
+                    this.status = ConstantUtil.CHKFILE_STATUS_INIT
+                    this.result = ConstantUtil.CHKFILE_RESULT_NONE
+                    this.remark = null
+                    this.thirdcnt = 0
+                    this.thirdamt = 0.00
+                    this.localcnt = 0
+                    this.localamt = 0.00
+                    this.lastsaved = systemUtilService.sysdatetime.sysdate
+                    this.tenantid = TenantContext.getTenantSchema()
+                }) //保存init对账文件
+            }
+        }
+    }
+
+    override fun saveOrUpdateTransactionChkfile(chkfile: TTransactionChkfile) {
+        transactionChkfileDao.save(chkfile)
+    }
+
+    override fun saveYnrccTransactionChkDtl(sourcetype: String, accdate: String, bean: YnrccChkfileBean): TTransactionChkdtl {
+        return transactionChkdtlDao.save(TTransactionChkdtl().apply {
+            this.accdate = accdate
+            this.sourcetype = sourcetype
+            this.amount = bean.amount / 100.0
+            this.thirdRefno = bean.agentrefno
+            this.localRefno = bean.refno
+            this.thirdAccdate = bean.agentdate
+            this.transtype = bean.flag
+            this.thirdStatus = bean.status
+            this.remark = null
+            this.extdata = bean.summary
+            this.chkresult = ConstantUtil.CHKDTL_CHKRESULT_UNCHECK
+            this.resolved = null
+            this.lastsaved = systemUtilService.sysdatetime.sysdate
+            this.tenantid = TenantContext.getTenantSchema()
+        })
+    }
+
+    override fun doBatchSaveYnrccTransactionChkDtl(sourcetype: String, accdate: String, list: ArrayList<YnrccChkfileBean>): Boolean {
+        for (bean in list) {
+            saveYnrccTransactionChkDtl(sourcetype, accdate, bean)
+        }
+        return true
+    }
+
+    override fun deleteTransactionChkDtlByAccdateAndSourcetype(accdate: String, sourcetype: String) {
+        transactionChkdtlDao.deleteByAccdateAndSorucetype(accdate, sourcetype)
+    }
+
+    override fun doSuccessTransactionChkfile(chkfile: TTransactionChkfile, remark: String) {
+        val suminfo = transactionChkdtlDao.getTransactionSumInfo(chkfile.accdate, chkfile.sourcetype)
+        chkfile.status = ConstantUtil.CHKFILE_STATUS_UNCHECK
+        chkfile.remark = remark
+        chkfile.thirdcnt = suminfo.totalcnt ?: 0
+        chkfile.thirdamt = suminfo.totalamt ?: 0.0
+        transactionChkfileDao.save(chkfile)
+        businessparaDao.updateBusinessparaValue(YnrccUtil.YNRCC_BILLS_DOWNLOAD_LASTDATE, chkfile.accdate) //更新下载对账单日期
+    }
 
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt
index 2171dee..2326df3 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_reconciliation_service.kt
@@ -1,5 +1,7 @@
 package com.supwisdom.dlpay.api.service
 
+import com.supwisdom.dlpay.api.bean.YnrccChkfileBean
+import com.supwisdom.dlpay.api.domain.TTransactionChkdtl
 import com.supwisdom.dlpay.api.domain.TTransactionChkfile
 import org.springframework.transaction.annotation.Transactional
 
@@ -7,4 +9,23 @@
     @Transactional(rollbackFor = [Exception::class], readOnly = true)
     fun getTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile?
 
+    @Transactional(rollbackFor = [Exception::class])
+    fun doInitTransactionChkfile(accdate: String, sourcetype: String): TTransactionChkfile
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun saveOrUpdateTransactionChkfile(chkfile: TTransactionChkfile)
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun saveYnrccTransactionChkDtl(sourcetype: String, accdate: String, bean: YnrccChkfileBean): TTransactionChkdtl
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doBatchSaveYnrccTransactionChkDtl(sourcetype: String, accdate: String, list: ArrayList<YnrccChkfileBean>): Boolean
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun deleteTransactionChkDtlByAccdateAndSourcetype(accdate: String, sourcetype: String)
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doSuccessTransactionChkfile(chkfile: TTransactionChkfile, reamrk:String)
+
+
 }
\ No newline at end of file
diff --git a/payapi/src/main/resources/data.sql b/payapi/src/main/resources/data.sql
index da276c1..112b98b 100644
--- a/payapi/src/main/resources/data.sql
+++ b/payapi/src/main/resources/data.sql
@@ -512,6 +512,7 @@
 INSERT INTO "tb_syspara" ("paraid", "displayflag", "editflag", "lastsaved", "paraname", "paraunit", "paraval", "remark", "valuetype", "tenantid")
 VALUES (4, 'yes', 1, '20190514165658', '手机端用户过期时间', '秒', null, '手机端用户过期时间(秒)', 'decimal', '{tenantid}');
 
+INSERT INTO "tb_syspara" ("paraid", "displayflag", "editflag", "lastsaved", "paraname", "paraunit", "paraval", "remark", "valuetype", "tenantid")
 VALUES (2019, 'yes', 1, '20190514165658', '与卡管系统对接的应用ID', null, null, '与卡管系统对接的app_id', 'string', '{tenantid}');
 INSERT INTO "tb_syspara" ("paraid", "displayflag", "editflag", "lastsaved", "paraname", "paraunit", "paraval", "remark", "valuetype", "tenantid")
 VALUES (2020, 'yes', 1, '20190514165658', '与卡管系统对接的签名秘钥', null, null, '与卡管系统对接的appkey', 'string', '{tenantid}');