撤销退款逻辑
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/ReverseDtlDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/ReverseDtlDao.java
deleted file mode 100644
index 87b0e77..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/ReverseDtlDao.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.supwisdom.dlpay.api.dao;
-
-import com.supwisdom.dlpay.api.domain.TReverseDtl;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface ReverseDtlDao extends JpaRepository<TReverseDtl, String> {
-
-  @Query("from TReverseDtl t where t.originRefno=?1 and t.billno=?2 ")
-  TReverseDtl findByOriginRefnoAndBillno(String originRefno, String billno);
-}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TReverseDtl.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TReverseDtl.java
deleted file mode 100644
index 93e30b3..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TReverseDtl.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package com.supwisdom.dlpay.api.domain;
-
-import org.hibernate.annotations.GenericGenerator;
-
-import javax.persistence.*;
-import javax.validation.constraints.NotNull;
-
-@Entity
-@Table(name = "TB_REVERSEDTL", indexes = {@Index(name = "TB_REVERSEDTL_UK", unique = true, columnList = "originRefno, billno")})
-public class TReverseDtl {
-  @Id
-  @GenericGenerator(name = "idGenerator", strategy = "uuid")
-  @GeneratedValue(generator = "idGenerator")
-  @Column(name = "ID", nullable = false, length = 32)
-  private String id;
-
-  @Column(name = "ORIGIN_REFNO", length = 20)
-  @NotNull
-  private String originRefno; //原始流水号
-
-  @Column(name = "BILLNO", length = 20)
-  @NotNull
-  private String billno; //业务系统请求流水号
-
-  @Column(name = "TRANSDATE", length = 8)
-  @NotNull
-  private String transdate;
-
-  @Column(name = "TRANSTIME", length = 6)
-  @NotNull
-  private String transtime;
-
-  @Column(name = "REFUND_AMOUNT", precision = 9)
-  private Integer refundAmount; //退款金额
-
-  @Column(name = "REVERSE_FLAG", nullable = false, length = 10)
-  @NotNull
-  private String reverseFlag; //refund, cancel
-
-  @Column(name = "STATUS", nullable = false, length = 20)
-  @NotNull
-  private String status;
-
-  @Column(name = "REMARK", length = 600)
-  private String remark;
-
-  @Column(name = "CREATETIME", length = 14)
-  private String createtime;
-
-  @Column(name = "tenantid", length = 20)
-  private String tenantid = "";
-
-  public String getId() {
-    return id;
-  }
-
-  public void setId(String id) {
-    this.id = id;
-  }
-
-  public String getOriginRefno() {
-    return originRefno;
-  }
-
-  public void setOriginRefno(String originRefno) {
-    this.originRefno = originRefno;
-  }
-
-  public String getBillno() {
-    return billno;
-  }
-
-  public void setBillno(String billno) {
-    this.billno = billno;
-  }
-
-  public String getTransdate() {
-    return transdate;
-  }
-
-  public void setTransdate(String transdate) {
-    this.transdate = transdate;
-  }
-
-  public String getTranstime() {
-    return transtime;
-  }
-
-  public void setTranstime(String transtime) {
-    this.transtime = transtime;
-  }
-
-  public Integer getRefundAmount() {
-    return refundAmount;
-  }
-
-  public void setRefundAmount(Integer refundAmount) {
-    this.refundAmount = refundAmount;
-  }
-
-  public String getReverseFlag() {
-    return reverseFlag;
-  }
-
-  public void setReverseFlag(String reverseFlag) {
-    this.reverseFlag = reverseFlag;
-  }
-
-  public String getStatus() {
-    return status;
-  }
-
-  public void setStatus(String status) {
-    this.status = status;
-  }
-
-  public String getRemark() {
-    return remark;
-  }
-
-  public void setRemark(String remark) {
-    this.remark = remark;
-  }
-
-  public String getCreatetime() {
-    return createtime;
-  }
-
-  public void setCreatetime(String createtime) {
-    this.createtime = createtime;
-  }
-
-  public String getTenantid() {
-    return tenantid;
-  }
-
-  public void setTenantid(String tenantid) {
-    this.tenantid = tenantid;
-  }
-}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/service/SourceTypeService.java b/payapi/src/main/java/com/supwisdom/dlpay/api/service/SourceTypeService.java
index 7b6194f..833eb0a 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/service/SourceTypeService.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/service/SourceTypeService.java
@@ -35,4 +35,10 @@
   @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
   Map<String, String> getConsumePaytypeConfig(String paytype, String shopaccno, boolean anonymousflag, boolean ignoreStatus) throws Exception;
 
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
+  boolean checkCanReverse(String sourcetype) throws Exception;
+
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
+  boolean checkShopCanReverse(String sourcetype, String shopaccno) throws Exception;
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/service/impl/SourceTypeServiceImpl.java b/payapi/src/main/java/com/supwisdom/dlpay/api/service/impl/SourceTypeServiceImpl.java
index 57b9a01..96f3656 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/service/impl/SourceTypeServiceImpl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/service/impl/SourceTypeServiceImpl.java
@@ -166,4 +166,34 @@
     return result;
   }
 
