修改农信社接口定义,完善退款逻辑
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentCode.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentCode.java
new file mode 100644
index 0000000..a203a67
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentCode.java
@@ -0,0 +1,34 @@
+package com.supwisdom.dlpay.agent;
+
+public enum AgentCode {
+  SUCCESS("success", "成功"),
+  FAIL("fail", "交易失败"),
+  REFNO_NOT_EXISTS("refno_not_exists", "指定流水不存在"),
+  ILLEGAL_DATA("illege_data", "数据不合法,不能交易"),
+  SERVER_INTERNAL_ERROR("server_internal_error", "交易系统错误"),
+  NEED_QUERY("need_query", "交易未完成,请查询"),
+  WAIT_NOTIFY("wait_notify", "交易已发起,等待通知"),
+  SHORT_OF_BALANCE("short_of_balance", "余额不足"),
+  COMMON_ERROR("common_error", "其它错误");
+
+  AgentCode(String code, String msg) {
+    this.code = code;
+    this.msg = msg;
+  }
+
+  public String value() {
+    return this.code;
+  }
+
+  public String message() {
+    return this.msg;
+  }
+
+  private String code;
+  private String msg;
+
+  @Override
+  public String toString() {
+    return code;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentConst.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentConst.java
new file mode 100644
index 0000000..6807f6b
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentConst.java
@@ -0,0 +1,5 @@
+package com.supwisdom.dlpay.agent;
+
+public class AgentConst {
+
+}
\ No newline at end of file
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentPayService.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentPayService.java
new file mode 100644
index 0000000..5ba80d6
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentPayService.java
@@ -0,0 +1,13 @@
+package com.supwisdom.dlpay.agent;
+
+import com.supwisdom.dlpay.api.domain.TTransactionMain;
+
+public interface AgentPayService {
+  AgentResponse pay(TTransactionMain transaction);
+
+  AgentResponse cancel(TTransactionMain transaction);
+
+  AgentResponse refund(TTransactionMain transaction);
+
+  AgentResponse query(TTransactionMain transaction);
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
new file mode 100644
index 0000000..79bd0be
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
@@ -0,0 +1,14 @@
+package com.supwisdom.dlpay.agent;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class AgentResponse {
+  private AgentCode code;
+  private String agentCode;
+  private String agentMsg;
+
+  private String agentRefno;
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/DlpayResp.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/DlpayResp.java
similarity index 97%
rename from payapi/src/main/java/com/supwisdom/dlpay/api/bean/DlpayResp.java
rename to payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/DlpayResp.java
index 3f01175..ba28bb8 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/DlpayResp.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/DlpayResp.java
@@ -1,4 +1,4 @@
-package com.supwisdom.dlpay.api.bean;
+package com.supwisdom.dlpay.agent.citizencard;
 
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccRespCode.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccRespCode.java
new file mode 100644
index 0000000..b1512d5
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccRespCode.java
@@ -0,0 +1,13 @@
+package com.supwisdom.dlpay.agent.citizencard;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class YnrccRespCode {
+  private String code;
+  private String msg;
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccUtil.java
new file mode 100644
index 0000000..5b28763
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccUtil.java
@@ -0,0 +1,81 @@
+package com.supwisdom.dlpay.agent.citizencard;
+
+import com.supwisdom.dlpay.agent.AgentCode;
+import org.springframework.data.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class YnrccUtil {
+  public static final String BANKCARD_BIND_TRANSCODE = "BC5510";
+  public static final String BANKCARD_SIGN_TRANSCODE = "BC5511";
+  public static final String BANKCARD_PAY_TRANSCODE = "BC5512";
+  public static final String BANKCARD_PAYREFUND_TRANSCODE = "BC5513";
+  public static final String BANKCARD_QUERYRESULT_TRANSCODE = "BC5514";
+  public static final String BANKCARD_CHKFILE_TRANSCODE = "BC5515";
+
+  public static final String DLPAY_CATEGORIE = "C001"; //消费类别
+
+  public static final String YNRCC_ANGENT_URL = "ynrcc.agent.url"; //农商行前置url
+  public static final String YNRCC_SIGNKEY = "ynrcc.agent.signkey"; //农商行前置md5key
+  public static final String YNRCC_MERCHANT_BANKCARDNO = "merchant.bankcardno";
+  public static final String YNRCC_MERCHANT_BANKACCNAME = "merchant.bankaccname";
+
+  public static final String PARAM_CONFIG_ERROR = "90000"; // 参数未配置
+  public static final String PARAM_VALUE_ERROR = "90001"; // 参数值错误
+
+  public static final int AGENT_CONNECT_TIMEOUT = 20;
+  public static final String TRANSTYPE_SIGNCARD = "1"; //签约
+  public static final String TRANSTYPE_UNSIGNCARD = "2"; //解约
+
+  public static final String CODE_SUCCESS = "0000"; //成功
+  public static final String CODE_NOT_EXISTS = "0401"; //流水不存在
+  public static final String CODE_EXCEPTION = "10000"; //异常
+
+  //查询接口返回的流水状态
+  public static final String DTL_STATUS_SUCCESS = "0"; //成功
+  public static final String DTL_STATUS_FAIL = "1"; //失败
+  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 List<Pair<AgentCode, YnrccRespCode>> errcode = new ArrayList<>(0);
+
+  static {
+    errcode.add(Pair.of(AgentCode.SUCCESS, new YnrccRespCode("0000", "成功")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0101", "手机号不一致")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0102", "无预留手机号")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0103", "证件类型不一致")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0104", "证件号码不一致")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0105", "户名不符")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0106", "卡状态异常")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0107", "无此卡号")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0108", "已存在签约信息,与签约证件号码不符")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0109", "已存在签约信息,与签约证件类型不符")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0110", "已存在签约信息,与签约户名不符")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0111", "已存在签约信息,与签约手机号不符")));
+
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0201", "未进行银行卡绑定")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0202", "无效的交易类型")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0301", "未签约")));
+    errcode.add(Pair.of(AgentCode.SHORT_OF_BALANCE, new YnrccRespCode("0302", "余额不足")));
+    errcode.add(Pair.of(AgentCode.SERVER_INTERNAL_ERROR, new YnrccRespCode("0303", "MD5校验失败")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0304", "该卡号已经解约,不允许重复解约")));
+    errcode.add(Pair.of(AgentCode.FAIL, new YnrccRespCode("0401", "原始流水不存在")));
+    errcode.add(Pair.of(AgentCode.FAIL, new YnrccRespCode("0402", "原始流水未成功")));
+    errcode.add(Pair.of(AgentCode.FAIL, new YnrccRespCode("0403", "原始流水已退款")));
+    errcode.add(Pair.of(AgentCode.SHORT_OF_BALANCE, new YnrccRespCode("0404", "商户账户余额不足")));
+    errcode.add(Pair.of(AgentCode.FAIL, new YnrccRespCode("0405", "不在退款时间范围内")));
+    errcode.add(Pair.of(AgentCode.SUCCESS, new YnrccRespCode("0406", "当日无交易明细")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("0407", "非大理市民卡,不允许交易")));
+    errcode.add(Pair.of(AgentCode.FAIL, new YnrccRespCode("0408", "同一请求流水号不允许重复提交")));
+    errcode.add(Pair.of(AgentCode.COMMON_ERROR, new YnrccRespCode("4444", "其他错误")));
+    errcode.add(Pair.of(AgentCode.NEED_QUERY, new YnrccRespCode(CODE_EXCEPTION, "待查询")));
+    errcode.add(Pair.of(AgentCode.SERVER_INTERNAL_ERROR, new YnrccRespCode(PARAM_CONFIG_ERROR, "{message}")));
+    errcode.add(Pair.of(AgentCode.SERVER_INTERNAL_ERROR, new YnrccRespCode(PARAM_VALUE_ERROR, "{message}")));
+  }
+
+
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java
index 476a1fa..3fb3544 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java
@@ -16,6 +16,10 @@
   @Query(value = "select t from TTransactionMain t where t.refno = ?1")
   TTransactionMain findByRefnoForUpdate(String refno);
 
+  @Lock(LockModeType.OPTIMISTIC)
+  @Query(value = "select t from TTransactionMain  t where t.refno = ?1")
+  TTransactionMain findByRefnoNoLock(String refno);
+
 
   TTransactionMain findByRefno(String refno);
 
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java
index 8435ce1..8d34d10 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java
@@ -2,6 +2,7 @@
 
 import com.supwisdom.dlpay.framework.util.Subject;
 import com.supwisdom.dlpay.framework.util.TradeDict;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 
 import javax.persistence.*;
 import javax.validation.constraints.Digits;
@@ -83,6 +84,10 @@
   @Column(name = "end_time")
   private Timestamp endTime;
 
+  @Column(name = "update_time")
+  @Version
+  private Timestamp updateTime;
+
   @Column(name = "reverse_type", nullable = false, length = 10)
   @NotNull
   private String reverseType = TradeDict.REVERSE_FLAG_NONE; // 流水标识, none - 正常交易流水, cancel - 撤销流水, refund - 退款流水
@@ -379,4 +384,12 @@
   public void setTenantid(String tenantid) {
     this.tenantid = tenantid;
   }
+
+  public Timestamp getUpdateTime() {
+    return updateTime;
+  }
+
+  public void setUpdateTime(Timestamp updateTime) {
+    this.updateTime = updateTime;
+  }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
index 57f5b3b..85c2578 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
@@ -96,6 +96,7 @@
    * - refund : 手工撤销
    */
   public static final String REVERSE_FLAG_NONE = "none";
+  public static final String REVERSE_FLAG_WIP = "wip";
   public static final String REVERSE_FLAG_CANCEL = "cancel";
   public static final String REVERSE_FLAG_REFUND = "refund";
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java
deleted file mode 100644
index 77b7116..0000000
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.supwisdom.dlpay.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-
-public class YnrccUtil {
-  public static final String BANKCARD_BIND_TRANSCODE = "BC5510";
-  public static final String BANKCARD_SIGN_TRANSCODE = "BC5511";
-  public static final String BANKCARD_PAY_TRANSCODE = "BC5512";
-  public static final String BANKCARD_PAYREFUND_TRANSCODE = "BC5513";
-  public static final String BANKCARD_QUERYRESULT_TRANSCODE = "BC5514";
-  public static final String BANKCARD_CHKFILE_TRANSCODE = "BC5515";
-
-  public static final String DLPAY_CATEGORIE = "C001"; //消费类别
-
-  public static final String YNRCC_ANGENT_URL = "ynrcc.agent.url"; //农商行前置url
-  public static final String YNRCC_SIGNKEY = "ynrcc.agent.signkey"; //农商行前置md5key
-  public static final String YNRCC_MERCHANT_BANKCARDNO = "merchant.bankcardno";
-  public static final String YNRCC_MERCHANT_BANKACCNAME = "merchant.bankaccname";
-
-  public static final String PARAM_CONFIG_ERROR = "90000"; // 参数未配置
-  public static final String PARAM_VALUE_ERROR = "90001"; // 参数值错误
-
-  public static final int AGENT_CONNECT_TIMEOUT = 20;
-  public static final String TRANSTYPE_SIGNCARD = "1"; //签约
-  public static final String TRANSTYPE_UNSIGNCARD = "2"; //解约
-
-  public static final String CODE_SUCCESS = "0000"; //成功
-  public static final String CODE_NOT_EXISTS = "0401"; //流水不存在
-  public static final String CODE_EXCEPTION = "10000"; //异常
-
-  //查询接口返回的流水状态
-  public static final String DTL_STATUS_SUCCESS = "0"; //成功
-  public static final String DTL_STATUS_FAIL = "1"; //失败
-  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 Map<String, String> errcode = new HashMap<>(0);
-  static {
-    errcode.put("0000", "成功");
-    errcode.put("0101", "手机号不一致");
-    errcode.put("0102", "无预留手机号");
-    errcode.put("0103", "证件类型不一致");
-    errcode.put("0104", "证件号码不一致");
-    errcode.put("0105", "户名不符");
-    errcode.put("0106", "卡状态异常");
-    errcode.put("0107", "无此卡号");
-    errcode.put("0108", "已存在签约信息,与签约证件号码不符");
-    errcode.put("0109", "已存在签约信息,与签约证件类型不符");
-    errcode.put("0110", "已存在签约信息,与签约户名不符");
-    errcode.put("0111", "已存在签约信息,与签约手机号不符");
-
-    errcode.put("0201", "未进行银行卡绑定");
-    errcode.put("0202", "无效的交易类型");
-    errcode.put("0301", "未签约");
-    errcode.put("0302", "余额不足");
-    errcode.put("0303", "MD5校验失败");
-    errcode.put("0304", "该卡号已经解约,不允许重复解约");
-    errcode.put("0401", "原始流水不存在");
-    errcode.put("0402", "原始流水未成功");
-    errcode.put("0403", "原始流水已退款");
-    errcode.put("0404", "商户账户余额不足");
-    errcode.put("0405", "不在退款时间范围内");
-    errcode.put("0406", "当日无交易明细");
-    errcode.put("0407", "非大理市民卡,不允许交易");
-    errcode.put("0408", "同一请求流水号不允许重复提交");
-    errcode.put("4444", "其他错误");
-  }
-
-
-
-
-}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/citizencard_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/citizencard_service.kt
new file mode 100644
index 0000000..8e02f9d
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/citizencard_service.kt
@@ -0,0 +1,86 @@
+package com.supwisdom.dlpay.agent.service
+
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentPayService
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.citizencard.DlpayResp
+import com.supwisdom.dlpay.agent.citizencard.YnrccRespCode
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.framework.util.MoneyUtil
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Component
+
+interface CitizencardPayService {
+    fun bindCard(bankcardno: String, username: String, idtype: String, idno: String, phone: String): DlpayResp
+
+    fun signCard(bankcardno: String, username: String, idtype: String, idno: String, phone: String, transtype: String): DlpayResp
+
+    fun cardPay(shopaccno: String, userid: String, accdate: String, amount: Int, refno: String): DlpayResp
+
+    fun cardPayRefund(refno: String, accdate: String, orignRefno: String, amount: Int): DlpayResp
+
+    fun queryResult(orignRefno: String): DlpayResp
+
+    fun getChkfilename(checkdate: String, merchantBankcardno: String?): DlpayResp
+
+}
+
+@Component
+class CitizenCardPayAgent : AgentPayService {
+    @Autowired
+    private lateinit var citizencardPayService: CitizencardPayService
+
+    private fun agentCode(code: String, msg: String?): org.springframework.data.util.Pair<AgentCode, YnrccRespCode> {
+        return YnrccUtil.errcode.firstOrNull {
+            it.second.code == code
+        }?.let {
+            org.springframework.data.util.Pair.of(it.first, YnrccRespCode(
+                    code, it.second.msg.replace("{message}", msg ?: "未知")
+            ))
+        } ?: org.springframework.data.util.Pair.of(AgentCode.COMMON_ERROR,
+                YnrccRespCode(code, msg ?: "未知"))
+    }
+
+    override fun pay(transaction: TTransactionMain): AgentResponse {
+        val resp = citizencardPayService.cardPay(transaction.shopDtl.shopaccno, transaction.personDtl.userid, transaction.accdate,
+                MoneyUtil.YuanToFen(transaction.personDtl.amount), transaction.refno)
+
+        return AgentResponse().also {
+            val code = agentCode(resp.code, resp.message)
+            it.code = code.first
+            it.agentCode = code.second.code
+            it.agentMsg = code.first.message() + "-" + code.second.msg
+            it.agentRefno = resp.bankjourno
+        }
+    }
+
+    override fun cancel(transaction: TTransactionMain): AgentResponse {
+        return refund(transaction)
+    }
+
+    override fun refund(transaction: TTransactionMain): AgentResponse {
+        val resp = citizencardPayService.cardPayRefund(transaction.refno, transaction.accdate,
+                transaction.reverseRefno, MoneyUtil.YuanToFen(transaction.personDtl.amount))
+
+        return AgentResponse().also {
+            val code = agentCode(resp.code, resp.message)
+            it.code = code.first
+            it.agentCode = code.second.code
+            it.agentMsg = code.first.message() + "-" + code.second.msg
+            it.agentRefno = resp.bankjourno
+        }
+    }
+
+    override fun query(transaction: TTransactionMain): AgentResponse {
+        val resp = citizencardPayService.queryResult(transaction.refno)
+
+        return AgentResponse().also {
+            val code = agentCode(resp.code, resp.message)
+            it.code = code.first
+            it.agentCode = code.second.code
+            it.agentMsg = code.first.message() + "-" + code.second.msg
+            it.agentRefno = resp.bankjourno
+        }
+    }
+}
\ No newline at end of file
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/agent/service/impl/citizencard_service_impl.kt
similarity index 97%
rename from payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/impl/citizencard_service_impl.kt
rename to payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/citizencard_service_impl.kt
index 8868a0b..554ece6 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/impl/citizencard_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/citizencard_service_impl.kt
@@ -1,17 +1,17 @@
-package com.supwisdom.dlpay.citizencard.service.impl
+package com.supwisdom.dlpay.agent.service.impl
 
 import com.google.gson.Gson
 import com.sun.jersey.api.client.Client
 import com.sun.jersey.api.client.ClientResponse
-import com.supwisdom.dlpay.api.bean.DlpayResp
+import com.supwisdom.dlpay.agent.citizencard.DlpayResp
 import com.supwisdom.dlpay.api.service.CardService
 import com.supwisdom.dlpay.api.service.SourceTypeService
 import com.supwisdom.dlpay.api.service.UserService
 import com.supwisdom.dlpay.api.types.IDTypes
-import com.supwisdom.dlpay.citizencard.service.CitizencardPayService
+import com.supwisdom.dlpay.agent.service.CitizencardPayService
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.util.*
-import com.supwisdom.dlpay.util.YnrccUtil
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
 import mu.KotlinLogging
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
@@ -339,7 +339,7 @@
         val refno = systemUtilService.refno
         val params = hashMapOf<String, String>()
         params.plus(mapOf(
-                "transcode" to YnrccUtil.BANKCARD_BIND_TRANSCODE,
+                "transcode" to YnrccUtil.BANKCARD_CHKFILE_TRANSCODE,
                 "transdate" to systime.hostdate,
                 "transtime" to systime.hosttime,
                 "refno" to refno,
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 78e2834..73f8ba6 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
@@ -2,8 +2,8 @@
 
 import com.supwisdom.dlpay.api.repositories.ShopaccService
 import com.supwisdom.dlpay.api.service.TransactionServiceProxy
-import com.supwisdom.dlpay.citizencard.service.CitizencardPayService
-import com.supwisdom.dlpay.util.YnrccUtil
+import com.supwisdom.dlpay.agent.service.CitizencardPayService
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
 import mu.KotlinLogging
 import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
 import org.springframework.beans.factory.annotation.Autowired
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 8ffa2ec..2760298 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
@@ -1,13 +1,16 @@
 package com.supwisdom.dlpay.api.controller
 
+import com.supwisdom.dlpay.agent.AgentCode
 import com.supwisdom.dlpay.api.*
 import com.supwisdom.dlpay.api.bean.*
 import com.supwisdom.dlpay.api.service.*
-import com.supwisdom.dlpay.citizencard.service.CitizencardPayService
+import com.supwisdom.dlpay.agent.service.CitizencardPayService
+import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.util.*
-import com.supwisdom.dlpay.util.YnrccUtil
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
+import com.supwisdom.dlpay.agent.service.CitizenCardPayAgent
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.http.ResponseEntity
 import org.springframework.web.bind.annotation.PostMapping
@@ -33,6 +36,9 @@
     lateinit var cardService: CardService
     @Autowired
     lateinit var citizencardPayService: CitizencardPayService
+
+    @Autowired
+    private lateinit var citizenCardPayAgent: CitizenCardPayAgent
     @Autowired
     lateinit var citizencardQueryResultTask: CitizencardQueryResultTask
 
@@ -203,26 +209,30 @@
     @PostMapping("/citizencard/payfinish")
     fun citizencardPayinit(@Valid @RequestBody param: CitizenCardPayfinishParam): ResponseEntity<Any> {
         val dtl = transactionService.wip(param.refno)
-        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 {
+        val resp = citizenCardPayAgent.pay(dtl)
+        when (resp.code) {
+            AgentCode.SUCCESS ->
+                transactionService.success(dtl.refno, resp.agentRefno, false).let {
                     return ResponseEntity.ok(ResponseBodyBuilder.create()
                             .success(CitizenPayResponse(it.refno,
                                     it.outTradeNo,
                                     it.shopDtl.amount), "交易确认成功"))
+
+
                 }
-            YnrccUtil.CODE_EXCEPTION == resp.code -> {
+            AgentCode.NEED_QUERY -> {
                 //去查询
                 citizencardQueryResultTask.queryResult(dtl.refno, 0)
                 return ResponseEntity.ok(ResponseBodyBuilder.create()
-                        .data("refno", dtl.refno)
-                        .fail(TradeErrorCode.WAIT_QUERY_RESULT, "请查询支付结果"))
+                        .fail(CitizenPayResponse(dtl.refno,
+                                dtl.outTradeNo,
+                                dtl.shopDtl.amount), TradeErrorCode.WAIT_QUERY_RESULT, "请查询支付结果"))
             }
             else -> //失败
-                transactionService.fail(param.refno, resp.message).let {
+                transactionService.fail(param.refno, resp.agentMsg).let {
                     return ResponseEntity.ok(ResponseBodyBuilder.create()
-                            .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${resp.message}"))
+                            .fail(CitizenPayResponse(dtl.refno, dtl.outTradeNo, dtl.shopDtl.amount),
+                                    TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${resp.agentMsg}"))
                 }
         }
     }
@@ -261,35 +271,38 @@
 
                 }
                 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)
+                    val resp = citizenCardPayAgent.pay(cancelTrans)
+                    when (resp.code) {
+                        AgentCode.SUCCESS -> {
+                            transactionService.success(cancelTrans.refno, resp.agentRefno, false)
 
                             return ResponseEntity.ok(ResponseBodyBuilder.create()
                                     .success(PayReverseResponse(cancelTrans.refno), "交易撤销成功"))
                         }
-                        YnrccUtil.CODE_EXCEPTION == resp.code -> {
+                        AgentCode.NEED_QUERY -> {
                             //待查询
                             citizencardQueryResultTask.queryResult(cancelTrans.refno, 0)
                             return ResponseEntity.ok(ResponseBodyBuilder.create()
-                                    .data("cancelRefno", cancelTrans.refno)
-                                    .fail(TradeErrorCode.WAIT_QUERY_RESULT, "请查询撤销结果"))
+                                    .fail(PayReverseResponse(cancelTrans.refno),
+                                            TradeErrorCode.WAIT_QUERY_RESULT, "请查询撤销结果"))
                         }
-                        else -> transactionService.fail(cancelTrans.refno, resp.message).let {
+                        else -> transactionService.fail(cancelTrans.refno,
+                                "${resp.agentCode}-${resp.agentMsg}").let {
                             return ResponseEntity.ok(ResponseBodyBuilder.create()
-                                    .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易撤销失败-${resp.message}"))
+                                    .fail(PayReverseResponse(cancelTrans.refno),
+                                            TradeErrorCode.WAIT_QUERY_RESULT, "请查询撤销结果"))
                         }
                     }
                 }
                 else -> return ResponseEntity.ok(ResponseBodyBuilder.create()
-                        .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "暂不支持支付方式[${mainDtl.sourceType}]的流水撤销"))
+                        .fail(PayReverseResponse(cancelTrans.refno),
+                                TradeErrorCode.BUSINESS_DEAL_ERROR, "暂不支持支付方式[${mainDtl.sourceType}]的流水撤销"))
             }
 
 
         } ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
-                .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在"))
+                .fail(PayReverseResponse(),
+                        TradeErrorCode.BUSINESS_DEAL_ERROR, "流水不存在"))
     }
 
     /**
@@ -307,6 +320,9 @@
                 } else {
                     consumePayService.checkCanReverse(mainDtl.sourceType)
                 }
+            } else {
+                throw TransactionCheckException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
+                        "该笔交易未定义sourcetype, 不支持退款")
             }
 
             val builder = TransactionBuilder().apply {
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 ad08dab..e2ac86c 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
@@ -310,6 +310,13 @@
         if (transaction.shop) {
             transaction.shopDtl.remark = remark
         }
+        if (transaction.reverseType != TradeDict.REVERSE_FLAG_NONE) {
+            val originTrans = transactionMainDao.findByRefnoNoLock(transaction.reverseRefno ?: "")
+                    ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
+                            "系统异常,无法处理退款流水")
+            originTrans.reverseFlag = TradeDict.REVERSE_FLAG_NONE
+            transactionMainDao.save(originTrans)
+        }
         transaction.endTime = systemUtilService.sysdatetime.sysdate
         transactionMainDao.save(transaction)
         return transaction
@@ -358,8 +365,12 @@
         }
         transactionOnSuccess(transaction, sourcetypeRefno, false)
 
-        if(transaction.reverseRefno.isNotEmpty()){
-            //TODO:更新原流水信息
+        if (transaction.reverseType != TradeDict.REVERSE_FLAG_NONE) {
+            val originTrans = transactionMainDao.findByRefnoNoLock(transaction.reverseRefno ?: "")
+                    ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
+                            "系统异常,无法处理退款流水")
+            originTrans.reverseFlag = transaction.reverseType
+            transactionMainDao.save(originTrans)
         }
 
         transaction.endTime = systemUtilService.sysdatetime.sysdate
@@ -381,17 +392,17 @@
             throw TransactionProcessException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
                     "原流水不是成功状态")
         }
-        if (originTrans.reverseFlag != TradeDict.REVERSE_FLAG_NONE
-                || originTrans.reverseFlag != TradeDict.REVERSE_FLAG_REFUND) {
+        if (originTrans.reverseFlag != TradeDict.REVERSE_FLAG_NONE) {
             throw TransactionProcessException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
-                    "原流水已被退款")
+                    "原流水已被退款或正在处理退款中")
         }
 
-        doReversePrepareAndCheck(originTrans, builder)
+        doReversePrepareAndCheck(originTrans, builder, refundAmount)
+        // 判断退款金额
         builder.preCheck()
         val transaction = doReverseProcess(originTrans, builder)
 
-        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_REFUND
+        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_WIP
         originTrans.refundAmount = refundAmount
         transactionMainDao.save(originTrans)
         return transaction
@@ -410,10 +421,10 @@
                     "原流水已被冲正")
         }
 
-        doReversePrepareAndCheck(originTrans, builder)
+        doReversePrepareAndCheck(originTrans, builder, 0.0)
         val transaction = doReverseProcess(originTrans, builder)
 
-        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_CANCEL
+        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_WIP
         transactionMainDao.save(originTrans)
         return transaction
     }
@@ -457,7 +468,8 @@
         return builderRecords(builder, TradeDict.DTL_STATUS_INIT)
     }
 
-    private fun doReversePrepareAndCheck(originTrans: TTransactionMain, builder: TransactionBuilder) {
+    private fun doReversePrepareAndCheck(originTrans: TTransactionMain, builder: TransactionBuilder,
+                                         amount: Double) {
         if (originTrans.person) {
             val account = accountUtilService.readAccount(originTrans.personDtl.userid)
             builder.person(account).apply {
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
deleted file mode 100644
index 326f44a..0000000
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/citizencard/service/citizencard_service.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.supwisdom.dlpay.citizencard.service
-
-import com.supwisdom.dlpay.api.bean.DlpayResp
-
-interface CitizencardPayService {
-    fun bindCard(bankcardno: String, username: String, idtype: String, idno: String, phone: String): DlpayResp
-
-    fun signCard(bankcardno: String, username: String, idtype: String, idno: String, phone: String, transtype: String): DlpayResp
-
-    fun cardPay(shopaccno: String, userid: String, accdate: String, amount: Int, refno: String): DlpayResp
-
-    fun cardPayRefund(refno: String, accdate: String, orignRefno: String, amount: Int): DlpayResp
-
-    fun queryResult(orignRefno: String): DlpayResp
-
-    fun getChkfilename(checkdate: String, merchantBankcardno: String?): DlpayResp
-
-}
\ No newline at end of file