+  @Override
+  public boolean checkCanReverse(String sourcetype) throws Exception {
+    //step1: 判断系统支付能力是否启用
+    TSourceType tSourceType = sourceTypeDao.getBySourceType(sourcetype);
+    if (null == tSourceType) {
+      throw new TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统不支持支付方式[" + sourcetype + "]");
+    } else if (!tSourceType.getReversable()) {
+      throw new TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统不支持支付方式[" + sourcetype + "]的流水冲正或退款");
+    }
+    return true;
+  }
+
+  @Override
+  public boolean checkShopCanReverse(String sourcetype, String shopaccno) throws Exception {
+    TSourceType tSourceType = sourceTypeDao.getBySourceType(sourcetype);
+    if (null == tSourceType) {
+      throw new TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统不支持支付方式[" + sourcetype + "]");
+    } else if (!tSourceType.getReversable()) {
+      throw new TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统不支持支付方式[" + sourcetype + "]的流水冲正或退款功能");
+    }
+
+    TShopSourceType tShopSourceType = shopSourceTypeDao.getById(sourcetype, shopaccno);
+    if (null == tShopSourceType) {
+      throw new TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "该商户[" + shopaccno + "]未启用支付方式[" + sourcetype + "]");
+    } else if (!tShopSourceType.getReverseEnable()) {
+      throw new TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "该商户[" + shopaccno + "]未启用支付方式[" + sourcetype + "]的流水冲正或退款功能");
+    }
+    return true;
+  }
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java
index ef6fea0..77b7116 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java
@@ -36,8 +36,8 @@
   public static final String DTL_STATUS_REFUND = "2"; //已退款
   public static final String DTL_STATUS_PART_REFUND = "3"; //部分退款
 
-  public static final int QUERY_MAX_COUNT = 3; //查询最大次数
-
+  public static final int QUERY_MAX_COUNT = 3; //最大查询次数
+  
   public static final Map<String, String> errcode = new HashMap<>(0);
   static {
     errcode.put("0000", "成功");
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
index 0a2c5d5..78e2834 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
@@ -69,7 +69,7 @@
         try {
             if(qcnt >= YnrccUtil.QUERY_MAX_COUNT){
                 //查询超最大次数
-                logger.error("查询refno=[$refno]流水结果查询超最大次数[${YnrccUtil.QUERY_MAX_COUNT}]")
+                logger.error("查询refno=[$refno]流水结果超最大查询次数[${YnrccUtil.QUERY_MAX_COUNT}]")
                 return
             }
 
@@ -80,9 +80,9 @@
                     //查询成功
                     when {
                         YnrccUtil.DTL_STATUS_SUCCESS == resp.status ->
-                            transactionService.success(refno, resp.bankjourno) //流水成功
+                            transactionService.success(refno, resp.bankjourno, false) //流水成功
                         YnrccUtil.DTL_STATUS_REFUND == resp.status -> {
-                            //流水已退款
+                            //流水已退款 TODO:流水成功后才退款,无查询原成功流水逻辑
                             return
                         }
                         YnrccUtil.DTL_STATUS_PART_REFUND == resp.status -> {
@@ -108,4 +108,5 @@
             ex.printStackTrace()
         }
     }
+
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
index 8361ebb..8ffa2ec 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
@@ -2,7 +2,6 @@
 
 import com.supwisdom.dlpay.api.*
 import com.supwisdom.dlpay.api.bean.*
-import com.supwisdom.dlpay.api.domain.TReverseDtl
 import com.supwisdom.dlpay.api.service.*
 import com.supwisdom.dlpay.citizencard.service.CitizencardPayService
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
@@ -204,26 +203,27 @@
     @PostMapping("/citizencard/payfinish")
     fun citizencardPayinit(@Valid @RequestBody param: CitizenCardPayfinishParam): ResponseEntity<Any> {
         val dtl = transactionService.wip(param.refno)
-        var resp = citizencardPayService.cardPay(dtl.shopDtl.shopaccno, dtl.personDtl.userid, MoneyUtil.YuanToFen(dtl.personDtl.amount), dtl.refno)
-        if (YnrccUtil.CODE_SUCCESS == resp.code) {
-            //成功
-            transactionService.success(param.refno, resp.bankjourno).let {
+        val resp = citizencardPayService.cardPay(dtl.shopDtl.shopaccno, dtl.personDtl.userid, dtl.accdate, MoneyUtil.YuanToFen(dtl.personDtl.amount), dtl.refno)
+        when {
+            YnrccUtil.CODE_SUCCESS == resp.code -> //成功
+                transactionService.success(dtl.refno, resp.bankjourno, false).let {
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .success(CitizenPayResponse(it.refno,
+                                    it.outTradeNo,
+                                    it.shopDtl.amount), "交易确认成功"))
+                }
+            YnrccUtil.CODE_EXCEPTION == resp.code -> {
+                //去查询
+                citizencardQueryResultTask.queryResult(dtl.refno, 0)
                 return ResponseEntity.ok(ResponseBodyBuilder.create()
-                        .success(CitizenPayResponse(it.refno,
-                                it.outTradeNo,
-                                it.shopDtl.amount), "交易确认成功"))
+                        .data("refno", dtl.refno)
+                        .fail(TradeErrorCode.WAIT_QUERY_RESULT, "请查询支付结果"))
             }
-        } else if (YnrccUtil.CODE_EXCEPTION == resp.code) {
-            //去查询
-            citizencardQueryResultTask.queryResult(dtl.refno, 0)
-            return ResponseEntity.ok(ResponseBodyBuilder.create()
-                    .fail(TradeErrorCode.WAIT_QUERY_RESULT, "请查询支付结果"))
-        } else {
-            //失败
-            transactionService.fail(param.refno, resp.message).let {
-                return ResponseEntity.ok(ResponseBodyBuilder.create()
-                        .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${resp.message}"))
-            }
+            else -> //失败
+                transactionService.fail(param.refno, resp.message).let {
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${resp.message}"))
+                }
         }
     }
 
@@ -234,39 +234,60 @@
      * */
     @PostMapping("/paycancel")
     fun payCancel(@Valid @RequestBody param: ConsumePayCancelParam): ResponseEntity<Any> {
-        consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let {mainDtl->
-            //保存撤销请求
-            val reverseDtl = consumePayService.saveInitReverseDtl(TReverseDtl().apply {
-                this.originRefno = mainDtl.refno
-                this.billno = param.billno
-                this.transdate = param.transdate
-                this.transtime = param.transtime
-                this.refundAmount = null
-                this.reverseFlag = TradeDict.REVERSE_FLAG_CANCEL //撤销
-                this.status = TradeDict.DTL_STATUS_INIT
-                this.createtime = systemUtilService.sysdatetime.hostdatetime
-            })
-
-            try {
-                //TODO: 不管撤销怎么样返回成功
-                val builder = TransactionBuilder().apply {
-                    setTransInfo(param.transdate, param.transtime, mainDtl.transCode, mainDtl.sourceType)
-                    setOutTransInfo(mainDtl.outId, param.requestbillno)
+        consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let { mainDtl ->
+            if (mainDtl.sourceType.isNotEmpty()) {
+                //判断能否冲正
+                if (mainDtl.shop) {
+                    consumePayService.checkCanReverse(mainDtl.sourceType, mainDtl.shopDtl.shopaccno)
+                } else {
+                    consumePayService.checkCanReverse(mainDtl.sourceType)
                 }
-                val cancelTrans = builder.cancelInit(mainDtl.refno, transactionService)
-                //fixme: 撤销逻辑
-                if (mainDtl.sourceType.isNotEmpty()) {
-                    // 第三方冲正
-                }
-                transactionService.success(cancelTrans.refno)
+            }
 
-            } catch (ex: Exception) {
-                ex.printStackTrace()
+            val builder = TransactionBuilder().apply {
+                setTransInfo(param.transdate, param.transtime, mainDtl.transCode, mainDtl.sourceType)
+                setOutTransInfo(mainDtl.outId, param.requestbillno)
+            }
+
+            val cancelTrans = builder.cancelInit(mainDtl.refno, transactionService)
+            transactionService.wip(cancelTrans.refno)
+            when {
+                TradeDict.PAYTYPE_BALANCE == mainDtl.sourceType -> {
+                    //余额支付,直接撤销
+                    transactionService.success(cancelTrans.refno)
+
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .success(PayReverseResponse(cancelTrans.refno), "交易撤销成功"))
+
+                }
+                TradeDict.PAYTYPE_CITIZEN_CARD == mainDtl.sourceType -> {
+
+                    val resp = citizencardPayService.cardPayRefund(cancelTrans.refno, cancelTrans.accdate, mainDtl.refno, MoneyUtil.YuanToFen(mainDtl.personDtl.amount))
+                    when {
+                        YnrccUtil.CODE_SUCCESS == resp.code -> {
+                            transactionService.success(cancelTrans.refno, resp.bankjourno, false)
+
+                            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                                    .success(PayReverseResponse(cancelTrans.refno), "交易撤销成功"))
+                        }
+                        YnrccUtil.CODE_EXCEPTION == resp.code -> {
+                            //待查询
+                            citizencardQueryResultTask.queryResult(cancelTrans.refno, 0)
+                            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                                    .data("cancelRefno", cancelTrans.refno)
+                                    .fail(TradeErrorCode.WAIT_QUERY_RESULT, "请查询撤销结果"))
+                        }
+                        else -> transactionService.fail(cancelTrans.refno, resp.message).let {
+                            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                                    .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易撤销失败-${resp.message}"))
+                        }
+                    }
+                }
+                else -> return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "暂不支持支付方式[${mainDtl.sourceType}]的流水撤销"))
             }
 
 
-            return ResponseEntity.ok(ResponseBodyBuilder.create()
-                    .success(PayReverseResponse(""), "交易确认成功"))
         } ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
                 .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在"))
     }
@@ -278,37 +299,57 @@
      * */
     @PostMapping("/payrefund")
     fun payRefund(@Valid @RequestBody param: ConsumePayRefundParam): ResponseEntity<Any> {
-        consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let {mainDtl->
-            //保存退款请求
-            val reverseDtl = consumePayService.saveInitReverseDtl(TReverseDtl().apply {
-                this.originRefno = mainDtl.refno
-                this.billno = param.billno
-                this.transdate = param.transdate
-                this.transtime = param.transtime
-                this.refundAmount = null
-                this.reverseFlag = TradeDict.REVERSE_FLAG_REFUND //撤销
-                this.status = TradeDict.DTL_STATUS_INIT
-                this.createtime = systemUtilService.sysdatetime.hostdatetime
-            })
-
-            try{
-                val builder = TransactionBuilder().apply {
-                    setTransInfo(param.transdate, param.transtime, mainDtl.transCode, mainDtl.sourceType)
-                    setOutTransInfo(mainDtl.outId, param.requestbillno)
+        consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let { mainDtl ->
+            if (mainDtl.sourceType.isNotEmpty()) {
+                //判断能否冲正
+                if (mainDtl.shop) {
+                    consumePayService.checkCanReverse(mainDtl.sourceType, mainDtl.shopDtl.shopaccno)
+                } else {
+                    consumePayService.checkCanReverse(mainDtl.sourceType)
                 }
-                val refundTrans = builder.refundInit(mainDtl.refno,
-                        param.refundAmount / 100.0, transactionService)
-                //fixme: 撤销逻辑
-                if (mainDtl.sourceType.isNotEmpty()) {
-                    // 第三方冲正
-                }
-                transactionService.success(refundTrans.refno)
-            }catch (ex :Exception){
-                ex.printStackTrace()
             }
 
-            return ResponseEntity.ok(ResponseBodyBuilder.create()
-                    .success(PayReverseResponse(""), "交易确认成功"))
+            val builder = TransactionBuilder().apply {
+                setTransInfo(param.transdate, param.transtime, mainDtl.transCode, mainDtl.sourceType)
+                setOutTransInfo(mainDtl.outId, param.requestbillno)
+            }
+            val refundTrans = builder.refundInit(mainDtl.refno, param.refundAmount / 100.0, transactionService)
+            transactionService.wip(refundTrans.refno)
+            when {
+                TradeDict.PAYTYPE_BALANCE == mainDtl.sourceType -> {
+                    //余额支付,直接撤销
+                    transactionService.success(refundTrans.refno)
+
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .success(PayReverseResponse(refundTrans.refno), "交易退款成功"))
+
+                }
+                TradeDict.PAYTYPE_CITIZEN_CARD == mainDtl.sourceType -> {
+
+                    val resp = citizencardPayService.cardPayRefund(refundTrans.refno, refundTrans.accdate, mainDtl.refno, MoneyUtil.YuanToFen(mainDtl.personDtl.amount))
+                    when {
+                        YnrccUtil.CODE_SUCCESS == resp.code -> {
+                            transactionService.success(refundTrans.refno, resp.bankjourno, false)
+
+                            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                                    .success(PayReverseResponse(refundTrans.refno), "交易退款成功"))
+                        }
+                        YnrccUtil.CODE_EXCEPTION == resp.code -> {
+                            //待查询
+                            citizencardQueryResultTask.queryResult(refundTrans.refno, 0)
+                            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                                    .data("refundRefno", refundTrans.refno)
+                                    .fail(TradeErrorCode.WAIT_QUERY_RESULT, "请查询退款结果"))
+                        }
+                        else -> transactionService.fail(refundTrans.refno, resp.message).let {
+                            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                                    .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易退款失败-${resp.message}"))
+                        }
+                    }
+                }
+                else -> return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "暂不支持支付方式[${mainDtl.sourceType}]的流水退款"))
+            }
         } ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
                 .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在"))
     }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt
index 02533ab..29867ae 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt
@@ -1,6 +1,5 @@
 package com.supwisdom.dlpay.api.service
 
-import com.supwisdom.dlpay.api.domain.TReverseDtl
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.framework.domain.TDictionary
 import org.springframework.transaction.annotation.Propagation
@@ -22,9 +21,7 @@
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class], readOnly = true)
     fun getDtltypeDictionary(dictval:String, dicttype:String):TDictionary
 
-    @Transactional(rollbackFor = [Exception::class])
-    fun saveOrUpdateReverseDtl(revDtl: TReverseDtl): TReverseDtl
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class], readOnly = true)
+    fun checkCanReverse(sourcetype: String, shopaccno: String? = null): Boolean
 
-    //没有事务
-    fun saveInitReverseDtl(revDtl: TReverseDtl): TReverseDtl
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt
index 0396d36..8830fcd 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt
@@ -1,21 +1,15 @@
 package com.supwisdom.dlpay.api.service.impl
 
-import com.supwisdom.dlpay.api.dao.ReverseDtlDao
 import com.supwisdom.dlpay.api.dao.TransactionMainDao
-import com.supwisdom.dlpay.api.domain.TReverseDtl
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
 import com.supwisdom.dlpay.api.service.ConsumePayService
 import com.supwisdom.dlpay.api.service.SourceTypeService
-import com.supwisdom.dlpay.exception.TransactionProcessException
+
 import com.supwisdom.dlpay.framework.dao.DictionaryDao
 import com.supwisdom.dlpay.framework.domain.TDictionary
-import com.supwisdom.dlpay.framework.tenant.TenantContext
-import com.supwisdom.dlpay.framework.util.Dictionary
 import com.supwisdom.dlpay.framework.util.StringUtil
-import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.dao.DataAccessException
 import org.springframework.stereotype.Service
 
 @Service
@@ -26,8 +20,6 @@
     lateinit var transactionMainDao: TransactionMainDao
     @Autowired
     lateinit var dictionaryDao: DictionaryDao
-    @Autowired
-    lateinit var reverseDtlDao: ReverseDtlDao
 
     override fun checkShopPaytype(shopaccno: String, sourceType: String, anonymousflag: Boolean?): Boolean {
         return sourceTypeService.checkShopSourceType(shopaccno, sourceType, true == anonymousflag)
@@ -54,21 +46,11 @@
                 ?: throw RequestParamCheckException("未识别流水类别[$dictval]")
     }
 
-    override fun saveOrUpdateReverseDtl(revDtl: TReverseDtl): TReverseDtl {
-        if (StringUtil.isEmpty(revDtl.tenantid)) {
-            revDtl.tenantid = TenantContext.getTenantSchema()
-        }
-        return reverseDtlDao.save(revDtl)
-    }
-
-    override fun saveInitReverseDtl(revDtl: TReverseDtl): TReverseDtl {
-        return try {
-            saveOrUpdateReverseDtl(revDtl)
-        } catch (ex: DataAccessException) {
-            //唯一索引冲突,其他异常抛出
-            reverseDtlDao.findByOriginRefnoAndBillno(revDtl.originRefno, revDtl.billno)
-                    ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "保存撤销或退款请求失败")
+    override fun checkCanReverse(sourcetype: String, shopaccno: String?): Boolean {
+        return if (StringUtil.isEmpty(shopaccno)) {
+            sourceTypeService.checkCanReverse(sourcetype)
+        } else {
+            sourceTypeService.checkShopCanReverse(sourcetype, shopaccno);
         }
     }
-
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
index 99f6948..ad08dab 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
@@ -344,7 +344,7 @@
         transaction.sourceTypeRefno = sorcetypeRefno
     }
 
-    override fun success(refno: String, sourcetypeRefno: String): TTransactionMain {
+    override fun success(refno: String, sourcetypeRefno: String, accdateUpdate: Boolean?): TTransactionMain {
         val transaction = transactionMainDao.findByRefnoForUpdate(refno)
                 ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "参考号<$refno>错误,流水不存在")
 
@@ -353,16 +353,22 @@
             throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误,流水已结束")
         }
         transaction.status = TradeDict.DTL_STATUS_SUCCESS
-        transaction.accdate = systemUtilService.accdate
+        if (true == accdateUpdate) {
+            transaction.accdate = systemUtilService.accdate
+        }
         transactionOnSuccess(transaction, sourcetypeRefno, false)
 
+        if(transaction.reverseRefno.isNotEmpty()){
+            //TODO:更新原流水信息
+        }
+
         transaction.endTime = systemUtilService.sysdatetime.sysdate
         transactionMainDao.save(transaction)
         return transaction
     }
 
     override fun success(refno: String): TTransactionMain {
-        return success(refno, "")
+        return success(refno, "", true)
     }
 
     //////////////////////////////////////////////////////////////////
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
index 011244a..76abfd8 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
@@ -27,7 +27,7 @@
     fun fail(refno: String, remark: String): TTransactionMain
 
     @Transactional
-    fun success(refno: String, sourcetypeRefno: String): TTransactionMain
+    fun success(refno: String, sourcetypeRefno: String, accdateUpdate: Boolean? = true): TTransactionMain
 
     @Transactional
     fun success(refno: String): TTransactionMain
@@ -84,8 +84,8 @@
         return transactionService.fail(refno, remark)
     }
 
-    fun success(refno: String, sourcetypeRefno: String): TTransactionMain {
-        return transactionService.success(refno, sourcetypeRefno).also {
+    fun success(refno: String, sourcetypeRefno: String, accdateUpdate: Boolean? = true): TTransactionMain {
+        return transactionService.success(refno, sourcetypeRefno, accdateUpdate).also {
             if (it.shop) {
                 shopAccBalanceAsyncTask.updateShopBalance(it.refno)
             }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/citizencard_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/citizencard_service.kt
index 49dbe4d..326f44a 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/citizencard_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/citizencard_service.kt
@@ -7,9 +7,9 @@
 
     fun signCard(bankcardno: String, username: String, idtype: String, idno: String, phone: String, transtype: String): DlpayResp
 
-    fun cardPay(shopaccno: String, userid: String, amount: Int, refno: String): DlpayResp
+    fun cardPay(shopaccno: String, userid: String, accdate: String, amount: Int, refno: String): DlpayResp
 
-    fun cardPayRefund(refno: String, orignRefno: String, amount: Int): DlpayResp
+    fun cardPayRefund(refno: String, accdate: String, orignRefno: String, amount: Int): DlpayResp
 
     fun queryResult(orignRefno: String): DlpayResp
 
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/impl/citizencard_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/impl/citizencard_service_impl.kt
index 2439bcf..8868a0b 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/impl/citizencard_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/impl/citizencard_service_impl.kt
@@ -152,7 +152,7 @@
         }
     }
 
-    override fun cardPay(shopaccno: String, userid: String, amount: Int, refno: String): DlpayResp {
+    override fun cardPay(shopaccno: String, userid: String, accdate: String, amount: Int, refno: String): DlpayResp {
         var resp = DlpayResp()
         val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_CITIZEN_CARD, shopaccno, false, false)
         if (!checkCitizencardConfig(config, resp)) {
@@ -197,7 +197,7 @@
         val params = hashMapOf<String, String>()
         params.plus(mapOf(
                 "transcode" to YnrccUtil.BANKCARD_PAY_TRANSCODE,
-                "transdate" to systime.hostdate,
+                "transdate" to accdate, //我们的记账日期
                 "transtime" to systime.hosttime,
                 "refno" to refno,
                 "categorie" to YnrccUtil.DLPAY_CATEGORIE,
@@ -238,7 +238,7 @@
         }
     }
 
-    override fun cardPayRefund(refno: String, orignRefno: String, amount: Int): DlpayResp {
+    override fun cardPayRefund(refno: String, accdate: String, orignRefno: String, amount: Int): DlpayResp {
         var resp = DlpayResp()
         val config = sourceTypeService.getChargePaytypeConfig(TradeDict.PAYTYPE_CITIZEN_CARD, true)
         if (!checkCitizencardConfig(config, resp)) {
@@ -249,7 +249,7 @@
         val params = hashMapOf<String, String>()
         params.plus(mapOf(
                 "transcode" to YnrccUtil.BANKCARD_PAYREFUND_TRANSCODE,
-                "transdate" to systime.hostdate,
+                "transdate" to accdate, //我们的记账日期
                 "transtime" to systime.hosttime,
                 "refno" to refno,
                 "refund_refno" to orignRefno,