Merge branch 'hotfix/1.0.32'
diff --git a/config/application-devel-pg-xkx.properties b/config/application-devel-pg-xkx.properties
index e03fe08..390649f 100644
--- a/config/application-devel-pg-xkx.properties
+++ b/config/application-devel-pg-xkx.properties
@@ -12,7 +12,12 @@
 spring.datasource.password=123456
 database.dbtype=postgresql
 
+# logging settings
+spring.jpa.show-sql = false
 logging.level.org.hibernate.SQL=ERROR
+logging.level.com.mascloud=ERROR
+logging.level.root=info
+
 # Redis settings
 spring.redis.host=localhost
 spring.redis.port=6379
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserMessageData.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserMessageData.java
new file mode 100644
index 0000000..666c677
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserMessageData.java
@@ -0,0 +1,20 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class UserMessageData {
+  private String msgid;   //tb_msg的id
+  private String content; //tb_msg的content
+  private String lastupdate;  //tb_msg的lastupdate
+  private String refno;   //tb_msg的refno
+  private String transdesc; //refno对应流水的交易描述
+  private Double amount;  //refno对应流水的交易金额
+  private String userid;  //tb_msg的userid
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserQueryMessageParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserQueryMessageParam.java
new file mode 100644
index 0000000..d9a01e3
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserQueryMessageParam.java
@@ -0,0 +1,28 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+
+@Getter
+@Setter
+public class UserQueryMessageParam extends APIRequestParam {
+  @Sign
+  @NotEmpty(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  private Integer pageNo; //可以为空,默认1
+
+  @Sign
+  private Integer pageSize; //可以为空,默认10
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserQueryMessageResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserQueryMessageResponse.java
new file mode 100644
index 0000000..b5e4028
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/UserQueryMessageResponse.java
@@ -0,0 +1,20 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class UserQueryMessageResponse extends ApiResponse {
+  private int pageNo = 1;
+  private int pageSize = 10;
+  private int totalCount = 0;
+  private int totalPages = 0;
+  private List<UserMessageData> data;
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayConfirmParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayConfirmParam.java
new file mode 100644
index 0000000..0b5851f
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayConfirmParam.java
@@ -0,0 +1,31 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class YnrccPayConfirmParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "交易参考号不能为空")
+  private String refno;
+
+  @Sign
+  @NotBlank(message = "参数Plain不能为空")
+  private String plain;   //农商行快捷支付参数
+
+  @Sign
+  @NotBlank(message = "参数Signature不能为空")
+  private String signature;   //农商行快捷支付参数
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayConfirmResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayConfirmResponse.java
new file mode 100644
index 0000000..a9241c4
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayConfirmResponse.java
@@ -0,0 +1,18 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+import java.util.Map;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@ToString
+public class YnrccPayConfirmResponse extends ApiResponse  {
+  private String refno;
+  private String billno;
+  private Double amount;
+
+  private Map<String, String> data; //农商行快捷支付返回字段
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayLimitModifyParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayLimitModifyParam.java
new file mode 100644
index 0000000..bd6e000
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayLimitModifyParam.java
@@ -0,0 +1,40 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+
+@Getter
+@Setter
+public class YnrccPayLimitModifyParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotBlank(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotBlank(message = "签约商户不能为空")
+  private String shopaccno;
+
+  @Sign
+  @Min(value = 0L, message = "错误的单次限额")
+  private Integer singlelimit; //单次限额。单位:分
+
+  @Sign
+  @Min(value = 0L, message = "错误的单日限额")
+  private Integer daylimit; //日限额。单位:分
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayLimitModifyResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayLimitModifyResponse.java
new file mode 100644
index 0000000..04607b4
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayLimitModifyResponse.java
@@ -0,0 +1,13 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@ToString
+public class YnrccPayLimitModifyResponse extends ApiResponse  {
+  private Integer singlelimit; //单次限额。单位:分
+  private Integer daylimit; //日限额。单位:分
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayOrderParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayOrderParam.java
new file mode 100644
index 0000000..a497a13
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayOrderParam.java
@@ -0,0 +1,57 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import com.supwisdom.dlpay.api.util.DateUtil;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Positive;
+
+@Getter
+@Setter
+public class YnrccPayOrderParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "用户唯一号不能为空")
+  private String userid; //用户userid
+
+  @Sign
+  @NotBlank(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotBlank(message = "对接系统唯一订单号不能为空")
+  private String billno;
+
+  @Sign
+  @NotNull(message = "交易金额不能为空")
+  @Positive(message = "交易金额必须大于零")
+  private Integer amount;
+
+  @Sign
+  @NotBlank(message = "请指定交易商户")
+  private String shopaccno;
+
+  @Sign
+  @NotBlank(message = "交易日期不能为空")
+  private String transdate;
+  @Sign
+  @NotBlank(message = "交易时间不能为空")
+  private String transtime;
+
+  @Sign
+  @NotBlank(message = "流水类型不能为空")
+  private String dtltype;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    if (!DateUtil.checkDatetimeValid(transdate, DateUtil.DATE_FMT))
+      throw new RequestParamCheckException("交易日期错误[yyyyMMdd]");
+    if (!DateUtil.checkDatetimeValid(transtime, DateUtil.TIME_FMT))
+      throw new RequestParamCheckException("交易时间错误[HHmmss]");
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayOrderResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayOrderResponse.java
new file mode 100644
index 0000000..c93e2cc
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayOrderResponse.java
@@ -0,0 +1,18 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@ToString
+public class YnrccPayOrderResponse extends ApiResponse {
+  private String refno; //核心平台流水号
+  private String billno; //订单号
+  private Double amount;  //支付金额
+
+  //农商行快捷支付参数
+  private String plain;
+  private String signature;
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayRefundParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayRefundParam.java
new file mode 100644
index 0000000..73095ce
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayRefundParam.java
@@ -0,0 +1,52 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import com.supwisdom.dlpay.api.util.DateUtil;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class YnrccPayRefundParam extends APIRequestParam {
+  @Sign
+  private String refno;
+  @Sign
+  private String billno;
+  @Sign
+  private String shopaccno;
+
+  @Sign
+  @Min(value = 0L, message = "错误的退款金额")
+  private Integer refundAmount;
+
+  @Sign
+  @NotBlank(message = "撤销或退款流水号不能为空")
+  private String requestbillno;
+  @Sign
+  @NotBlank(message = "交易日期不能为空")
+  private String transdate;
+  @Sign
+  @NotBlank(message = "交易时间不能为空")
+  private String transtime;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    if (StringUtils.isEmpty(refno) && (StringUtils.isEmpty(billno) || StringUtils.isEmpty(shopaccno))) {
+      throw new RequestParamCheckException("原流水唯一号不能为空");
+    }
+    if (!DateUtil.checkDatetimeValid(transdate, DateUtil.DATE_FMT)) {
+      throw new RequestParamCheckException("交易日期错误[yyyyMMdd]");
+    }
+    if (!DateUtil.checkDatetimeValid(transtime, DateUtil.TIME_FMT)) {
+      throw new RequestParamCheckException("交易时间错误[HHmmss]");
+    }
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayRefundResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayRefundResponse.java
new file mode 100644
index 0000000..975abde
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayRefundResponse.java
@@ -0,0 +1,14 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class YnrccPayRefundResponse extends ApiResponse {
+  private String refundRefno; //退款流水号
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignApplyParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignApplyParam.java
new file mode 100644
index 0000000..da80b3a
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignApplyParam.java
@@ -0,0 +1,31 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+
+@Getter
+@Setter
+public class YnrccPaySignApplyParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotBlank(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotBlank(message = "签约商户不能为空")
+  private String shopaccno;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignApplyResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignApplyResponse.java
new file mode 100644
index 0000000..4d43405
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignApplyResponse.java
@@ -0,0 +1,20 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class YnrccPaySignApplyResponse extends ApiResponse {
+  private String signNo; //签约号
+  private boolean authSign = false; //是否授权签约
+
+  //农商行快捷支付参数
+  private String plain;
+  private String signature;
+  private YnrccPaySignUserData signUserData;
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignCancelParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignCancelParam.java
new file mode 100644
index 0000000..9d83baf
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignCancelParam.java
@@ -0,0 +1,31 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+
+@Getter
+@Setter
+public class YnrccPaySignCancelParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotBlank(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotBlank(message = "签约商户不能为空")
+  private String shopaccno;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignCancelResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignCancelResponse.java
new file mode 100644
index 0000000..2911c4e
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignCancelResponse.java
@@ -0,0 +1,12 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@ToString
+public class YnrccPaySignCancelResponse extends ApiResponse {
+  private String signNo; //签约号
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignConfirmParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignConfirmParam.java
new file mode 100644
index 0000000..aa85cb6
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignConfirmParam.java
@@ -0,0 +1,32 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class YnrccPaySignConfirmParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "签约号不能为空")
+  private String signNo; //申请时返回的签约号
+
+  @Sign
+  @NotBlank(message = "参数Plain不能为空")
+  private String plain;   //农商行快捷支付参数
+
+  @Sign
+  @NotBlank(message = "参数Signature不能为空")
+  private String signature;   //农商行快捷支付参数
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignConfirmResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignConfirmResponse.java
new file mode 100644
index 0000000..dfc871c
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignConfirmResponse.java
@@ -0,0 +1,16 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+import java.util.Map;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class YnrccPaySignConfirmResponse extends ApiResponse {
+  private String signNo;
+
+  private Map<String, String> data; //农商行快捷支付返回字段
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignInfo.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignInfo.java
new file mode 100644
index 0000000..785d556
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignInfo.java
@@ -0,0 +1,19 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class YnrccPaySignInfo {
+  private String signNo; //申请时返回的签约号
+  private String bankcardno; //签约银行卡号
+  private String shopaccno; //核心平台商户账号
+  private String shopname;  //核心平台商户名称
+  private String signtime;  //签约时间 yyyyMMddHHmmss
+  private String userid;  //核心平台用户ID
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignListQueryParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignListQueryParam.java
new file mode 100644
index 0000000..3a923d9
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignListQueryParam.java
@@ -0,0 +1,26 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+
+@Getter
+@Setter
+public class YnrccPaySignListQueryParam extends APIRequestParam {
+  @Sign
+  private String userid; //可二选一
+
+  @Sign
+  private String bankcardno; //可二选一
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    if (StringUtils.isEmpty(userid) && StringUtils.isEmpty(bankcardno)) {
+      throw new RequestParamCheckException("未指定要查询的签约用户!");
+    }
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignListQueryResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignListQueryResponse.java
new file mode 100644
index 0000000..526f979
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignListQueryResponse.java
@@ -0,0 +1,14 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+import java.util.List;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class YnrccPaySignListQueryResponse extends ApiResponse {
+  private List<YnrccPaySignInfo> data;
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignQueryParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignQueryParam.java
new file mode 100644
index 0000000..d18e016
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignQueryParam.java
@@ -0,0 +1,31 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+
+@Getter
+@Setter
+public class YnrccPaySignQueryParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotBlank(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotBlank(message = "签约商户不能为空")
+  private String shopaccno;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignQueryResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignQueryResponse.java
new file mode 100644
index 0000000..e3a30fa
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignQueryResponse.java
@@ -0,0 +1,12 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class YnrccPaySignQueryResponse extends ApiResponse {
+  private boolean signFlag = false; //是否已签约,默认:否
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignUserData.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignUserData.java
new file mode 100644
index 0000000..0ff52b8
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignUserData.java
@@ -0,0 +1,17 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class YnrccPaySignUserData {
+  private String name; //姓名
+  private String idType; //证件类型
+  private String idNo; //证件号码
+  private String acNo; //支付账号
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthParam.java
new file mode 100644
index 0000000..5f225e4
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthParam.java
@@ -0,0 +1,30 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+
+@Getter
+@Setter
+public class YnrccPayThirdAuthParam extends APIRequestParam {
+  @Sign
+  @NotBlank(message = "第三方服务标识不能为空")
+  private String thirdservice;
+
+  @Sign
+  @NotBlank(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotBlank(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthResponse.java
new file mode 100644
index 0000000..fce24e5
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthResponse.java
@@ -0,0 +1,15 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.*;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class YnrccPayThirdAuthResponse extends ApiResponse{
+  private String thirdService;
+  private YnrccPayThirdAuthUser user;
+  private String sdkConfigData;
+  private String access2ServiceData;
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthUser.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthUser.java
new file mode 100644
index 0000000..75c2245
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayThirdAuthUser.java
@@ -0,0 +1,17 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class YnrccPayThirdAuthUser {
+  private String name; //姓名
+  private String idNo; //证件号
+  private String phone; //手机号
+  private String acNo; //银行卡号
+}
diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java
index 62584f7..9eb32fb 100644
--- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java
@@ -24,4 +24,16 @@
 
     @PostMapping("/qrcodequery")
     DoorQrcodeResponse qrcodequery(@RequestBody DoorQRCodeParam param);
+
+    @PostMapping("/ynrccpay/order")
+    YnrccPayOrderResponse ynrccPayOrder(@RequestBody YnrccPayOrderParam param);
+
+    @PostMapping("/ynrccpay/confirm")
+    YnrccPayConfirmResponse ynrccPayConfirm(@RequestBody YnrccPayConfirmParam param);
+
+    @PostMapping("/ynrccpay/refund")
+    YnrccPayRefundResponse ynrccPayRefund(@RequestBody YnrccPayRefundParam param);
+
+    @PostMapping("/ynrccpay/thirdAuth")
+    YnrccPayThirdAuthResponse ynrccPayThirdAuth(@RequestBody YnrccPayThirdAuthParam param);
 }
diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/TransactionProxy.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/TransactionProxy.java
index 570587a..5d6be32 100644
--- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/TransactionProxy.java
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/TransactionProxy.java
@@ -15,4 +15,7 @@
 
   @PostMapping("/api/consume/queryresult")
   QueryTransDtlResponse queryDtlResult(@RequestBody QueryDtlResultParam param);
+
+  @PostMapping("/api/consume/thirdquery")
+  QueryTransDtlResponse queryDtlResultByThird(@RequestBody QueryDtlResultParam param);
 }
diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java
index 329c29e..1fb815f 100644
--- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java
@@ -78,4 +78,25 @@
 
   @PostMapping("/api/user/queryCitizenCard")
   DoorQrcodeResponse queryCitizenCard(@RequestParam("uid") String uid);
+
+  @PostMapping("/api/user/ynrccpaySignQuery")
+  YnrccPaySignQueryResponse queryYnrccPaySign(@RequestBody YnrccPaySignQueryParam param);
+
+  @PostMapping("/api/user/ynrccpaySignApply")
+  YnrccPaySignApplyResponse applyYnrccPaySign(@RequestBody YnrccPaySignApplyParam param);
+
+  @PostMapping("/api/user/ynrccpaySignConfirm")
+  YnrccPaySignConfirmResponse confirmYnrccPaySign(@RequestBody YnrccPaySignConfirmParam param);
+
+  @PostMapping("/api/user/ynrccpaySignCancel")
+  YnrccPaySignCancelResponse cancelYnrccPaySign(@RequestBody YnrccPaySignCancelParam param);
+
+  @PostMapping("/api/user/ynrccpayModifyLimit")
+  YnrccPayLimitModifyResponse modifyYnrccPayLimit(@RequestBody YnrccPayLimitModifyParam param);
+
+  @PostMapping("/api/user/queryMessage")
+  UserQueryMessageResponse queryUserMessage(@RequestBody UserQueryMessageParam param);
+
+  @PostMapping("/api/user/ynrccpaySignList")
+  YnrccPaySignListQueryResponse queryYnrccPaySignList(@RequestBody YnrccPaySignListQueryParam param);
 }
diff --git a/payapi/build.gradle b/payapi/build.gradle
index d144174..7a4c6cf 100644
--- a/payapi/build.gradle
+++ b/payapi/build.gradle
@@ -115,6 +115,11 @@
 //    implementation files('libs/ojdbc6.jar')
     implementation 'commons-dbcp:commons-dbcp:1.4'
     implementation 'commons-beanutils:commons-beanutils:1.9.3'
+    implementation files('libs/ynrcc-openapi-sdk-1.1.2-RELEASE.jar')
+
+    //大理农商行sdk需求jar
+    implementation 'cn.hutool:hutool-crypto:5.4.7'
+    implementation 'org.bouncycastle:bcprov-jdk15on:1.64'
 
     implementation 'log4j:log4j:1.2.17'
     implementation 'com.alibaba:fastjson:1.2.60'
diff --git a/payapi/libs/ynrcc-openapi-sdk-1.1.2-RELEASE.jar b/payapi/libs/ynrcc-openapi-sdk-1.1.2-RELEASE.jar
new file mode 100644
index 0000000..c3d54ee
--- /dev/null
+++ b/payapi/libs/ynrcc-openapi-sdk-1.1.2-RELEASE.jar
Binary files differ
diff --git a/payapi/sql/update-210106.sql b/payapi/sql/update-210106.sql
new file mode 100644
index 0000000..513f317
--- /dev/null
+++ b/payapi/sql/update-210106.sql
@@ -0,0 +1,58 @@
+-- 农商行网关支付
+INSERT INTO "tb_sourcetype" ("sourcetype_id", "sourcetype", "checkable", "paydesc", "enable", "charge_enable", "consume_enable", "anonymous_enable", "reversable", "pay_subjno", "deposite_subjno", "tplusn", "start_chktime", "tenantid")
+VALUES ('B837FFDD20C0CA07E05011AC03000113', 'ynrccpay', 't', '农商行网关支付', 't', 'f', 't', 'f', 't', '112235', '-', 1, null, '{tenantid}');
+commit;
+
+--新加农商行支付款
+INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
+VALUES (33, '112235', 1, 'y', 1, '1122', '20210106', 2, '农商行支付款', 1, '{tenantid}');
+commit;
+
+-- ----------------------------
+-- Table structure for tb_ynrccpay_sign
+-- ----------------------------
+CREATE TABLE tb_ynrccpay_sign (
+	id varchar(32) NOT NULL,
+	bankcardno varchar(32) NOT NULL,
+	shopaccno varchar(10) NOT NULL,
+	userid varchar(32) NOT NULL,
+	status varchar(10) NOT NULL,
+	sign_flag bool NOT NULL,
+	customer_sign_no varchar(60),
+	sign_time varchar(14),
+	cancel_time varchar(14),
+	remark varchar(600),
+	createtime varchar(14)
+);
+ALTER TABLE tb_ynrccpay_sign ADD CONSTRAINT tb_ynrccpay_sign_pkey PRIMARY KEY (id);
+CREATE INDEX idx1_ynrccpay_sign ON tb_ynrccpay_sign(bankcardno,shopaccno,status);
+
+INSERT INTO "tb_transcode" ("transcode_id", "transcode", "transname", "tenantid")
+VALUES (4, 3050, '农商行网关快捷支付', '{tenantid}');
+commit;
+
+
+INSERT INTO "public"."tb_sourcetype_config"("id", "config_name", "config_value", "configid", "globalflag", "sourcetype", "tenantid") VALUES ('26', '农商行网关支付商户号', NULL, 'ynrcc.netpay.Mer_Id', 'f', 'ynrccpay', '{tenantid}');
+INSERT INTO "public"."tb_sourcetype_config"("id", "config_name", "config_value", "configid", "globalflag", "sourcetype", "tenantid") VALUES ('27', '农商行网关支付商户名', NULL, 'ynrcc.netpay.Mer_IdName', 'f', 'ynrccpay', '{tenantid}');
+INSERT INTO "public"."tb_sourcetype_config"("id", "config_name", "config_value", "configid", "globalflag", "sourcetype", "tenantid") VALUES ('28', '农商行网关支付回调地址', NULL, 'ynrcc.netpay.MerURL', 'f', 'ynrccpay', '{tenantid}');
+INSERT INTO "public"."tb_sourcetype_config"("id", "config_name", "config_value", "configid", "globalflag", "sourcetype", "tenantid") VALUES ('25', '农商行网关支付地址', 'https://ebank.ynrcc.com/pweb/%s?LoginType=C&_locale=zh_CN&BankId=9999', 'ynrcc.netpay.URL', 't', 'ynrccpay', '{tenantid}');
+commit;
+
+CREATE TABLE tb_ynrccpay_thirdapp (
+  id varchar(32) NOT NULL,
+  mch_id varchar(20) NOT NULL,
+  mch_name varchar(200),
+  app_id varchar(60) NOT NULL,
+  token varchar(20) NOT NULL,
+  pubkey varchar(200) NOT NULL,
+  enable bool NOT NULL,
+  remark varchar(200)
+);
+ALTER TABLE tb_ynrccpay_thirdapp ADD CONSTRAINT tb_ynrccpay_thirdapp_pkey PRIMARY KEY (id);
+
+-- 测试环境或正式环境插入相应配置
+INSERT INTO "public"."tb_ynrccpay_thirdapp"("id", "mch_id", "mch_name", "app_id", "token", "pubkey", "enable", "remark")
+VALUES ('test', '1002010472001', '大理市信息化发展有限责任公司', '318D34955996AA035F3047939EA655FF', 'J6upjifWdQfRj3eh', '043AAF09775EC7EEEAAA2C66773F61BF18CE4D2DDDCBFFF43249113D849AD3FF4F8951889E8BF759EC80AF2EEA7473F9FEE97A7DE0B284FFD3312BD5021061F172', 't', '测试环境配置');
+--INSERT INTO "public"."tb_ynrccpay_thirdapp"("id", "mch_id", "mch_name", "app_id", "token", "pubkey", "enable", "remark")
+--VALUES ('dev', '1002010472001', '大理市信息化发展有限责任公司', '5FE60D156754432BAC1789AF35EEA592', 'Cg3Ue7mdkWv9g5mK', '0484D7043D24F3AC19E3F7CA03A166C2F813BCFE2141CB0E8559214A23E7A8DFDC9B4C1E9D9FBE9456621373652B145DDB91BD6DD484E8F04870560E7A16F5AB2C', 't', '生产环境配置');
+commit;
\ No newline at end of file
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
index 149c3ae..caa0ce4 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
@@ -1,5 +1,7 @@
 package com.supwisdom.dlpay.agent;
 
+import java.util.Map;
+
 public class AgentResponse<T> {
   public static final String AGENTCODE_SUCCESS = "0";
 
@@ -13,6 +15,7 @@
   private DtlStatus dtlStatus;
 
   private T payload;
+  private Map<String,String> params;
 
   public String getAgentBody() {
     return agentBody;
@@ -70,6 +73,14 @@
     this.payload = payload;
   }
 
+  public Map<String, String> getParams() {
+    return params;
+  }
+
+  public void setParams(Map<String, String> params) {
+    this.params = params;
+  }
+
   public AgentResponse() {
   }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/ConcatUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/ConcatUtil.java
new file mode 100644
index 0000000..1315114
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/ConcatUtil.java
@@ -0,0 +1,30 @@
+package com.supwisdom.dlpay.agent.ynrccpay;
+
+public class ConcatUtil {
+  private String delimiter;
+  private StringBuilder builder;
+
+  public ConcatUtil(String delimiter) {
+    if (delimiter == null) {
+      throw new RuntimeException("Delimiter must not be null");
+    }
+    this.delimiter = delimiter;
+    builder = new StringBuilder();
+  }
+
+  public ConcatUtil add(String field) {
+    if (field == null) {
+      throw new RuntimeException("added value must not be null");
+    }
+    if (builder.length() > 0) {
+      builder.append(this.delimiter);
+    }
+    builder.append(field);
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    return builder.toString();
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayChkfile.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayChkfile.java
new file mode 100644
index 0000000..1690847
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayChkfile.java
@@ -0,0 +1,138 @@
+package com.supwisdom.dlpay.agent.ynrccpay;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 农商行快捷支付对账单
+ * 	4
+ * ZF01|20210308|20201225161726|20210308151427000066|5607894487|10020104721000000001||0.01|156|0|0.01||20201225161726000115
+ * ZF01|20210308|20210308161616|20210308140757000064|5607894462|10020104721000000001||0.01|156|0|0.01||20210113170353000126
+ * ZF01|20210308|20210308181818|20210308150900000065|5607894483|10020104721000000001||0.01|156|0|0.01||20201225110202000098
+ * ZF02|20210308|20210308152004|114075700006420210308152004|20210308140757000064|10020104721000000001||0.01|156|0|0.01||
+ * */
+public class YnrccPayChkfile {
+
+  private String payFlag; //交易代码:ZF01-支付;ZF02-退款
+  private String clearDate; //清算日期
+  private String transDateTime; //交易时间 yyyyMMddHHmmss
+  private String billNo; //商户订单号
+  private String agentRefno; //银行流水号
+  private String merchantNo; //商户号
+  private String termNo; //终端号
+  private String amount; //交易金额,单位:元
+  private String currencyType; //币种  156-人民币
+  private String feeAmount; //手续费,单位:元
+  private String diffAmount; //交易金额与手续费金额的差值(交易金额-手续费金额),单位:元
+  private String remark1; //备注1
+  private String remark2; //备注2
+
+  public static final String PAY = "ZF01";
+  public static final String REFUND = "ZF02";
+  public static final List<String> HEADER = Arrays.asList("payFlag", "clearDate", "transDateTime", "billNo", "agentRefno",
+      "merchantNo", "termNo", "amount", "currencyType", "feeAmount", "diffAmount", "remark1", "remark2");
+
+  public String getPayFlag() {
+    return payFlag;
+  }
+
+  public void setPayFlag(String payFlag) {
+    this.payFlag = payFlag;
+  }
+
+  public String getClearDate() {
+    return clearDate;
+  }
+
+  public void setClearDate(String clearDate) {
+    this.clearDate = clearDate;
+  }
+
+  public String getTransDateTime() {
+    return transDateTime;
+  }
+
+  public void setTransDateTime(String transDateTime) {
+    this.transDateTime = transDateTime;
+  }
+
+  public String getBillNo() {
+    return billNo;
+  }
+
+  public void setBillNo(String billNo) {
+    this.billNo = billNo;
+  }
+
+  public String getAgentRefno() {
+    return agentRefno;
+  }
+
+  public void setAgentRefno(String agentRefno) {
+    this.agentRefno = agentRefno;
+  }
+
+  public String getMerchantNo() {
+    return merchantNo;
+  }
+
+  public void setMerchantNo(String merchantNo) {
+    this.merchantNo = merchantNo;
+  }
+
+  public String getTermNo() {
+    return termNo;
+  }
+
+  public void setTermNo(String termNo) {
+    this.termNo = termNo;
+  }
+
+  public String getAmount() {
+    return amount;
+  }
+
+  public void setAmount(String amount) {
+    this.amount = amount;
+  }
+
+  public String getCurrencyType() {
+    return currencyType;
+  }
+
+  public void setCurrencyType(String currencyType) {
+    this.currencyType = currencyType;
+  }
+
+  public String getFeeAmount() {
+    return feeAmount;
+  }
+
+  public void setFeeAmount(String feeAmount) {
+    this.feeAmount = feeAmount;
+  }
+
+  public String getDiffAmount() {
+    return diffAmount;
+  }
+
+  public void setDiffAmount(String diffAmount) {
+    this.diffAmount = diffAmount;
+  }
+
+  public String getRemark1() {
+    return remark1;
+  }
+
+  public void setRemark1(String remark1) {
+    this.remark1 = remark1;
+  }
+
+  public String getRemark2() {
+    return remark2;
+  }
+
+  public void setRemark2(String remark2) {
+    this.remark2 = remark2;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayCommonResp.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayCommonResp.java
new file mode 100644
index 0000000..8c9f27d
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayCommonResp.java
@@ -0,0 +1,22 @@
+package com.supwisdom.dlpay.agent.ynrccpay;
+
+public class YnrccPayCommonResp {
+  private String Plain;
+  private String Signature;
+
+  public String getPlain() {
+    return Plain;
+  }
+
+  public void setPlain(String plain) {
+    Plain = plain;
+  }
+
+  public String getSignature() {
+    return Signature;
+  }
+
+  public void setSignature(String signature) {
+    Signature = signature;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayResp.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayResp.java
new file mode 100644
index 0000000..71f9200
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayResp.java
@@ -0,0 +1,185 @@
+package com.supwisdom.dlpay.agent.ynrccpay;
+
+public class YnrccPayResp {
+  private String code; //ZF0000 表示成功
+  private String message;
+
+  private String plain;
+  private String signature;
+
+  private String TransId;
+  private String Mer_Id;
+  private String TransSeqNo;
+
+  //退款
+  private String OrgTransAmt;
+  private String TransAmount;
+  private String MerchantSeqNo;
+
+  //查询
+  private String OrgTransId; //ZF01 - 支付;  ZF02 - 退货
+  private String OrderNo; //订单号
+  private String Amount; //交易金额
+  private String Amount1; //已退货金额
+  private String FeeAmt; //手续费金额
+  private String CurrencyType; //币种
+  private String PpDateTime; //支付系统交易时间
+  private String ClearingDate; //清算日期
+  private String TransStatus; //交易状态 00 - 交易成功; 01 - 交易失败; 02 - 撤消成功; 03 - 部分退货; 04 - 全部退货; 99 - 交易超时
+
+  public String error() {
+    return "code=[" + this.code + "],message=[" + this.message + "]";
+  }
+
+  public String getCode() {
+    return code;
+  }
+
+  public void setCode(String code) {
+    this.code = code;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+
+  public String getPlain() {
+    return plain;
+  }
+
+  public void setPlain(String plain) {
+    this.plain = plain;
+  }
+
+  public String getSignature() {
+    return signature;
+  }
+
+  public void setSignature(String signature) {
+    this.signature = signature;
+  }
+
+  public String getTransId() {
+    return TransId;
+  }
+
+  public void setTransId(String transId) {
+    TransId = transId;
+  }
+
+  public String getMer_Id() {
+    return Mer_Id;
+  }
+
+  public void setMer_Id(String mer_Id) {
+    Mer_Id = mer_Id;
+  }
+
+  public String getTransSeqNo() {
+    return TransSeqNo;
+  }
+
+  public void setTransSeqNo(String transSeqNo) {
+    TransSeqNo = transSeqNo;
+  }
+
+  public String getTransStatus() {
+    return TransStatus;
+  }
+
+  public void setTransStatus(String transStatus) {
+    TransStatus = transStatus;
+  }
+
+  public String getOrgTransAmt() {
+    return OrgTransAmt;
+  }
+
+  public void setOrgTransAmt(String orgTransAmt) {
+    OrgTransAmt = orgTransAmt;
+  }
+
+  public String getTransAmount() {
+    return TransAmount;
+  }
+
+  public void setTransAmount(String transAmount) {
+    TransAmount = transAmount;
+  }
+
+  public String getMerchantSeqNo() {
+    return MerchantSeqNo;
+  }
+
+  public void setMerchantSeqNo(String merchantSeqNo) {
+    MerchantSeqNo = merchantSeqNo;
+  }
+
+  public String getOrgTransId() {
+    return OrgTransId;
+  }
+
+  public void setOrgTransId(String orgTransId) {
+    OrgTransId = orgTransId;
+  }
+
+  public String getOrderNo() {
+    return OrderNo;
+  }
+
+  public void setOrderNo(String orderNo) {
+    OrderNo = orderNo;
+  }
+
+  public String getAmount() {
+    return Amount;
+  }
+
+  public void setAmount(String amount) {
+    Amount = amount;
+  }
+
+  public String getAmount1() {
+    return Amount1;
+  }
+
+  public void setAmount1(String amount1) {
+    Amount1 = amount1;
+  }
+
+  public String getFeeAmt() {
+    return FeeAmt;
+  }
+
+  public void setFeeAmt(String feeAmt) {
+    FeeAmt = feeAmt;
+  }
+
+  public String getCurrencyType() {
+    return CurrencyType;
+  }
+
+  public void setCurrencyType(String currencyType) {
+    CurrencyType = currencyType;
+  }
+
+  public String getPpDateTime() {
+    return PpDateTime;
+  }
+
+  public void setPpDateTime(String ppDateTime) {
+    PpDateTime = ppDateTime;
+  }
+
+  public String getClearingDate() {
+    return ClearingDate;
+  }
+
+  public void setClearingDate(String clearingDate) {
+    ClearingDate = clearingDate;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayUtil.java
new file mode 100644
index 0000000..ce51759
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayUtil.java
@@ -0,0 +1,89 @@
+package com.supwisdom.dlpay.agent.ynrccpay;
+
+
+import com.google.gson.Gson;
+import com.supwisdom.dlpay.agent.AgentCode;
+import com.supwisdom.dlpay.agent.citizencard.YnrccRespCode;
+import org.springframework.data.util.Pair;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class YnrccPayUtil {
+  public static final String GATEWAY = "ynrcc.netpay.URL";
+  public static final String MER_ID = "ynrcc.netpay.Mer_Id";
+  public static final String MER_NAME = "ynrcc.netpay.Mer_IdName";
+  public static final String MER_URL = "ynrcc.netpay.MerURL";
+
+  public static final String chkFileDelimiter = "|";
+  public static final String SUCCESS = "ZF0000";
+  public static final String WAIT_FOR_QUERY = "ZF0098"; //等待查询结果
+  public static final String NO_RECORDS_TODAY = "ZF0101"; //当日无交易明细
+
+
+  public static String toJson(Object obj) {
+    if (null == obj) return "";
+    Gson gson = new Gson();
+    return gson.toJson(obj);
+  }
+
+  public static final List<Pair<AgentCode, YnrccRespCode>> errcode = new ArrayList<>(0);
+
+  static {
+    errcode.add(Pair.of(AgentCode.SUCCESS, new YnrccRespCode("ZF0000", "交易成功")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0001", "本机构无权查看机构的信息")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0003", "无效商户")));
+    errcode.add(Pair.of(AgentCode.SERVER_INTERNAL_ERROR, new YnrccRespCode("ZF0006", "网络不通")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0012", "无效交易")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0013", "无效金额")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0014", "无效卡号")));
+    errcode.add(Pair.of(AgentCode.REFNO_NOT_EXISTS, new YnrccRespCode("ZF0020", "原订单信息不存在")));
+    errcode.add(Pair.of(AgentCode.SERVER_INTERNAL_ERROR, new YnrccRespCode("ZF0022", "交易异常")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0030", "终端上送数据格式错")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0041", "账号被冻结或挂失")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0042", "无此帐户")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0048", "该客户号已关闭快速支付")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0049", "签约已撤消或冻结")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0050", "没有签约协议支付")));
+    errcode.add(Pair.of(AgentCode.SHORT_OF_BALANCE, new YnrccRespCode("ZF0051", "余额不足")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0055", "密码错误")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0058", "不允许商户进行的交易")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0061", "超出商户金额限制")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0062", "退货金额超限")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0063", "上笔交易正在处理中,现交易被拒绝")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0064", "原始交易金额不匹配")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0065", "超出取款限制次数")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0067", "不允许多次退货")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0075", "超出密码输入次数")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0077", "商户状态错误")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0082", "卡号已经被注销了")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0084", "账号不存在")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0085", "银联支付号被注销了")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0086", "身份证号不匹配")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0087", "无效证件号码")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0088", "简单密码")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0092", "上笔交易正在处理中")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0093", "违法交易,无法完成")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0094", "重复交易")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0096", "系统内部错")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0097", "无效终端,柜员号不存在")));
+    errcode.add(Pair.of(AgentCode.REQUIRE_QUERY, new YnrccRespCode("ZF0098", "交易超时,请查询")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0099", "支付密码不允许为空")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF00EI", "找不到机构号")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF00EB", "(商户)机构设置错误")));
+
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF00A0", "成功接收订单")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF00A1", "支付方取消订单")));
+    errcode.add(Pair.of(AgentCode.REFNO_NOT_EXISTS, new YnrccRespCode("ZF0101", "无相关数据")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZF0214", "平台已冻结或已注销")));
+
+    //自定义错误 ZExxxx
+    errcode.add(Pair.of(AgentCode.CONFIG_ERROR, new YnrccRespCode("ZE0001", "系统参数未配置")));
+    errcode.add(Pair.of(AgentCode.COMMON_ERROR, new YnrccRespCode("ZE0002", "签名计算错误")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZE0097", "请求农商行网关快捷支付返回数据有误")));
+    errcode.add(Pair.of(AgentCode.ILLEGAL_DATA, new YnrccRespCode("ZE0098", "请求农商行网关快捷支付返回数据为空")));
+    errcode.add(Pair.of(AgentCode.SERVER_INTERNAL_ERROR, new YnrccRespCode("ZE0099", "请求农商行网关快捷支付httpStatus非200")));
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/CardDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/CardDao.java
index 4b3ace3..dfe5630 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/CardDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/CardDao.java
@@ -32,4 +32,10 @@
   List<TCard> findCitizencardByCardphyidWithoutOldId(String cardphyid, String oldId);
 
   TCard getById(String id);
+
+  @Query("select count(t.id) from TCard t where t.status='normal' and t.cardtype='bankcard' and t.cardno=?1 ")
+  int countByBankCardNo(String bankcardno);
+
+  @Query("select count(t.id) from TCard t where t.status='normal' and t.cardtype='bankcard' and t.cardno=?1 and t.userid=?2 ")
+  int countByBankCardNoAndUserid(String bankcardno, String userid);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/ShopSourceTypeConfigDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/ShopSourceTypeConfigDao.java
index e861165..9c59a82 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/ShopSourceTypeConfigDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/ShopSourceTypeConfigDao.java
@@ -14,4 +14,7 @@
 
   @Query("select a from TShopSourceTypeConfig a where a.shopaccno=?1 and a.sourceType=?2 and a.configid=?3 ")
   TShopSourceTypeConfig getShopSourceTypeConfigById(String shopaccno, String sourceType, String configid);
+
+  @Query("select distinct a.shopaccno from TShopSourceTypeConfig a where a.sourceType=?1 order by a.shopaccno ")
+  List<String> getSourcetypeBindShopaccnos(String sourceType);
 }
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 b72f8d2..10a3139 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
@@ -8,6 +8,7 @@
 
 import javax.persistence.LockModeType;
 import javax.persistence.QueryHint;
+import java.util.List;
 
 public interface TransactionMainDao extends CrudRepository<TTransactionMain, String> {
 
@@ -28,4 +29,12 @@
 
   @Query("select min(t.accdate) from TTransactionMain t where t.sourceType=?1 ")
   String findMinAccdateBySourcetype(String sourcetype);
+
+  @Query("from TTransactionMain t where t.reverseRefno=?1 and t.status='success' order by t.refno ")
+  List<TTransactionMain> findByRefundSuccessTransdtl(String refno);
+
+  @Query("from TTransactionMain t where t.reverseRefno=?1 order by t.refno ")
+  List<TTransactionMain> findByRefundTransdtl(String refno);
+
+
 }
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 8e4048b..0e81d21 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
@@ -52,4 +52,7 @@
   @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
   TSourceTypeCheckStatus saveOrUpdateSourceTypeCheckStatus(TSourceTypeCheckStatus s);
 
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
+  List<String> getShopaccnoBySourcetype(String sourcetype);
+
 }
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 62c471f..f0bd529 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
@@ -11,6 +11,7 @@
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -210,4 +211,10 @@
     }
     return sourceTypeCheckDao.save(s);
   }
+
+  @Override
+  public List<String> getShopaccnoBySourcetype(String sourcetype) {
+    List<String> list = shopSourceTypeConfigDao.getSourcetypeBindShopaccnos(sourcetype);
+    return list != null ? list : new ArrayList<String>(0);
+  }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/citizencard/dao/YnrccPaySignDao.java b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/dao/YnrccPaySignDao.java
new file mode 100644
index 0000000..752bba4
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/dao/YnrccPaySignDao.java
@@ -0,0 +1,37 @@
+package com.supwisdom.dlpay.citizencard.dao;
+
+import com.supwisdom.dlpay.citizencard.domain.TYnrccPaySign;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface YnrccPaySignDao extends JpaRepository<TYnrccPaySign, String> {
+  @Query("from TYnrccPaySign t where t.bankcardno=?1 and t.shopaccno=?2 and t.status='normal'")
+  TYnrccPaySign getUserSign(String bankcardno, String shopaccno);
+
+  @Query("select count(t.id) from TYnrccPaySign t where t.bankcardno=?1 and t.shopaccno<>?2 and t.status='normal' and t.signFlag is true ")
+  int countByBankcardnoAndSignStatus(String bankcardno, String shopaccno);
+
+  @Query("from TYnrccPaySign t where t.bankcardno=?1 and t.shopaccno<>?2 and t.status='normal' and t.signFlag is true")
+  List<TYnrccPaySign> queryOtherShopSign(String bankcardno, String shopaccno);
+
+  TYnrccPaySign getById(String id);
+
+  @Query("from TYnrccPaySign t where t.userid=?1 and t.status='normal' and t.signFlag is true")
+  List<TYnrccPaySign> queryActiveSignsByUserid(String userid);
+
+  @Query("from TYnrccPaySign t where t.bankcardno=?1 and t.status='normal' and t.signFlag is true")
+  List<TYnrccPaySign> queryActiveSignsByBankcardno(String bankcardno);
+
+  @Query("from TYnrccPaySign t where t.userid=?1 and t.bankcardno=?2 and t.status='normal' and t.signFlag is true")
+  List<TYnrccPaySign> queryActiveSignsByUseridAndBankcardno(String userid, String bankcardno);
+
+  @Query("select count(t.id) from TYnrccPaySign t where t.bankcardno=?1 and t.status='normal' ")
+  int countByBankcardno(String bankcardno);
+
+  @Query("select count(t.id) from TYnrccPaySign t where t.bankcardno=?1 and t.userid=?2 and t.status='normal' ")
+  int countByBankcardnoAndUserid(String bankcardno, String userid);
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/citizencard/dao/YnrccPayThirdappDao.java b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/dao/YnrccPayThirdappDao.java
new file mode 100644
index 0000000..f20a8c4
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/dao/YnrccPayThirdappDao.java
@@ -0,0 +1,12 @@
+package com.supwisdom.dlpay.citizencard.dao;
+
+import com.supwisdom.dlpay.citizencard.domain.TYnrccPayThirdapp;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+
+public interface YnrccPayThirdappDao extends JpaRepository<TYnrccPayThirdapp, String> {
+  @Query("from TYnrccPayThirdapp t where t.enable is true ")
+  List<TYnrccPayThirdapp> queryYnrccPayThirdConfig();
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/citizencard/domain/TYnrccPaySign.java b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/domain/TYnrccPaySign.java
new file mode 100644
index 0000000..b286057
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/domain/TYnrccPaySign.java
@@ -0,0 +1,134 @@
+package com.supwisdom.dlpay.citizencard.domain;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "TB_YNRCCPAY_SIGN",
+    indexes = {@Index(name = "idx1_ynrccpay_sign", columnList = "bankcardno,shopaccno,status")})
+public class TYnrccPaySign {
+  @Id
+  @GenericGenerator(name = "midGenerator", strategy = "uuid")
+  @GeneratedValue(generator = "midGenerator")
+  @Column(name = "id", nullable = false, length = 32)
+  private String id;
+
+  @Column(name="bankcardno", nullable = false, length = 32)
+  private String bankcardno;
+
+  @Column(name="shopaccno", nullable = false, length = 10)
+  private String shopaccno;
+
+  @Column(name="userid", nullable = false, length = 32)
+  private String userid;
+
+  @Column(name="status", nullable = false, length = 10)
+  private String status;
+
+  @Column(name="sign_flag", nullable = false, length = 10)
+  private boolean signFlag;
+
+  @Column(name="customer_sign_no", length = 60)
+  private String customerSignNo;
+
+  @Column(name="sign_time", length = 14)
+  private String signTime;
+
+  @Column(name="cancel_time", length = 14)
+  private String cancelTime;
+
+  @Column(name="remark", length = 600)
+  private String remark;
+
+  @Column(name="createtime", length = 14)
+  private String createtime;
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getBankcardno() {
+    return bankcardno;
+  }
+
+  public void setBankcardno(String bankcardno) {
+    this.bankcardno = bankcardno;
+  }
+
+  public String getShopaccno() {
+    return shopaccno;
+  }
+
+  public void setShopaccno(String shopaccno) {
+    this.shopaccno = shopaccno;
+  }
+
+  public String getUserid() {
+    return userid;
+  }
+
+  public void setUserid(String userid) {
+    this.userid = userid;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public boolean isSignFlag() {
+    return signFlag;
+  }
+
+  public void setSignFlag(boolean signFlag) {
+    this.signFlag = signFlag;
+  }
+
+  public String getCustomerSignNo() {
+    return customerSignNo;
+  }
+
+  public void setCustomerSignNo(String customerSignNo) {
+    this.customerSignNo = customerSignNo;
+  }
+
+  public String getSignTime() {
+    return signTime;
+  }
+
+  public void setSignTime(String signTime) {
+    this.signTime = signTime;
+  }
+
+  public String getCancelTime() {
+    return cancelTime;
+  }
+
+  public void setCancelTime(String cancelTime) {
+    this.cancelTime = cancelTime;
+  }
+
+  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;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/citizencard/domain/TYnrccPayThirdapp.java b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/domain/TYnrccPayThirdapp.java
new file mode 100644
index 0000000..b4ef460
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/domain/TYnrccPayThirdapp.java
@@ -0,0 +1,118 @@
+package com.supwisdom.dlpay.citizencard.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 大理农商行快捷支付第三方中间缴费业务
+ * 对接参数配置表
+ * */
+@Entity
+@Table(name = "TB_YNRCCPAY_THIRDAPP")
+public class TYnrccPayThirdapp {
+
+  @Id
+  @Column(name = "id", unique = true, nullable = false, length = 32)
+  private String id;
+
+  @Column(name = "mch_id", nullable = false, length = 20)
+  private String mchId;
+
+  @Column(name = "mch_name", nullable = false, length = 200)
+  private String mchName;
+
+  @Column(name = "app_id", nullable = false, length = 60)
+  private String appId;
+
+  @Column(name = "token", nullable = false, length = 20)
+  private String token;
+
+  @Column(name = "pubkey", nullable = false, length = 200)
+  private String pubkey;
+
+  @Column(name = "enable", nullable = false, length = 20)
+  private boolean enable;
+
+  @Column(name = "remark", length = 200)
+  private String remark;
+
+  public TYnrccPayThirdapp() {
+  }
+
+  public TYnrccPayThirdapp(String id, String mchId, String mchName, String appId, String token, String pubkey, boolean enable, String remark) {
+    this.id = id;
+    this.mchId = mchId;
+    this.mchName = mchName;
+    this.appId = appId;
+    this.token = token;
+    this.pubkey = pubkey;
+    this.enable = enable;
+    this.remark = remark;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getMchId() {
+    return mchId;
+  }
+
+  public void setMchId(String mchId) {
+    this.mchId = mchId;
+  }
+
+  public String getMchName() {
+    return mchName;
+  }
+
+  public void setMchName(String mchName) {
+    this.mchName = mchName;
+  }
+
+  public String getAppId() {
+    return appId;
+  }
+
+  public void setAppId(String appId) {
+    this.appId = appId;
+  }
+
+  public String getToken() {
+    return token;
+  }
+
+  public void setToken(String token) {
+    this.token = token;
+  }
+
+  public String getPubkey() {
+    return pubkey;
+  }
+
+  public void setPubkey(String pubkey) {
+    this.pubkey = pubkey;
+  }
+
+  public boolean isEnable() {
+    return enable;
+  }
+
+  public void setEnable(boolean enable) {
+    this.enable = enable;
+  }
+
+  public String getRemark() {
+    return remark;
+  }
+
+  public void setRemark(String remark) {
+    this.remark = remark;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/citizencard/task/CitizencardCheckConfirmTask.java b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/task/CitizencardCheckConfirmTask.java
index 3cb0417..08d4e17 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/citizencard/task/CitizencardCheckConfirmTask.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/citizencard/task/CitizencardCheckConfirmTask.java
@@ -15,7 +15,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
@@ -36,7 +35,8 @@
   @Scheduled(cron = "${citizencard.confirm.chkdtl.cron}")
   @SchedulerLock(name = "CitizencardChkClearConfirmTask", lockAtMostForString = "PT10M")
   public void doConfirmCitizenCardChkdtlTask() {
-    try { long t1 = System.currentTimeMillis();
+    try {
+      long t1 = System.currentTimeMillis();
       if (null == TenantContext.getTenantSchema()) TenantContext.setTenantSchema(Constants.DEFAULT_TENANTID);
 
       TBusinesspara businessParam = systemUtilService.getBusinessValueForUpdateNowait(ConstantUtil.BUSINESS_CITIZENCARD_CLEARDATE);
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/PageRes.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/PageRes.java
new file mode 100644
index 0000000..03467f9
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/PageRes.java
@@ -0,0 +1,51 @@
+package com.supwisdom.dlpay.framework.util;
+
+import java.util.List;
+
+public class PageRes<T> {
+  private int pageNo = 1;
+  private int pageSize = 10;
+  private int totalCount = 0;
+  private int totalPages = 0;
+  private List<T> data;
+
+  public int getPageNo() {
+    return pageNo;
+  }
+
+  public void setPageNo(int pageNo) {
+    this.pageNo = pageNo;
+  }
+
+  public int getPageSize() {
+    return pageSize;
+  }
+
+  public void setPageSize(int pageSize) {
+    this.pageSize = pageSize;
+  }
+
+  public int getTotalCount() {
+    return totalCount;
+  }
+
+  public void setTotalCount(int totalCount) {
+    this.totalCount = totalCount;
+  }
+
+  public int getTotalPages() {
+    return totalPages;
+  }
+
+  public void setTotalPages(int totalPages) {
+    this.totalPages = totalPages;
+  }
+
+  public List<T> getData() {
+    return data;
+  }
+
+  public void setData(List<T> data) {
+    this.data = data;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java
index e80344a..21602c4 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java
@@ -78,6 +78,11 @@
    */
   public static final String SUBJNO_PAY_CITIZEN_CARD = "112234";
 
+  /**
+   * 应收账款 - 农商行网关快捷支付
+   */
+  public static final String SUBJNO_YNRCC_NETPAY = "112235";
+
 
   //======================= 负债类 =====================//
 
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
index b78049f..29f3921 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
@@ -13,6 +13,8 @@
 
   public static final int TRANSCODE_ALIPAY = 3040;//支付宝支付
 
+  public static final int TRANSCODE_YNRCC_NETPAY = 3050;//农商行网关快捷支付
+
   // QRcode 聚合支付
   public static final int TRANSCODE_QRCODE = 1002;
 
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 161b1c7..ae9aafe 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
@@ -81,6 +81,7 @@
   public static final String PAYTYPE_CITIZEN_CARD = "citizenCard"; //市民卡
   public static final String PAYTYPE_YKT_CARD = "yktpay"; //一卡通
   public static final String PAYTYPE_OTHER_THIRDPART = "thirdpart"; //其他第三方
+  public static final String PAYTYPE_YNRCC_PAY="ynrccpay"; //农商行网关快捷支付
 
   public static final String PAYTYPE_APP = "APP"; //app内支付
   public static final String PAYTYPE_H5 = "H5"; //H5内支付
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java
index 84a951e..fab8949 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeErrorCode.java
@@ -130,6 +130,8 @@
 
   public static final int NO_DEAL_EEROR = 30005; // 无交易记录
 
+  public static final int BUSINESS_USER_NO_SIGN = 30006; // 用户未签约
+
   //============= 交易错误 ============//
   public static final int CARD_NOT_EXISTS = 40000; //卡不存在
 
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/UserMessageService.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/UserMessageService.java
new file mode 100644
index 0000000..842b9d9
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/UserMessageService.java
@@ -0,0 +1,11 @@
+package com.supwisdom.dlpay.system.service;
+
+import com.supwisdom.dlpay.api.bean.UserMessageData;
+import com.supwisdom.dlpay.framework.util.PageRes;
+import org.springframework.transaction.annotation.Transactional;
+
+public interface UserMessageService {
+  @Transactional(rollbackFor = Exception.class, readOnly = true)
+  PageRes<UserMessageData> queryMessageByUserid(String userid, int pageNo, int pageSize);
+
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/UserMessageServiceImpl.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/UserMessageServiceImpl.java
new file mode 100644
index 0000000..b5fa9ce
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/UserMessageServiceImpl.java
@@ -0,0 +1,49 @@
+package com.supwisdom.dlpay.system.service.impl;
+
+import com.supwisdom.dlpay.api.bean.UserMessageData;
+import com.supwisdom.dlpay.framework.util.PageRes;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.system.bean.CitizenCardShowBean;
+import com.supwisdom.dlpay.system.service.UserMessageService;
+import org.hibernate.query.internal.NativeQueryImpl;
+import org.hibernate.transform.Transformers;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class UserMessageServiceImpl implements UserMessageService {
+  @PersistenceContext
+  private EntityManager entityManager;
+
+  @Override
+  public PageRes<UserMessageData> queryMessageByUserid(String userid, int pageNo, int pageSize) {
+    StringBuffer querySql = new StringBuffer("select a.msgid,a.content,a.lastupdate,a.refno,b.transdesc,b.amount,a.userid " +
+        " from tb_msg a left join tb_persondtl b on a.refno=b.refno where a.userid=:userid order by a.lastupdate desc");
+    StringBuffer countSql = new StringBuffer("select count(a.msgid) as cnt " +
+        " from tb_msg a left join tb_persondtl b on a.refno=b.refno where a.userid=:userid ");
+
+    Query query = entityManager.createNativeQuery(querySql.toString());
+    Query countQuery = entityManager.createNativeQuery(countSql.toString());
+    query.setParameter("userid", userid.trim());
+    countQuery.setParameter("userid", userid.trim());
+    query.setFirstResult((pageNo - 1) * pageSize);
+    query.setMaxResults(pageSize); //分页显示
+    query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(UserMessageData.class));
+    List<UserMessageData> list = query.getResultList();
+    BigInteger cnt = (BigInteger) countQuery.getSingleResult();
+    PageRes<UserMessageData> page = new PageRes<>();
+    page.setPageNo(pageNo);
+    page.setPageSize(pageSize);
+    page.setTotalCount(cnt == null ? 0 : cnt.intValue());
+    page.setTotalPages(page.getTotalCount() % page.getPageSize() > 0 ? (page.getTotalCount() / page.getPageSize() + 1) : (page.getTotalCount() / page.getPageSize()));
+    page.setData(list == null ? new ArrayList<>(0) : list);
+    return page;
+  }
+}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/ynrcc_netpay_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/ynrcc_netpay_service_impl.kt
new file mode 100644
index 0000000..d8b5af1
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/ynrcc_netpay_service_impl.kt
@@ -0,0 +1,433 @@
+package com.supwisdom.dlpay.agent.service.impl
+
+import com.csii.ynrcc.open.api.pay.YNRCCFastGateWayPayApi
+import com.csii.ynrcc.open.api.service.User
+import com.csii.ynrcc.open.api.service.YNRCCOpenServiceApi
+import com.google.gson.Gson
+import com.supwisdom.dlpay.agent.service.YnrccNetPayService
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayCommonResp
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayResp
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayUtil
+import com.supwisdom.dlpay.api.domain.TPerson
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.exception.TransactionProcessException
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.*
+import mu.KotlinLogging
+import org.springframework.http.HttpEntity
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+import org.springframework.http.converter.StringHttpMessageConverter
+import org.springframework.stereotype.Service
+import org.springframework.util.LinkedMultiValueMap
+import org.springframework.util.MultiValueMap
+import org.springframework.web.client.RestTemplate
+import java.net.URLDecoder
+import java.nio.charset.StandardCharsets
+
+@Service
+class YnrccNetPayServiceImpl(val restTemplate: RestTemplate,
+                             val systemUtilService: SystemUtilService,
+                             val sourceTypeService: SourceTypeService) : YnrccNetPayService {
+    private val logger = KotlinLogging.logger { }
+
+    override fun doAnalysisSignature(shopaccno: String, plain: String, signature: String): Map<String, String> {
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, true)
+        val data = YNRCCFastGateWayPayApi.verify(signature, plain) /* 调SDK验证签名 */
+        val merId = config[YnrccPayUtil.MER_ID]
+        if (!merId.isNullOrEmpty() && merId != data["Mer_Id"]) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "参数[Mer_Id]不匹配!")
+        }
+        return data
+    }
+
+    override fun doApplyYnrccPaySign(shopaccno: String): YnrccPayResp {
+        val resp = YnrccPayResp()
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, false)
+        val merId = config[YnrccPayUtil.MER_ID]
+        val merUrl = config[YnrccPayUtil.MER_URL]
+        if (merId.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_Id]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merUrl.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[MerURL]"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val params = hashMapOf<String, String>()
+        params["TransId"] = "IFSR"
+        params["Mer_Id"] = merId.trim()
+        params["MerURL"] = merUrl.trim()
+        params["PAY_MODE"] = "QS"
+
+        //调SDK生成签名
+        val signData = YNRCCFastGateWayPayApi.sign(params)
+        if (signData["Plain"].isNullOrEmpty() || signData["Signature"].isNullOrEmpty()) {
+            resp.code = "ZE0002"
+            resp.message = "签名计算错误!"
+            logger.error("签名后[Plain]和[Signature]参数为空!")
+            return resp
+        }
+
+        resp.code = YnrccPayUtil.SUCCESS
+        resp.message = "SUCCESS"
+        resp.plain = signData["Plain"]
+        resp.signature = signData["Signature"]
+        return resp
+    }
+
+    override fun doApplyAuthYnrccPaySign(shopaccno: String, oldCustomerSignNo: String): YnrccPayResp {
+        val resp = YnrccPayResp()
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, false)
+        val merId = config[YnrccPayUtil.MER_ID]
+        if (merId.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_Id]"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val params = hashMapOf<String, String>()
+        params["TransId"] = "IFSR"
+        params["Mer_Id"] = merId.trim()
+        params["CustomerSignNo"] = oldCustomerSignNo.trim()
+        params["PAY_MODE"] = "QS"
+
+        //调SDK生成签名
+        val signData = YNRCCFastGateWayPayApi.sign(params)
+        if (signData["Plain"].isNullOrEmpty() || signData["Signature"].isNullOrEmpty()) {
+            resp.code = "ZE0002"
+            resp.message = "签名计算错误!"
+            logger.error("签名后[Plain]和[Signature]参数为空!")
+            return resp
+        }
+
+        resp.code = YnrccPayUtil.SUCCESS
+        resp.message = "SUCCESS"
+        resp.plain = signData["Plain"]
+        resp.signature = signData["Signature"]
+        return resp
+    }
+
+    override fun doCancelYnrccPaySign(shopaccno: String, customerSignNo: String): YnrccPayResp {
+        val resp = YnrccPayResp()
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, false)
+        val gateWay = config[YnrccPayUtil.GATEWAY]
+        val merId = config[YnrccPayUtil.MER_ID]
+        if (gateWay.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[网关地址]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merId.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_Id]"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val url = String.format(gateWay, "PayGateFastPayCancelSign.do") //赋予接口名
+        val params = hashMapOf<String, String>()
+        params["TransId"] = "IFCR"
+        params["Mer_Id"] = merId.trim()
+        params["CustomerSignNo"] = customerSignNo
+        params["PAY_MODE"] = "Q"
+
+        val signData = YNRCCFastGateWayPayApi.sign(params) //调SDK生成签名
+        val plain = signData["Plain"]
+        val signature = signData["Signature"]
+        if (plain.isNullOrEmpty() || signature.isNullOrEmpty()) {
+            resp.code = "ZE0002"
+            resp.message = "签名计算错误!"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val result = postForm(url, plain, signature, "解约") //发起表单提交
+        resp.code = result["RespCode"]
+        resp.message = result["RespDesc"]
+        if (YnrccPayUtil.SUCCESS == result["RespCode"]) {
+            resp.transId = result["TransId"]
+            resp.mer_Id = result["Mer_Id"]
+        } else {
+            logger.error(resp.error())
+        }
+        return resp
+    }
+
+    private fun error(code: String, message: String): Map<String, String> {
+        val error = hashMapOf<String, String>()
+        error["RespCode"] = code
+        error["RespDesc"] = message
+        return error
+    }
+
+    private fun postForm(url: String, plain: String, signature: String, opt:String): Map<String,String> {
+        val httpHeaders = HttpHeaders()
+        httpHeaders.contentType = MediaType.APPLICATION_FORM_URLENCODED //Form表单提交
+        val requestParams = LinkedMultiValueMap<String, String>()
+        requestParams.add("Plain", plain);
+        requestParams.add("Signature", signature)
+        val httpEntity = HttpEntity<MultiValueMap<String, String>>(requestParams, httpHeaders)
+        restTemplate.messageConverters[1] = StringHttpMessageConverter(StandardCharsets.UTF_8) //UTF-8接收
+
+        logger.info("农商行网关快捷支付请求【$opt】:\nurl=[$url]\nPlain=[$plain]\nSignature=[$signature]")
+        val result = restTemplate.postForEntity(url, httpEntity, String::class.java)
+        if (200 == result.statusCodeValue) {
+            //请求成功
+            logger.info("农商行网关快捷支付请求【$opt】返回:\nurl=[$url]\nResponse Body=[" + result.body + "]")
+            val resJson = Gson().fromJson(result.body, YnrccPayCommonResp::class.java)
+            if (null == resJson || StringUtil.isEmpty(resJson.plain) || StringUtil.isEmpty(resJson.signature)) {
+                return error("ZE0098", "请求农商行网关【$opt】返回数据为空!")
+            }
+
+            val resData = when ("对账" == opt) {
+                true -> YNRCCFastGateWayPayApi.verify(resJson.signature, URLDecoder.decode(resJson.plain,"UTF-8")) //对账需先解码
+                false -> YNRCCFastGateWayPayApi.verify(resJson.signature, resJson.plain) //调SDK验证签名
+            }
+            logger.info("农商行网关快捷支付请求【$opt】返回:\nurl=[$url]\nResponse Plain=[" + YnrccPayUtil.toJson(resData) + "]")
+            val respCode = resData["RespCode"]?.trim()?.replace("\r\n", "")
+            return if (YnrccPayUtil.SUCCESS == respCode) {
+                resData["RespCode"] = respCode
+                resData["RespDesc"] = "SUCCESS"
+                resData
+            } else {
+                val errmsg = YnrccPayUtil.errcode.firstOrNull {
+                    it.second.code == respCode
+                }?.second?.msg
+                resData["RespCode"] = respCode
+                resData["RespDesc"] = "$respCode $errmsg"  //设置失败信息
+                resData
+            }
+        } else {
+            return error("ZE0099","请求农商行网关【$opt】失败!http status=[${result.statusCodeValue}]")
+        }
+    }
+
+    override fun doYnrccPayInit(shopaccno: String, refno: String, amount: Int, transDateTime: String, productInfo: String, extData: String, custname: String, email: String, customerSignNo: String): YnrccPayResp {
+        val resp = YnrccPayResp()
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, false)
+        val merId = config[YnrccPayUtil.MER_ID]
+        val merIdName = config[YnrccPayUtil.MER_NAME]
+        val merUrl = config[YnrccPayUtil.MER_URL]
+        if (merId.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_Id]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merIdName.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_IdName]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merUrl.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[MerURL]"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val params = hashMapOf<String, String>()
+        params["TransId"] = "IFPR"
+        params["Mer_Id"] = merId.trim()
+        params["Mer_IdName"] = merIdName
+        params["OrderNo"] = refno
+        params["Amount"] = MoneyUtil.formatYuanToString(amount / 100.0)
+        params["OrderDateTime"] = transDateTime
+        params["CurrencyType"] = "156"
+        params["CustomerName"] = custname
+        params["ProductInfo"] = productInfo
+        params["CustomerEMail"] = email
+        params["CustomerSignNo"] = customerSignNo
+        params["MerURL"] = merUrl
+        params["MsgExt"] = extData
+        params["PAY_MODE"] = "QS"
+
+        //调SDK生成签名
+        val signData = YNRCCFastGateWayPayApi.sign(params)
+        if (signData["Plain"].isNullOrEmpty() || signData["Signature"].isNullOrEmpty()) {
+            resp.code = "ZE0002"
+            resp.message = "签名计算错误!"
+            logger.error("签名后[Plain]和[Signature]参数为空!")
+            return resp
+        }
+
+        resp.code = YnrccPayUtil.SUCCESS
+        resp.message = "SUCCESS"
+        resp.plain = signData["Plain"]
+        resp.signature = signData["Signature"]
+        return resp
+    }
+
+    override fun doYnrccPayRefund(shopaccno: String, orignRefno: String, amount: Int, orignTransDate: String): YnrccPayResp {
+        val resp = YnrccPayResp()
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, false)
+        val gateWay = config[YnrccPayUtil.GATEWAY]
+        val merId = config[YnrccPayUtil.MER_ID]
+        if (gateWay.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[网关地址]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merId.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_Id]"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val url = String.format(gateWay, "MerchantWithdraw.do") //赋予接口名
+        val params = hashMapOf<String, String>()
+        params["TransId"] = "IPSR"
+        params["Mer_Id"] = merId.trim()
+        params["OrgMerchantSeqNo"] = orignRefno
+        params["Amount"] = MoneyUtil.formatYuanToString(amount / 100.0)
+        params["OrgMerchantDate"] = orignTransDate
+        params["PAY_MODE"] = "Q"
+
+        val signData = YNRCCFastGateWayPayApi.sign(params) //调SDK生成签名
+        val plain = signData["Plain"]
+        val signature = signData["Signature"]
+        if (plain.isNullOrEmpty() || signature.isNullOrEmpty()) {
+            resp.code = "ZE0002"
+            resp.message = "签名计算错误!"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val result = postForm(url, plain, signature, "退款") //发起表单提交
+        resp.code = result["RespCode"]
+        resp.message = result["RespDesc"]
+        if (YnrccPayUtil.SUCCESS == result["RespCode"]) {
+            resp.transId = result["TransId"]
+            resp.mer_Id = result["Mer_Id"]
+            resp.orgTransAmt = result["OrgTransAmt"]
+            resp.transAmount = result["TransAmount"]
+            resp.merchantSeqNo = result["MerchantSeqNo"]
+            resp.transSeqNo = result["TransSeqNo"]
+        } else {
+            logger.error(resp.error())
+        }
+        return resp
+    }
+
+    override fun doQueryYnrccPayResult(shopaccno: String, orignRefno: String, orignTransDate: String): YnrccPayResp {
+        val resp = YnrccPayResp()
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, false)
+        val gateWay = config[YnrccPayUtil.GATEWAY]
+        val merId = config[YnrccPayUtil.MER_ID]
+        val merIdName = config[YnrccPayUtil.MER_NAME]
+        if (gateWay.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[网关地址]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merId.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_Id]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merIdName.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_IdName]"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val url = String.format(gateWay, "QueryMerchantEpay.do") //赋予接口名
+        val params = hashMapOf<String, String>()
+        params["TransId"] = "IQSR"
+        params["Mer_Id"] = merId.trim()
+        params["Mer_IdName"] = merIdName.trim()
+        params["OrderNo"] = orignRefno
+        params["OrderDate"] = orignTransDate
+        params["PAY_MODE"] = "Q"
+
+        val signData = YNRCCFastGateWayPayApi.sign(params) //调SDK生成签名
+        val plain = signData["Plain"]
+        val signature = signData["Signature"]
+        if (plain.isNullOrEmpty() || signature.isNullOrEmpty()) {
+            resp.code = "ZE0002"
+            resp.message = "签名计算错误!"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val result = postForm(url, plain, signature, "结果查询") //发起表单提交
+        resp.code = result["RespCode"]
+        resp.message = result["RespDesc"]
+        if (YnrccPayUtil.SUCCESS == result["RespCode"]) {
+            resp.transId = result["TransId"]
+            resp.mer_Id = result["Mer_Id"]
+            resp.orgTransId = result["OrgTransId"]
+            resp.orderNo = result["OrderNo"]
+            resp.amount = result["Amount"]
+            resp.amount1 = result["Amount1"]
+            resp.feeAmt = result["FeeAmt"]
+            resp.currencyType = result["CurrencyType"]
+            resp.transSeqNo = result["TransSeqNo"]
+            resp.ppDateTime = result["PpDateTime"]
+            resp.clearingDate = result["ClearingDate"]
+            resp.transStatus = result["TransStatus"]
+        } else {
+            logger.error(resp.error())
+        }
+        return resp
+    }
+
+    override fun doQueryYnrccPayChkfile(checkDate: String, shopaccno: String): YnrccPayResp {
+        val resp = YnrccPayResp()
+        val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_YNRCC_PAY, shopaccno, false, false)
+        val gateWay = config[YnrccPayUtil.GATEWAY]
+        val merId = config[YnrccPayUtil.MER_ID]
+        if (gateWay.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[网关地址]"
+            logger.error(resp.error())
+            return resp
+        }
+        if (merId.isNullOrEmpty()) {
+            resp.code = "ZE0001"
+            resp.message = "系统参数未配置[Mer_Id]"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val url = String.format(gateWay, "MerchantCheckFileQry.do") //赋予接口名
+        val params = hashMapOf<String, String>()
+        params["TransId"] = "IDFR"
+        params["Mer_Id"] = merId.trim()
+        params["ClearDate"] = checkDate
+        params["PAY_MODE"] = "Q"
+
+        val signData = YNRCCFastGateWayPayApi.sign(params) //调SDK生成签名
+        val plain = signData["Plain"]
+        val signature = signData["Signature"]
+        if (plain.isNullOrEmpty() || signature.isNullOrEmpty()) {
+            resp.code = "ZE0002"
+            resp.message = "签名计算错误!"
+            logger.error(resp.error())
+            return resp
+        }
+
+        val result = postForm(url, plain, signature, "对账") //发起表单提交
+        resp.code = result["RespCode"]
+        resp.message = result["RespDesc"]
+        if (YnrccPayUtil.SUCCESS == result["RespCode"]) {
+            resp.plain = result["FileContent"] //对账单
+        }
+        return resp
+    }
+
+}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/ynrcc_netpay_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/ynrcc_netpay_service.kt
new file mode 100644
index 0000000..2510ab4
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/ynrcc_netpay_service.kt
@@ -0,0 +1,107 @@
+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.DtlStatus
+import com.supwisdom.dlpay.agent.citizencard.YnrccRespCode
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayResp
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayUtil
+import com.supwisdom.dlpay.api.dao.TransactionMainDao
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.exception.TransactionProcessException
+import com.supwisdom.dlpay.framework.util.MoneyUtil
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Component
+
+interface YnrccNetPayService {
+    fun doAnalysisSignature(shopaccno: String, plain: String, signature: String): Map<String, String>
+
+    fun doApplyYnrccPaySign(shopaccno: String): YnrccPayResp  //首次签约
+
+    fun doApplyAuthYnrccPaySign(shopaccno: String, oldCustomerSignNo: String): YnrccPayResp //授权签约
+
+    fun doCancelYnrccPaySign(shopaccno: String, customerSignNo: String): YnrccPayResp
+
+    fun doYnrccPayInit(shopaccno: String, refno: String, amount: Int, transDateTime: String, productInfo: String,
+                       extData: String, custname: String, email: String, customerSignNo: String): YnrccPayResp
+
+    fun doYnrccPayRefund(shopaccno: String, orignRefno: String, amount: Int, orignTransDate: String): YnrccPayResp
+
+    fun doQueryYnrccPayResult(shopaccno: String, orignRefno: String, orignTransDate: String): YnrccPayResp
+
+    fun doQueryYnrccPayChkfile(checkDate: String, shopaccno: String): YnrccPayResp
+}
+
+@Component("ynrccpayAgent")
+class YnrccNetPayAgent: AgentPayService<DtlStatus>{
+    @Autowired
+    private lateinit var ynrccNetPayService: YnrccNetPayService
+    @Autowired
+    lateinit var transactionMainDao: TransactionMainDao
+
+    private fun agentCode(code: String, msg: String?): org.springframework.data.util.Pair<AgentCode, YnrccRespCode> {
+        return YnrccPayUtil.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 auth(agentid: String?, billno: String?): AgentResponse<DtlStatus> {
+        return AgentResponse<DtlStatus>().apply {
+            this.code = AgentCode.NOT_SUPPORT
+        }
+    }
+
+    override fun pay(transaction: TTransactionMain): AgentResponse<DtlStatus> {
+        return AgentResponse<DtlStatus>().apply {
+            this.code = AgentCode.NOT_SUPPORT //fixme:支付由客户端发起,服务端无支付逻辑
+        }
+    }
+
+    override fun cancel(transaction: TTransactionMain): AgentResponse<DtlStatus> {
+        return refund(transaction)
+    }
+
+    override fun refund(transaction: TTransactionMain): AgentResponse<DtlStatus> {
+        val originalDtl = transactionMainDao.findByRefno(transaction.reverseRefno)?:
+            throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, "原始流水<${transaction.reverseRefno}>不存在")
+
+        //fixme:必须找原流水获取下单日期
+        val resp = ynrccNetPayService.doYnrccPayRefund(transaction.shopDtl.shopaccno, transaction.reverseRefno,
+                MoneyUtil.YuanToFen(transaction.personDtl.amount), originalDtl.shopDtl.accdate)
+        return AgentResponse<DtlStatus>().also {
+            val code = agentCode(resp.code, resp.message)
+            it.code = code.first
+            it.agentCode = code.second.code
+            it.agentMsg = code.second.msg
+            it.agentRefno = resp.transSeqNo
+        }
+    }
+
+    override fun query(transaction: TTransactionMain): AgentResponse<DtlStatus> {
+        val resp = ynrccNetPayService.doQueryYnrccPayResult(transaction.shopDtl.shopaccno, transaction.refno, transaction.shopDtl.accdate)
+
+        return AgentResponse<DtlStatus>().also {
+            val code = agentCode(resp.code, resp.message)
+            it.code = code.first
+            it.agentCode = code.second.code
+            it.agentMsg = code.second.msg
+            it.agentRefno = resp.transSeqNo
+            it.dtlStatus = when (resp.transStatus) {
+//                00 - 交易成功  01 - 交易失败  02 - 撤消成功  03 - 部分退货  04 - 全部退货    99 - 交易超时
+                "00" -> DtlStatus.SUCCESS
+                "03" -> DtlStatus.PARTIAL_REFUND
+                "04" -> DtlStatus.REFUND
+                else -> DtlStatus.FAIL
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/ynrccpay_checkfile_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/ynrccpay_checkfile_service.kt
new file mode 100644
index 0000000..21fc8c1
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/ynrccpay_checkfile_service.kt
@@ -0,0 +1,226 @@
+package com.supwisdom.dlpay.agent.service
+
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.CheckFileProvider
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayChkfile
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayUtil
+import com.supwisdom.dlpay.api.domain.TSourceTypeCheckStatus
+import com.supwisdom.dlpay.api.domain.TTransactionChkfile
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.api.service.TransactionReconciliationService
+import com.supwisdom.dlpay.exception.TransactionException
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.StringUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.util.ConstantUtil
+import mu.KotlinLogging
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Component
+import java.io.BufferedReader
+import java.io.ByteArrayInputStream
+import java.io.InputStreamReader
+import java.nio.charset.Charset
+
+@Component("ynrccpayCheckFileProvider")
+class YnrccpayCheckFileProvider : CheckFileProvider {
+    @Autowired
+    private lateinit var systemUtilService: SystemUtilService
+    @Autowired
+    private lateinit var transactionReconciliationService: TransactionReconciliationService
+    @Autowired
+    private lateinit var sourceTypeService: SourceTypeService
+    @Autowired
+    private lateinit var ynrccNetPayService:YnrccNetPayService
+
+    private val logger = KotlinLogging.logger { }
+
+    override fun acquireCheckFile(checkStatus: TSourceTypeCheckStatus): AgentResponse<TSourceTypeCheckStatus> {
+        try {
+            val billDate = checkStatus.checkAccdate
+            logger.info("【农商行网关快捷支付】对账单下载:download checkdate=【$billDate】")
+
+            val chkfile: TTransactionChkfile = transactionReconciliationService
+                .getTransactionChkfile(billDate, checkStatus.sourceType)?.let { file ->
+                    when (file.status) {
+                        ConstantUtil.CHKFILE_STATUS_INIT -> file //初始化直接返回
+                        ConstantUtil.CHKFILE_STATUS_ERROR -> reinitCheckFile(file) //错误或未对账的直接重新拉取
+                        else -> {
+                            when (checkStatus.forceRecheck) {
+                                true -> reinitCheckFile(file)  //对账已完成但强制重新对账
+                                false -> {
+                                    if (file.status == ConstantUtil.CHKFILE_STATUS_UNCHECK) {
+                                        file
+                                    } else {
+                                        throw TransactionException(-1, "【农商行网关快捷支付】该天[$billDate]已对账完成")
+                                    }
+                                } //对账已完成报错
+                            }
+                        }
+                    }
+                }
+                ?: transactionReconciliationService.saveInitTransactionChkfile(billDate, checkStatus.sourceType)
+
+            if (chkfile.status == ConstantUtil.CHKFILE_STATUS_UNCHECK) {
+                return successDownload("[$billDate]日对账数据已入库成功", checkStatus)
+            }
+
+            val fileDataList = ArrayList<YnrccPayChkfile>(0)
+            val shopaccList = sourceTypeService.getShopaccnoBySourcetype(TradeDict.PAYTYPE_YNRCC_PAY) //所有开通快捷支付的商户
+            for (shopacc in shopaccList) {
+                val resp = ynrccNetPayService.doQueryYnrccPayChkfile(billDate, shopacc)
+                when (resp.code) {
+                    YnrccPayUtil.SUCCESS -> {
+                        //成功
+                        BufferedReader(InputStreamReader(resp.plain?.byteInputStream(Charset.forName("UTF-8")))).use { reader ->
+                            val totalCnt = reader.readLine()?.trim()?.toInt() //总条目数
+                            var records = 0
+                            while (true) {
+                                val line = reader.readLine() ?: break
+                                if (line.isEmpty()) continue
+                                val columns = line.split(YnrccPayUtil.chkFileDelimiter)
+                                val bean = YnrccPayChkfile()
+                                try {
+                                    StringUtil.transforToBean(YnrccPayChkfile.HEADER, columns, bean)
+                                }catch (etr:Exception){
+                                    throw TransactionException(97, "商户[$shopacc]对账单下载[$billDate]文件明细解析错误!${etr.message}")
+                                }
+                                fileDataList.add(bean)
+                                records++
+                            }
+                            if (totalCnt != records) {
+                                throw TransactionException(97, "商户[$shopacc]对账单下载[$billDate]文件总交易笔数和明细不符!")
+                            }
+                        }
+                    }
+                    YnrccPayUtil.NO_RECORDS_TODAY -> {
+                        //fixme:当日无交易明细
+                    }
+                    else -> {
+                        //报错,退出对账单拉取
+                        logger.error("农商行网关快捷支付商户[$shopacc]对账单下载[$billDate]报错:${resp.message}")
+                        chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+                        chkfile.remark = "商户[$shopacc]请求获取对账文件报错:${resp.message}"
+                        transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
+
+                        //失败,直接返回
+                        return AgentResponse<TSourceTypeCheckStatus>().also {
+                            it.code = AgentCode.FAIL
+                            it.agentMsg = chkfile.remark
+                            it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                                this.remark = chkfile.remark
+                            })
+                        }
+                    }
+                }
+            }
+
+            if(fileDataList.isEmpty()){
+                //当日无交易明细,也创建空记录
+                transactionReconciliationService.doSuccessTransactionChkfile(chkfile, "请求银行返回:当日无交易明细")
+                //成功
+                return successDownload("当日无交易明细", checkStatus.apply {
+                    this.chkfileUrl = "none"
+                })
+            }
+
+            //保存对账单
+            val failcnt = doBatchSaveYnrccPayCheckDetails(chkfile, fileDataList)
+            if (failcnt > 0) {
+                chkfile.status = ConstantUtil.CHKFILE_STATUS_ERROR
+                chkfile.remark = "对账单数据存在保存失败记录,请手动核对对账单数据"
+                transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile)
+
+                return AgentResponse<TSourceTypeCheckStatus>().also {
+                    it.code = AgentCode.FAIL
+                    it.agentMsg = chkfile.remark
+                    it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                        this.checkFileOk = false
+                        this.chkfileUrl = "none"
+                        this.remark = chkfile.remark
+                    })
+                }
+            }
+
+            //成功
+            transactionReconciliationService.doSuccessTransactionChkfile(chkfile, "对账单数据下载成功")
+            return successDownload("[$billDate]日对账数据入库成功", checkStatus.apply {
+                this.chkfileUrl = "none"
+            })
+
+        } catch (et: TransactionException) {
+            return AgentResponse<TSourceTypeCheckStatus>().also {
+                it.code = AgentCode.FAIL
+                it.agentMsg = et.message
+                it.agentCode = "${et.code()}"
+                it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                    this.remark = et.message
+                })
+            }
+        }
+
+    }
+
+    override fun queryCheckFile(checkStatus: TSourceTypeCheckStatus?): AgentResponse<TSourceTypeCheckStatus> {
+        return AgentResponse<TSourceTypeCheckStatus>().also {
+            it.code = AgentCode.SUCCESS
+            it.agentMsg = "OK"
+            it.payload = checkStatus
+        }
+    }
+
+    override fun downloadCheckFile(checkStatus: TSourceTypeCheckStatus?): AgentResponse<TSourceTypeCheckStatus> {
+        return AgentResponse<TSourceTypeCheckStatus>().also {
+            it.code = AgentCode.SUCCESS
+            it.agentMsg = "OK"
+            it.payload = checkStatus
+        }
+    }
+
+    private fun reinitCheckFile(chkfile: TTransactionChkfile): TTransactionChkfile {
+        transactionReconciliationService.deleteTransactionChkdtls(chkfile.id) //删除明细
+        return transactionReconciliationService.saveOrUpdateTransactionChkfile(chkfile.apply {
+            this.status = ConstantUtil.CHKFILE_STATUS_INIT
+            this.result = ConstantUtil.CHKFILE_RESULT_NONE
+            this.remark = null
+            this.othercnt = 0
+            this.otheramt = 0.00
+            this.localcnt = 0
+            this.localamt = 0.00
+        }) //初始化chkfile
+    }
+
+    private fun successDownload(message: String, checkStatus: TSourceTypeCheckStatus): AgentResponse<TSourceTypeCheckStatus> {
+        return AgentResponse<TSourceTypeCheckStatus>().also {
+            it.code = AgentCode.SUCCESS
+            it.agentMsg = message
+            it.payload = sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus.apply {
+                this.checkFileOk = true
+                this.remark = message
+            })
+        }
+    }
+
+    private fun doBatchSaveYnrccPayCheckDetails(chkfile: TTransactionChkfile, list: ArrayList<YnrccPayChkfile>): Int {
+        try {
+            transactionReconciliationService.doBatchSaveYnrccPayTransactionChkDtl(chkfile, list)
+            return 0  //批量保存成功,无失败
+        } catch (e1: Exception) {
+        }
+
+        //批量保存有异常,逐笔保存
+        var failcnt = 0
+        var index = 1
+        for (bean in list) {
+            try {
+                transactionReconciliationService.saveYnrccPayTransactionChkDtl(chkfile, bean, index++)
+            } 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/advices.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
index 1fda9f0..17d1d2e 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
@@ -48,6 +48,7 @@
                     .exception(undeclared.code(), undeclared, "业务处理错误"))
         }
 
+        ex.printStackTrace()
         return ResponseEntity.ok().body(ResponseBodyBuilder.create()
                 .exception(TradeErrorCode.BUSINESS_DEAL_ERROR, undeclared, "业务处理报错"))
     }
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 f01d870..fd77c55 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
@@ -7,6 +7,7 @@
 import com.supwisdom.dlpay.api.domain.TShopdtl
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.repositories.ShopaccService
+import com.supwisdom.dlpay.api.service.ConsumePayService
 import com.supwisdom.dlpay.api.service.DtlQueryResultService
 import com.supwisdom.dlpay.api.service.TransactionServiceProxy
 import com.supwisdom.dlpay.exception.TransactionException
@@ -123,6 +124,9 @@
     @Autowired
     private lateinit var systemUtilService: SystemUtilService
 
+    @Autowired
+    lateinit var consumePayService: ConsumePayService
+
     @Async("queryAgentPayResult")
     fun queryResult(transaction: TTransactionMain, qcnt: Int) {
         try {
@@ -148,31 +152,41 @@
                     transaction.sourceType + "Agent")
 
             logger.info("refno=[${transaction.refno}]开始第" + (qcnt + 1) + "次查询支付结果:")
+            var endFlag = false
             val resp = service.query(transaction)
             when (resp.code) {
                 AgentCode.SUCCESS -> {
                     //查询成功
                     when (resp.dtlStatus) {
-                        DtlStatus.SUCCESS ->
+                        DtlStatus.SUCCESS -> {
+                            endFlag = true
                             transactionService.success(transaction.refno, resp.agentRefno, false) //流水成功
+                        }
                         DtlStatus.REFUND -> {
                             //流水已退款 TODO:流水成功后才退款,无查询原成功流水逻辑
+                            endFlag = true
                             logger.error("refno=[${transaction.refno}]查询结果为:已退款!!!")
                             return
                         }
                         DtlStatus.PARTIAL_REFUND -> {
                             //流水已部分退款 TODO:暂无逻辑
+                            endFlag = true
                             logger.error("refno=[${transaction.refno}]查询结果为:已部分退款!!!")
                             return
                         }
                         else -> {
                             //流水失败
+                            endFlag = true
                             transactionService.fail(transaction.refno, "查询流水状态为交易失败")
                         }
                     }
                 }
-                AgentCode.REFNO_NOT_EXISTS ->
-                    transactionService.fail(transaction.refno, "银行流水不存在") //银行返回流水不存在
+                AgentCode.REFNO_NOT_EXISTS -> {
+                    if(TradeDict.REVERSE_FLAG_NONE == transaction.reverseType) {
+                        endFlag = true
+                        transactionService.fail(transaction.refno, "银行流水不存在") //银行返回流水不存在
+                    }
+                }
                 AgentCode.REQUIRE_QUERY -> {
                     queryResult(transaction, qcnt + 1)  //查询次数加1
                 }
@@ -181,6 +195,36 @@
                     logger.error("查询refno=[${transaction.refno}]流水结果返回失败:code=[${resp.agentCode}],message=[${resp.agentMsg}]")
                 }
             }
+
+            //fixme: 撤销或退款可能不需要传商户订单号,必须查询原流水状态
+            if (!endFlag && (TradeDict.REVERSE_FLAG_CANCEL == transaction.reverseType || TradeDict.REVERSE_FLAG_REFUND == transaction.reverseType)) {
+                consumePayService.getTransactionMainDtl(transaction.reverseRefno, null, null)?.let {
+                    val origResp = service.query(it) //冲正流水,只能查询原始流水是否为退款状态
+                    when (origResp.code) {
+                        AgentCode.SUCCESS ->{
+                            when (origResp.dtlStatus) {
+                                DtlStatus.SUCCESS ->
+                                    transactionService.fail(transaction.refno, "查询确认退款失败!") //原始流水还是成功状态,则退款流水必定失败!!!
+                                DtlStatus.REFUND -> {
+                                    //流水已退款
+                                    transactionService.success(transaction.refno, origResp.agentRefno, false) //TODO: 确保这条原始流水只有一笔全额冲正流水成功!!!
+                                }
+                                DtlStatus.PARTIAL_REFUND -> {
+                                    //流水已部分退款 TODO:暂无逻辑
+                                }
+                                else -> {
+                                    //流水失败 无逻辑
+                                }
+                            }
+                        }
+                        else -> {
+                            //其他都重新查
+                            queryResult(transaction, qcnt + 1)  //查询次数加1
+                        }
+                    }
+                }
+            }
+
         } catch (ex: Exception) {
             ex.printStackTrace()
         }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
index 21edbe8..5c3163c 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
@@ -5,6 +5,8 @@
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
 import com.supwisdom.dlpay.framework.util.*
 import com.supwisdom.dlpay.util.DesUtil
+import java.util.*
+import kotlin.collections.ArrayList
 
 class DaliDatasyncParam {
     var app_id: String = ""
@@ -85,4 +87,59 @@
     var errmsg: String = ""
 }
 
+/**
+ * 农商行推送线下签约数据报文
+ * */
+class YnrccSendSignInfoParam {
+    var appId: String = ""
+    var bankCardNo: String = ""
+    var idType: String = ""
+    var idNo: String = ""
+    var phone: String = ""
+    var signStatus: String = ""
+    var timestamp: String = ""
+    var signType: String = ""
+    var sign: String = ""
+
+    fun checkParam(): Boolean {
+        if (StringUtil.isEmpty(appId)) {
+            throw RequestParamCheckException("请求参数错误[应用ID为空]")
+        }
+        if(StringUtil.isEmpty(bankCardNo)){
+            throw RequestParamCheckException("请求参数错误[银行卡号为空]")
+        }
+        if (StringUtil.isEmpty(idType)) {
+            throw RequestParamCheckException("请求参数错误[证件类型为空]")
+        }
+        if (StringUtil.isEmpty(idNo)) {
+            throw RequestParamCheckException("请求参数错误[证件号码为空]")
+        }
+        if (StringUtil.isEmpty(phone)) {
+            throw RequestParamCheckException("请求参数错误[手机号为空]")
+        }
+        if (StringUtil.isEmpty(phone)) {
+            throw RequestParamCheckException("请求参数错误[手机号为空]")
+        }
+        if(!listOf("Y","N").contains(signStatus)){
+            throw RequestParamCheckException("请求参数错误[签约状态(Y/N)]")
+        }
+        if (!DateUtil.checkDatetimeValid(timestamp, DateUtil.DATETIME_FMT)) {
+            throw RequestParamCheckException("请求参数错误[时间戳]")
+        }
+        if (StringUtil.isEmpty(signType)
+            || !"HmacSHA256".equals(signType, true)) {
+            throw RequestParamCheckException("请求参数错误[签名算法]")
+        }
+        if (StringUtil.isEmpty(sign)) {
+            throw RequestParamCheckException("请求参数错误[签名为空]")
+        }
+        return true
+    }
+
+    fun checkSign(key: String): Boolean {
+        val signData ="appId=$appId&bankCardNo=$bankCardNo&idType=$idType&idNo=$idNo&phone=$phone&signStatus=$signStatus&timestamp=$timestamp"
+        return sign.equals(HmacUtil.HMACSHA256(signData, key), true)
+    }
+}
+
 
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 692be0c..da34d6d 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
@@ -11,12 +11,11 @@
 import com.supwisdom.dlpay.api.bean.groups.InitAction
 import com.supwisdom.dlpay.api.domain.TSourceType
 import com.supwisdom.dlpay.api.service.*
-import com.supwisdom.dlpay.api.util.Constants
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.SystemUtilService
-import com.supwisdom.dlpay.framework.tenant.TenantContext
 import com.supwisdom.dlpay.framework.util.*
+import mu.KotlinLogging
 import org.apache.commons.lang3.StringUtils
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.context.ApplicationContext
@@ -59,6 +58,11 @@
     @Autowired
     private lateinit var qrCodeService: QRCodeService
 
+    @Autowired
+    private lateinit var ynrccNetPayBusinessService: YnrccNetPayBusinessService
+
+    private val logger = KotlinLogging.logger { }
+
     /**
      * ============================================================================
      * 消费流水结果查询统一接口
@@ -838,5 +842,254 @@
         })
     }
 
+    /**
+     * ============================================================================
+     *                           农商行网关快捷支付【初始化下单】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpay/order")
+    fun ynrccPayOrder(@Valid @RequestBody param: YnrccPayOrderParam): ResponseEntity<Any> {
+        val userSign = ynrccNetPayBusinessService.queryUserYnrccPaySignInfo(param.bankcardno, param.shopaccno)
+        if (null == userSign || !userSign.isSignFlag || StringUtil.isEmpty(userSign.customerSignNo)) {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_USER_NO_SIGN, "用户未签约农商行网关快捷支付!"))
+        }
 
+        val person = userService.findOnePersonByUserid(param.userid)
+        if (person.userid != userSign.userid) {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(TradeErrorCode.INPUT_DATA_ERROR, "银行卡持有人错误!"))
+        }
+        val dtlType = consumePayService.getDtltypeDictionary(param.dtltype, Dictionary.DTLTYPES)
+        if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_YNRCC_PAY)) {
+            val account = accountUtilServcie.readAccount(person.userid)
+            val shopacc = accountUtilServcie.readShopbyShopaccno(param.shopaccno)
+            val subject = accountUtilServcie.readSubject(Subject.SUBJNO_YNRCC_NETPAY)
+            val transaction = TransactionBuilder().apply {
+                setTransInfo(param.transdate, param.transtime,
+                        TradeCode.TRANSCODE_YNRCC_NETPAY,
+                        TradeDict.PAYTYPE_YNRCC_PAY)
+                setOutTransInfo(shopacc.shopaccno, param.billno)
+                operator(param.shopaccno, TradeDict.OPERTYPE_SHOP)
+                payinfo = userSign.customerSignNo //存放签约协议号
+                description = dtlType.dictcaption
+                dtltype = param.dtltype
+            }.person(account).apply {
+                setAmount(param.amount / 100.0, TradeDict.TRADE_FLAG_OUT)
+                setOpposite(AccountProxy(shopacc))
+            }.and().shop(shopacc).apply {
+                setAmount(param.amount / 100.0, TradeDict.TRADE_FLAG_IN)
+                setOpposite(AccountProxy(account))
+            }.and().addDebitCreditRecord(AccountProxy(subject), AccountProxy(account),
+                    param.amount / 100.0, dtlType.dictcaption)
+                    .addDebitCreditRecord(AccountProxy(account), AccountProxy(shopacc),
+                            param.amount / 100.0, dtlType.dictcaption)
+                    .also {
+//                        param.feelist?.also {
+//                            TODO("feelist 费用清单暂无!")
+//                        }
+                    }.init(transactionService)
+
+            //创建初始化流水后,返回客户端sdk需要的支付参数
+            val resp = ynrccNetPayBusinessService.doYnrccPayInit(transaction, userSign)
+
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(resp, "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<农商行网关快捷支付>"))
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行网关快捷支付【下单支付确认】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpay/confirm")
+    fun ynrccPayConfirm(@Valid @RequestBody param: YnrccPayConfirmParam): ResponseEntity<Any> {
+        val dtl = transactionService.wip(param.refno)
+        val resp = ynrccNetPayBusinessService.doYnrccPayConfirm(dtl, param.plain, param.signature)
+        val ret = YnrccPayConfirmResponse(dtl.refno,dtl.outTradeNo,dtl.shopDtl.amount,resp.params)
+        when (resp.code) {
+            AgentCode.SUCCESS ->
+                transactionService.success(dtl.refno, resp.agentRefno, false).let {
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .success(ret, "交易确认成功"))
+                }
+            AgentCode.REQUIRE_QUERY -> {
+                //去查询
+                agentQueryResultTask.queryResult(dtl, 0)
+                return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(ret, TradeErrorCode.WAIT_QUERY_RESULT, "请查询支付结果"))
+            }
+            else -> //失败
+                transactionService.fail(param.refno, resp.agentMsg).let {
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .fail(ret, TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${resp.agentMsg}"))
+                }
+        }
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行网关快捷支付【退款】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpay/refund")
+    fun ynrccPayRefund(@Valid @RequestBody param: YnrccPayRefundParam): ResponseEntity<Any> {
+        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)
+                }
+            } else {
+                throw TransactionCheckException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
+                        "该笔交易未定义sourcetype, 不支持退款")
+            }
+
+            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)
+            val service = createAgentService<Any>(mainDtl.sourceType)
+            val resp = service.refund(refundTrans)
+            when (resp.code) {
+                AgentCode.SUCCESS -> {
+                    transactionService.success(refundTrans.refno, resp.agentRefno, false)
+
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .success(YnrccPayRefundResponse(refundTrans.refno), "交易退款成功"))
+                }
+                AgentCode.REQUIRE_QUERY -> {
+                    //待查询
+                    agentQueryResultTask.queryResult(refundTrans, 0)
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .fail(YnrccPayRefundResponse(refundTrans.refno),
+                                    TradeErrorCode.WAIT_QUERY_RESULT, "请查询退款结果"))
+                }
+                else -> transactionService.fail(refundTrans.refno,
+                        "${resp.agentCode}-${resp.agentMsg}").let {
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .fail(YnrccPayRefundResponse(refundTrans.refno),
+                                    TradeErrorCode.BUSINESS_DEAL_ERROR, "退款失败!${resp.agentMsg}"))
+                }
+            }
+
+        } ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在"))
+    }
+
+    /**
+     * ============================================================================
+     *                      直接调第三方查询流水结果 (通用)
+     * ============================================================================
+     * */
+    @PostMapping("/thirdquery")
+    fun queryDtlResultByThird(@Valid @RequestBody param: QueryDtlResultParam): ResponseEntity<Any> {
+        consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let {
+            if (TradeDict.DTL_STATUS_SUCCESS == it.status || TradeDict.DTL_STATUS_FAIL == it.status) {
+                return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(QueryTransDtlResponse(it.refno, it.outTradeNo, it.shopDtl.amount,
+                        it.status, it.sourceType, it.personDtl.payinfo, it.reverseFlag,
+                        it.shopDtl.transdesc,it.personDtl.remark), "查询成功"))
+            }
+
+            //发往第三方查询
+            var endFlag = false
+            val service = ApplicationUtil.findAgentPayService<Any>(applicationContext, it.sourceType + "Agent")
+            val resp = service.query(it)
+            when (resp.code) {
+                AgentCode.SUCCESS -> {
+                    //查询成功
+                    when (resp.dtlStatus) {
+                        DtlStatus.SUCCESS -> {
+                            endFlag = true
+                            transactionService.success(it.refno, resp.agentRefno, false) //流水成功
+                        }
+                        DtlStatus.REFUND -> {
+                            //流水已退款 TODO:流水成功后才退款,无查询原成功流水逻辑
+                        }
+                        DtlStatus.PARTIAL_REFUND -> {
+                            //流水已部分退款 TODO:暂无逻辑
+                        }
+                        else -> {
+                            //流水失败
+                            endFlag = true
+                            transactionService.fail(it.refno, "查询流水状态为交易失败")
+                        }
+                    }
+                }
+                AgentCode.REFNO_NOT_EXISTS -> {
+                    if(TradeDict.REVERSE_FLAG_NONE == it.reverseType){
+                        endFlag = true
+                        transactionService.fail(it.refno, "银行流水不存在") //银行返回流水不存在
+                    }
+                }
+                AgentCode.REQUIRE_QUERY -> {
+                    //流水无结果 TODO: 还需继续查询
+                }
+                else -> {
+                    //其他明确错误,查询失败
+                    logger.error("向第三方查询 refno=[${it.refno}]流水结果返回失败:code=[${resp.agentCode}],message=[${resp.agentMsg}]")
+                }
+            }
+
+            //TODO: 撤销或退款可能不需要传商户订单号,必须查询原流水状态
+            if (!endFlag && (TradeDict.REVERSE_FLAG_CANCEL == it.reverseType || TradeDict.REVERSE_FLAG_REFUND == it.reverseType)) {
+                consumePayService.getTransactionMainDtl(it.reverseRefno, null, null)?.let { origDtl ->
+                    val origResp = service.query(origDtl) //有冲正流水,原流水必定是成功流水。判断原流水状态是否为退款状态
+                    when (origResp.code) {
+                        AgentCode.SUCCESS -> {
+                            when (origResp.dtlStatus) {
+                                DtlStatus.SUCCESS ->
+                                    transactionService.fail(it.refno, "查询确认退款失败!") //原始流水还是成功状态,则退款流水必定失败!!!
+                                DtlStatus.REFUND -> {
+                                    //流水已退款
+                                    transactionService.success(it.refno, origResp.agentRefno, false) //TODO: 确保这条原始流水只有一笔全额冲正流水成功!!!
+                                }
+                                DtlStatus.PARTIAL_REFUND -> {
+                                    //流水已部分退款 TODO:暂无逻辑
+                                }
+                                else -> {
+                                    //流水失败 无逻辑
+                                }
+                            }
+                        }
+                        else -> {
+                            logger.error("向第三方查询 refno=[${it.refno}]冲正流水结果,原始流水支付状态查询返回失败:code=[${origResp.agentCode}],message=[${origResp.agentMsg}]")
+                        }
+                    }
+                }
+            }
+
+            return queryDtlResult(param) //直接查询逻辑
+
+        } ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在")
+        )
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行网关快捷支付【第三方开放能力】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpay/thirdAuth")
+    fun ynrccPayThirdAuth(@Valid @RequestBody param: YnrccPayThirdAuthParam): ResponseEntity<Any> {
+        val ret = ynrccNetPayBusinessService.doYnrccPayThirdAuth(param.thirdservice,param.bankcardno,param.userid)
+        return if (ret.retcode == 0) {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                .success(ret, "成功"))
+        } else {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(ret.retcode, ret.retmsg))
+        }
+    }
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/dali_datasync_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/dali_datasync_api_controller.kt
index ee0d97a..d017f6e 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/dali_datasync_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/dali_datasync_api_controller.kt
@@ -4,6 +4,7 @@
 import com.supwisdom.dlpay.api.bean.DaliDatasyncDetail
 import com.supwisdom.dlpay.api.bean.DaliDatasyncErrorDetail
 import com.supwisdom.dlpay.api.bean.DaliDatasyncParam
+import com.supwisdom.dlpay.api.bean.YnrccSendSignInfoParam
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
 import com.supwisdom.dlpay.api.service.DaliDatasyncService
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
@@ -247,5 +248,39 @@
         }
     }
 
+    /**
+     * ============================================================================
+     * 大理卡管系统推送市民卡信息同步接口
+     * ============================================================================
+     * */
+    @PostMapping("/signsync")
+    fun daliDatasync(@RequestBody param: YnrccSendSignInfoParam): ResponseEntity<Any> {
+        try{
+            if (TenantContext.getTenantSchema() == null) TenantContext.setTenantSchema(Constants.DEFAULT_TENANTID) //fixme: tenantid设置
+            param.checkParam()
+            val appid = systemUtilService.getSysparaValue(2022)
+            val appkey = systemUtilService.getSysparaValue(2023)
+            if (StringUtil.isEmpty(appid) || StringUtil.isEmpty(appkey)) {
+                return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(1000, "系统参数未配置"))
+            } else if (appid != param.appId) {
+                throw RequestParamCheckException("请求参数错误[应用ID错误]")
+            }
+            if (!param.checkSign(appkey)) {
+                return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(2002, "签名错误"))
+            }
+
+            return  ResponseEntity.ok(mapOf("retcode" to "0000", "retmsg" to "SUCCESS"))
+        }catch (ex: RequestParamCheckException) {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(2001, ex.message ?: "请求参数错误"))
+        }catch (e:Exception){
+            e.printStackTrace()
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(4000, "系统业务处理异常"))
+        }
+
+    }
 
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
index 0171ced..8d8fb8f 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
@@ -4,10 +4,7 @@
 import com.supwisdom.dlpay.agent.service.CitizencardPayService
 import com.supwisdom.dlpay.api.bean.*
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
-import com.supwisdom.dlpay.api.service.CardService
-import com.supwisdom.dlpay.api.service.KafkaSendMsgService
-import com.supwisdom.dlpay.api.service.QRCodeService
-import com.supwisdom.dlpay.api.service.UserService
+import com.supwisdom.dlpay.api.service.*
 import com.supwisdom.dlpay.exception.TransactionException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.util.TradeDict
@@ -15,11 +12,14 @@
 import com.supwisdom.dlpay.mobile.service.MobileApiService
 import com.supwisdom.dlpay.system.bean.LevelBean
 import com.supwisdom.dlpay.system.service.PointsService
+import com.supwisdom.dlpay.system.service.UserMessageService
 import org.apache.commons.beanutils.BeanUtils
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.http.ResponseEntity
+import org.springframework.validation.annotation.Validated
 import org.springframework.web.bind.annotation.*
 import java.net.URLDecoder
+import javax.validation.Valid
 
 @RestController
 @RequestMapping("/api/user")
@@ -40,8 +40,10 @@
     private lateinit var citizencardPayService: CitizencardPayService
     @Autowired
     private lateinit var qrcodeService: QRCodeService
-
-
+    @Autowired
+    private lateinit var ynrccNetPayBusinessService: YnrccNetPayBusinessService
+    @Autowired
+    private lateinit var userMessageService: UserMessageService
 
     @PostMapping("/open")
     fun openAccount(@RequestBody param: OpenUserParam): ResponseEntity<Any> {
@@ -446,4 +448,122 @@
                     .fail(ret.retcode, ret.retmsg))
         }
     }
+
+    /**
+     * 查询用户消息
+     * */
+    @PostMapping("/queryMessage")
+    fun queryUserMessage(@Valid @RequestBody param: UserQueryMessageParam): ResponseEntity<Any> {
+        val userid = param.userid ?: throw RequestParamCheckException("用户ID不能为空")
+        val pageNo = param.pageNo ?: 1
+        val pageSize = param.pageSize ?: 10
+        val page = userMessageService.queryMessageByUserid(userid, pageNo, pageSize)
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+            .success(UserQueryMessageResponse().apply {
+                this.pageNo = page.pageNo
+                this.pageSize = page.pageSize
+                this.totalCount = page.totalCount
+                this.totalPages = page.totalPages
+                this.data = page.data
+            }, "success")
+        )
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【签约状态查询】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignQuery")
+    fun queryYnrccPaySign(@Valid @RequestBody param: YnrccPaySignQueryParam): ResponseEntity<Any> {
+        val signFlag = ynrccNetPayBusinessService.checkUserYnrccPaySignStatus(param.userid,param.bankcardno,param.shopaccno)
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .success(YnrccPaySignQueryResponse(signFlag), "查询成功"))
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【签约列表查询】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignList")
+    fun queryYnrccPaySignList(@Valid @RequestBody param: YnrccPaySignListQueryParam): ResponseEntity<Any> {
+        val resp = ynrccNetPayBusinessService.doQueryYnrccPaySignList(param.userid, param.bankcardno)
+        return if (0 == resp.retcode) {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                .success(resp, "success"))
+        } else {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(resp.retcode, resp.retmsg))
+        }
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【签约申请】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignApply")
+    fun applyYnrccPaySign(@Valid @RequestBody param: YnrccPaySignApplyParam): ResponseEntity<Any> {
+        val resp = ynrccNetPayBusinessService.applyUserYnrccPaySign(param)
+        return if (0 == resp.retcode) {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                .success(resp, "success"))
+        } else {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(resp.retcode, resp.retmsg))
+        }
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【签约确认】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignConfirm")
+    fun confirmYnrccPaySign(@Valid @RequestBody param: YnrccPaySignConfirmParam): ResponseEntity<Any> {
+        val resp = ynrccNetPayBusinessService.confirmUserYnrccPaySign(param)
+        return if (0 == resp.retcode) {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(resp, "success"))
+        } else {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(resp.retcode, resp.retmsg))
+        }
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【解约】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignCancel")
+    fun cancelYnrccPaySign(@Valid @RequestBody param:YnrccPaySignCancelParam):ResponseEntity<Any>{
+        val resp = ynrccNetPayBusinessService.cancelUserYnrccPaySign(param)
+        return if (0 == resp.retcode) {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(resp, "success"))
+        } else {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(resp.retcode, resp.retmsg))
+        }
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【修改限额】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpayModifyLimit")
+    fun modifyYnrccPayLimit(@Valid @RequestBody param:YnrccPayLimitModifyParam):ResponseEntity<Any>{
+        val success=false
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPayLimitModifyResponse(), "success"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "暂无业务逻辑"))
+
+    }
 }
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 9937a31..8292e63 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,6 +1,7 @@
 package com.supwisdom.dlpay.api.service.impl
 
 import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayChkfile
 import com.supwisdom.dlpay.api.bean.YnrccChkfileBean
 import com.supwisdom.dlpay.api.dao.PersondtlDao
 import com.supwisdom.dlpay.api.dao.TransactionChkdtlDao
@@ -9,6 +10,7 @@
 import com.supwisdom.dlpay.api.domain.TSourceTypeCheckStatus
 import com.supwisdom.dlpay.api.domain.TTransactionChkdtl
 import com.supwisdom.dlpay.api.domain.TTransactionChkfile
+import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.service.SourceTypeService
 import com.supwisdom.dlpay.api.service.TransactionReconciliationService
 import com.supwisdom.dlpay.api.service.TransactionServiceProxy
@@ -305,4 +307,72 @@
         transactionChkfileDao.save(chkfile)
         return sourceTypeService.saveOrUpdateSourceTypeCheckStatus(checkStatus)
     }
+
+    override fun doBatchSaveYnrccPayTransactionChkDtl(chkfile: TTransactionChkfile, list: ArrayList<YnrccPayChkfile>): Boolean {
+        var idx=1
+        for (bean in list) {
+            saveYnrccPayTransactionChkDtl(chkfile, bean, idx++)
+        }
+        return true
+    }
+
+    override fun saveYnrccPayTransactionChkDtl(chkfile: TTransactionChkfile, bean: YnrccPayChkfile, idx:Int): TTransactionChkdtl {
+        return when(bean.payFlag){
+            YnrccPayChkfile.PAY->{
+                transactionChkdtlDao.save(TTransactionChkdtl().apply {
+                    this.chkfileId = chkfile.id
+                    this.accdate = chkfile.accdate
+                    this.sourcetype = chkfile.sourcetype
+                    this.recordno = idx
+                    this.amount = -1 * bean.amount.toDouble()
+                    this.otherRefno = bean.agentRefno
+                    this.localRefno = bean.billNo
+                    this.otherAccdate = bean.clearDate
+                    this.transtype = "pay"
+                    this.otherStatus = "success"
+                    this.remark = null
+                    this.extdata = "农商行网关快捷支付"
+                    this.chkresult = ConstantUtil.CHKDTL_CHKRESULT_UNCHECK
+                    this.resolved = ConstantUtil.CHKDTL_RESOLVED_NONE
+                    this.lastsaved = systemUtilService.sysdatetime.sysdate
+                    this.tenantid = TenantContext.getTenantSchema()
+                })
+            }
+            YnrccPayChkfile.REFUND->{
+                val refno = bean.agentRefno //商户订单号
+                var localRefno = bean.billNo
+                val refundSuccessList = transactionMainDao.findByRefundSuccessTransdtl(refno)
+                if (null != refundSuccessList && refundSuccessList.size > 0) {
+                    localRefno = refundSuccessList[0].refno //成功的退款流水
+                } else {
+                    val refundTransdtlList = transactionMainDao.findByRefundTransdtl(refno)
+                    if (null != refundTransdtlList && refundTransdtlList.size > 0) {
+                        localRefno = refundTransdtlList[0].refno //第一笔退款的流水
+                    }
+                }
+
+                transactionChkdtlDao.save(TTransactionChkdtl().apply {
+                    this.chkfileId = chkfile.id
+                    this.accdate = chkfile.accdate
+                    this.sourcetype = chkfile.sourcetype
+                    this.recordno = idx
+                    this.amount = bean.amount.toDouble()
+                    this.otherRefno = bean.billNo
+                    this.localRefno = localRefno
+                    this.otherAccdate = bean.clearDate
+                    this.transtype = "refund"
+                    this.otherStatus = "success"
+                    this.remark = null
+                    this.extdata = "农商行网关快捷支付退款[${bean.agentRefno}]"
+                    this.chkresult = ConstantUtil.CHKDTL_CHKRESULT_UNCHECK
+                    this.resolved = ConstantUtil.CHKDTL_RESOLVED_NONE
+                    this.lastsaved = systemUtilService.sysdatetime.sysdate
+                    this.tenantid = TenantContext.getTenantSchema()
+                })
+            }
+            else -> {
+                throw TransactionException(97, "不能识别对账单明细中交易代码[${bean.payFlag}]!")
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/ynrcc_netpay_business_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/ynrcc_netpay_business_service.kt
new file mode 100644
index 0000000..bd6be6c
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/ynrcc_netpay_business_service.kt
@@ -0,0 +1,387 @@
+package com.supwisdom.dlpay.api.service.impl
+
+import com.csii.ynrcc.open.api.service.User
+import com.csii.ynrcc.open.api.service.YNRCCOpenServiceApi
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.DtlStatus
+import com.supwisdom.dlpay.agent.citizencard.YnrccRespCode
+import com.supwisdom.dlpay.agent.service.YnrccNetPayService
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayResp
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayUtil
+import com.supwisdom.dlpay.api.bean.*
+import com.supwisdom.dlpay.api.dao.CardDao
+import com.supwisdom.dlpay.api.dao.PersonDao
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.api.service.TransactionService
+import com.supwisdom.dlpay.api.service.YnrccNetPayBusinessService
+import com.supwisdom.dlpay.api.types.IDTypes
+import com.supwisdom.dlpay.citizencard.dao.YnrccPaySignDao
+import com.supwisdom.dlpay.citizencard.dao.YnrccPayThirdappDao
+import com.supwisdom.dlpay.citizencard.domain.TYnrccPaySign
+import com.supwisdom.dlpay.exception.TransactionProcessException
+import com.supwisdom.dlpay.framework.dao.ShopaccDao
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.MoneyUtil
+import com.supwisdom.dlpay.framework.util.StringUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import com.supwisdom.dlpay.util.ConstantUtil
+import mu.KotlinLogging
+import org.springframework.stereotype.Service
+import java.util.ArrayList
+
+@Service
+class YnrccNetPayBusinessServiceImpl(val personDao: PersonDao,
+                                     val shopaccDao: ShopaccDao,
+                                     val ynrccPaySignDao: YnrccPaySignDao,
+                                     val cardDao: CardDao,
+                                     val ynrccPayThirdappDao: YnrccPayThirdappDao,
+                                     val transactionService: TransactionService,
+                                     val systemUtilService: SystemUtilService,
+                                     val sourceTypeService: SourceTypeService,
+                                     val ynrccNetPayService: YnrccNetPayService) : YnrccNetPayBusinessService {
+    private val logger = KotlinLogging.logger { }
+
+    override fun checkUserYnrccPaySignStatus(userid: String, bankcardno: String, shopaccno: String): Boolean {
+        logger.info("查询签约状态:userid=[$userid],bankcardno=[$bankcardno],shopaccno=[$shopaccno]")
+        val person = personDao.findByUserid(userid)
+                ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "用户<$userid>不存在")
+        val shopacc = shopaccDao.findByShopaccno(shopaccno)
+                ?: throw TransactionProcessException(TradeErrorCode.SHOP_NOT_EXISTS, "商户<$shopaccno>不存在")
+        if (sourceTypeService.checkShopSourceType(shopacc.shopaccno, TradeDict.PAYTYPE_YNRCC_PAY, false)) {
+            val paySign = ynrccPaySignDao.getUserSign(bankcardno, shopacc.shopaccno)
+            if (null != paySign) {
+                if (person.userid != paySign.userid) {
+                    throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "银行卡持有人错误!")
+                }
+
+                return paySign.isSignFlag
+            }
+        }
+        return false
+    }
+
+    override fun applyUserYnrccPaySign(param: YnrccPaySignApplyParam): YnrccPaySignApplyResponse {
+        logger.info("申请签约参数:" + YnrccPayUtil.toJson(param))
+        val resp = YnrccPaySignApplyResponse()
+        val person = personDao.findByUserid(param.userid?.trim())
+                ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "用户<${param.userid}>不存在")
+        val shopacc = shopaccDao.findByShopaccno(param.shopaccno?.trim())
+                ?: throw TransactionProcessException(TradeErrorCode.SHOP_NOT_EXISTS, "商户<${param.shopaccno}>不存在")
+        val bankCard = cardDao.findCardByCardnoAndCardtype(param.bankcardno.trim(), ConstantUtil.CARDTYPE_BANKCARD)
+        if (null != bankCard && person.userid != bankCard.userid) {
+            resp.retcode = 99
+            resp.retmsg = "银行卡持有人错误!"
+            return resp
+        }
+        val idType = IDTypes.findByValue(person.idtype)
+        if (idType < 0) {
+            resp.retcode = 99
+            resp.retmsg = "证件类型未识别[${person.idtype}]!"
+            return resp
+        }
+        sourceTypeService.checkShopSourceType(shopacc.shopaccno, TradeDict.PAYTYPE_YNRCC_PAY, false)
+
+        var userSign = ynrccPaySignDao.getUserSign(param.bankcardno, shopacc.shopaccno) ?: TYnrccPaySign().apply {
+            this.bankcardno = param.bankcardno.trim()
+            this.shopaccno = shopacc.shopaccno
+            this.userid = person.userid
+            this.status = TradeDict.STATUS_NORMAL
+            this.isSignFlag = false
+            this.createtime = systemUtilService.sysdatetime.hostdatetime
+        }
+        if (person.userid != userSign.userid) {
+            resp.retcode = 99
+            resp.retmsg = "银行卡持有人不匹配!"
+            return resp
+        } else if (userSign.isSignFlag) {
+            resp.retcode = 99
+            resp.retmsg = "该卡已签约!"
+            return resp
+        }
+
+        var isAuthSign = false
+        var signDataResp = YnrccPayResp()
+        val existSigns = ynrccPaySignDao.queryOtherShopSign(param.bankcardno, shopacc.shopaccno)
+        if (null != existSigns && existSigns.size > 0) {
+            //已签约过,则是授权签约
+            logger.info("进入授权签约申请!")
+            isAuthSign = true
+            val oldCustomerSignNo = existSigns[0].customerSignNo
+            signDataResp = ynrccNetPayService.doApplyAuthYnrccPaySign(shopacc.shopaccno, oldCustomerSignNo) //授权签约
+        } else {
+            //首次签约
+            signDataResp = ynrccNetPayService.doApplyYnrccPaySign(shopacc.shopaccno) //初次签约
+        }
+        if (YnrccPayUtil.SUCCESS != signDataResp.code) {
+            resp.retcode = 99
+            resp.retmsg = signDataResp.message
+            return resp
+        }
+
+        if (StringUtil.isEmpty(userSign.id)) {
+            ynrccPaySignDao.save(userSign) //新创建的保存申请记录
+        }
+
+        resp.retcode = 0
+        resp.retmsg = "success"
+        resp.signNo = userSign.id
+        resp.isAuthSign = isAuthSign
+        resp.plain = signDataResp.plain
+        resp.signature = signDataResp.signature
+        resp.signUserData = YnrccPaySignUserData().apply {
+            this.name = person.name
+            this.idType = idType.toString()
+            this.idNo = person.idno
+            this.acNo = userSign.bankcardno
+        }
+        logger.info("申请签约返回:" + YnrccPayUtil.toJson(resp))
+        return resp
+    }
+
+    override fun confirmUserYnrccPaySign(param: YnrccPaySignConfirmParam): YnrccPaySignConfirmResponse {
+        logger.info("确认签约参数:" + YnrccPayUtil.toJson(param))
+        val userSign = ynrccPaySignDao.getById(param.signNo.toString())
+                ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "签约申请记录<${param.signNo}>不存在!")
+
+        val data = ynrccNetPayService.doAnalysisSignature(userSign.shopaccno, param.plain, param.signature)
+        logger.info("签约确认:" + YnrccPayUtil.toJson(data))
+        val respCode = data["RespCode"]
+        if (YnrccPayUtil.SUCCESS != respCode) {
+            val errmsg = YnrccPayUtil.errcode.firstOrNull {
+                it.second.code == respCode
+            }?.second?.msg
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "$respCode $errmsg")
+        }
+
+        //签约成功
+//        if (data["CustomerAcNo"] != userSign.bankcardno) {
+//            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "支付账号与签约号不匹配!")  // CustomerAcNo 是脱敏返回的,不判断。 6210****6743
+//        }
+        if (userSign.isSignFlag && data["CustomerSignNo"] != userSign.customerSignNo) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "用户已签约且快捷支付协议号不一致!")
+        }
+
+        if (!userSign.isSignFlag) {
+            userSign.isSignFlag = true
+            userSign.customerSignNo = data["CustomerSignNo"]?.trim()
+            userSign.signTime = systemUtilService.sysdatetime.hostdatetime
+            ynrccPaySignDao.save(userSign)
+        }
+
+        return YnrccPaySignConfirmResponse().apply {
+            this.retcode = 0
+            this.retmsg = "success"
+            this.signNo = userSign.id
+            this.data = data
+        }
+    }
+
+    override fun cancelUserYnrccPaySign(param: YnrccPaySignCancelParam): YnrccPaySignCancelResponse {
+        logger.info("申请解约参数:" + YnrccPayUtil.toJson(param))
+        val userSign = ynrccPaySignDao.getUserSign(param.bankcardno.trim(), param.shopaccno)
+                ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "签约记录不存在或已解约!")
+        if (userSign.userid != param.userid) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "持卡人错误!")
+        } else if (!userSign.isSignFlag) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "该卡还未签约,不能解约!")
+        }
+
+        val resp = YnrccPaySignCancelResponse()
+        val cancelResp = ynrccNetPayService.doCancelYnrccPaySign(userSign.shopaccno, userSign.customerSignNo)
+        if (YnrccPayUtil.SUCCESS == cancelResp.code) {
+            //解约成功
+            userSign.status = TradeDict.STATUS_CLOSED
+            userSign.isSignFlag = false
+            userSign.cancelTime = systemUtilService.sysdatetime.hostdatetime
+            ynrccPaySignDao.save(userSign)
+
+            resp.retcode = 0
+            resp.retmsg = "success"
+            resp.signNo = userSign.id
+            return resp
+        }
+
+        resp.retcode = 99
+        resp.retmsg = cancelResp.message
+        return resp
+    }
+
+    override fun queryUserYnrccPaySign(bankcardno: String, shopaccno: String): TYnrccPaySign {
+        return ynrccPaySignDao.getUserSign(bankcardno.trim(), shopaccno.trim())
+                ?: throw RequestParamCheckException("银行卡签约记录不存在!")
+    }
+
+    override fun queryUserYnrccPaySignInfo(bankcardno: String, shopaccno: String): TYnrccPaySign? {
+        return ynrccPaySignDao.getUserSign(bankcardno.trim(), shopaccno.trim())
+    }
+
+    override fun doYnrccPayInit(transdtl: TTransactionMain, userSign: TYnrccPaySign): YnrccPayOrderResponse {
+        if (StringUtil.isEmpty(transdtl.refno) || null == transdtl.shopDtl || null == transdtl.shopDtl.amount) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "流水初始化错误!")
+        } else if (TradeDict.DTL_STATUS_SUCCESS == transdtl.status) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "非初始化交易流水!")
+        } else if (TradeDict.PAYTYPE_YNRCC_PAY != transdtl.sourceType || transdtl.shopDtl.shopaccno != userSign.shopaccno || transdtl.shopDtl.payInfo != userSign.customerSignNo) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易流水与签约信息不符!")
+        }
+
+        val refno = transdtl.refno
+        val shopaccno = transdtl.shopDtl.shopaccno
+        val amount = MoneyUtil.YuanToFen(transdtl.shopDtl.amount)
+        val hosttime = systemUtilService.sysdatetime.hosttime
+        val transDateTime = "${transdtl.shopDtl.accdate}$hosttime" //下单日期(记账日期,退款时用到)+下单时间
+        val billno = transdtl.outTradeNo //billno放附加信息
+        val productInfo = "农商行网关快捷支付[${transdtl.shopDtl.transdesc}]"; //商品描述
+        val person = personDao.findByUserid(userSign.userid)
+                ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "用户不存在!")
+        val orderResp = ynrccNetPayService.doYnrccPayInit(shopaccno, refno, amount, transDateTime,
+                productInfo, billno, person.name, person.email, userSign.customerSignNo)
+
+        if (YnrccPayUtil.SUCCESS != orderResp.code) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, orderResp.message)
+        }
+
+        val resp = YnrccPayOrderResponse()
+        resp.retcode = 0
+        resp.retmsg = "success"
+        resp.refno = refno
+        resp.billno = billno
+        resp.amount = transdtl.shopDtl.amount
+        resp.plain = orderResp.plain
+        resp.signature = orderResp.signature
+
+        logger.info("下单返回:" + YnrccPayUtil.toJson(resp))
+        return resp
+    }
+
+    override fun doYnrccPayConfirm(transaction: TTransactionMain, plain: String, signature: String): AgentResponse<DtlStatus> {
+        logger.info("支付确认参数: refno=[${transaction.refno}],plain=[$plain],signature=[$signature]")
+        if (TradeDict.DTL_STATUS_SUCCESS == transaction.status) {
+            throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水已入账!")
+        }
+
+        val data = ynrccNetPayService.doAnalysisSignature(transaction.shopDtl.shopaccno, plain, signature)
+        logger.info("支付确认:" + YnrccPayUtil.toJson(data))
+        val respCode = data["RespCode"]?.trim()
+        val orderNo = data["OrderNo"]?.trim()
+        val payAmt = data["Amount"]?.trim()
+        val tradeNo = data["TransSeqNo"]?.trim()
+        if (transaction.refno != orderNo) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "流水号错误,非此笔流水的确认信息!")
+        } else if (transaction.shopDtl.amount != payAmt?.toDouble()) {
+            throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "支付金额与流水交易金额不匹配!")
+        }
+
+        val agentCode = YnrccPayUtil.errcode.firstOrNull {
+            it.second.code == respCode
+        } ?: org.springframework.data.util.Pair.of(AgentCode.COMMON_ERROR,
+                YnrccRespCode(respCode, "未知错误[$respCode]"))
+
+        return AgentResponse<DtlStatus>().also {
+            it.code = agentCode.first
+            it.agentCode = agentCode.second.code
+            it.agentMsg = agentCode.first.message() + "-" + agentCode.second.msg
+            it.agentRefno = tradeNo
+            it.params = data
+        }
+    }
+
+    override fun doQueryYnrccPaySignList(userid: String?, bankcardno: String?): YnrccPaySignListQueryResponse {
+        val resp = YnrccPaySignListQueryResponse()
+        val signList = when (userid.isNullOrBlank()) {
+            true -> ynrccPaySignDao.queryActiveSignsByBankcardno(bankcardno?.trim())
+            false -> when (bankcardno.isNullOrBlank()) {
+                true -> ynrccPaySignDao.queryActiveSignsByUserid(userid?.trim())
+                false -> ynrccPaySignDao.queryActiveSignsByUseridAndBankcardno(userid?.trim(), bankcardno?.trim())
+            }
+        }
+        if (signList.isNullOrEmpty()) {
+            resp.retcode = 99
+            resp.retmsg = "无签约信息"
+            return resp
+        }
+
+        val data = ArrayList<YnrccPaySignInfo>()
+        for (sign in signList) {
+            data.add(YnrccPaySignInfo().apply {
+                this.signNo = sign.id
+                this.bankcardno = sign.bankcardno
+                this.shopaccno = sign.shopaccno
+                this.shopname = shopaccDao.getByShopaccno(sign.shopaccno)?.shopname ?: ""
+                this.signtime = sign.signTime
+                this.userid = sign.userid
+            })
+        }
+
+        resp.retcode = 0
+        resp.retmsg = "success"
+        resp.data = data
+        return resp
+    }
+
+    override fun doYnrccPayThirdAuth(thirdSrv: String, bankcardno: String, userid: String): YnrccPayThirdAuthResponse {
+        logger.info("中间缴费请求参数:thirdSrv=[$thirdSrv],bankcardno=[$bankcardno],userid=[$userid]")
+        val resp = YnrccPayThirdAuthResponse()
+        resp.retcode = 99
+
+        val thirdConfs = ynrccPayThirdappDao.queryYnrccPayThirdConfig()
+        if (null == thirdConfs || thirdConfs.isEmpty()) {
+            resp.retcode = 99
+            resp.retmsg = "中间缴费对接参数未配置!"
+            return resp
+        } else if (thirdConfs.size != 1) {
+            resp.retcode = 99
+            resp.retmsg = "中间缴费对接参数未指定!"
+            return resp
+        }
+
+        val config = thirdConfs[0]  //获取配置信息(第三方服务标识thirdSrv暂时无用)
+        var handler = YNRCCOpenServiceApi.getInstance(config.mchId, config.appId, config.token, config.pubkey)
+        //获取客户端sdk配置信息
+        val sdkConfigData = handler.getSDKConfigData()
+
+        //获取客户端SDK访问开放服务所需参数
+        val person = personDao.findByUserid(userid)
+            ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "用户不存在!")
+        if (person.mobile.isNullOrBlank()) {
+            resp.retcode = 99
+            resp.retmsg = "用户手机号为空!"
+            return resp
+        }
+        //fixme: 判断bankcard是否该userid所有
+        if (ynrccPaySignDao.countByBankcardno(bankcardno?.trim()) > 0) {
+            if (ynrccPaySignDao.countByBankcardnoAndUserid(bankcardno?.trim(), person.userid) < 1) {
+                resp.retcode = 99
+                resp.retmsg = "银行卡持有人错误!"
+                return resp
+            }
+        } else if (cardDao.countByBankCardNo(bankcardno?.trim()) > 0) {
+            if (cardDao.countByBankCardNoAndUserid(bankcardno?.trim(), person.userid) < 1) {
+                resp.retcode = 99
+                resp.retmsg = "银行卡持有人错误!"
+                return resp
+            }
+        }
+
+//        val user = User("测试", "420117198802234181", "13584821704", "623100095486551526")  //测试User
+        val user = User(person.name, person.idno, person.mobile, bankcardno)
+        val access2ServiceData = handler.getAccess2ServiceData(user)
+
+        resp.retcode = 0
+        resp.retmsg = "success"
+        resp.thirdService = thirdSrv
+        resp.user = YnrccPayThirdAuthUser().apply {
+            this.name = user.name
+            this.idNo = user.idNo
+            this.phone = user.phone
+            this.acNo = user.acNo
+        }
+        resp.sdkConfigData = sdkConfigData
+        resp.access2ServiceData = access2ServiceData
+        logger.info("中间缴费成功返回:" + YnrccPayUtil.toJson(resp))
+        return resp
+    }
+}
\ 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 d7ce27d..5c4e132 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,6 @@
 package com.supwisdom.dlpay.api.service
 
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayChkfile
 import com.supwisdom.dlpay.api.bean.YnrccChkfileBean
 import com.supwisdom.dlpay.api.domain.TSourceTypeCheckStatus
 import com.supwisdom.dlpay.api.domain.TTransactionChkdtl
@@ -65,6 +66,10 @@
     @Transactional(rollbackFor = [Exception::class])
     fun doConfirmChkfileStatus(chkfile: TTransactionChkfile, checkStatus: TSourceTypeCheckStatus): TSourceTypeCheckStatus
 
+    @Transactional(rollbackFor = [Exception::class])
+    fun doBatchSaveYnrccPayTransactionChkDtl(chkfile: TTransactionChkfile, list: ArrayList<YnrccPayChkfile>): Boolean
 
+    @Transactional(rollbackFor = [Exception::class])
+    fun saveYnrccPayTransactionChkDtl(chkfile: TTransactionChkfile, bean: YnrccPayChkfile, idx: Int): TTransactionChkdtl
 
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/ynrcc_netpay_business_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/ynrcc_netpay_business_service.kt
new file mode 100644
index 0000000..4884f07
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/ynrcc_netpay_business_service.kt
@@ -0,0 +1,40 @@
+package com.supwisdom.dlpay.api.service
+
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.DtlStatus
+import com.supwisdom.dlpay.api.bean.*
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.citizencard.domain.TYnrccPaySign
+import org.springframework.transaction.annotation.Transactional
+
+interface YnrccNetPayBusinessService {
+    @Transactional(rollbackFor = [Exception::class], readOnly = true)
+    fun checkUserYnrccPaySignStatus(userid: String, bankcardno: String, shopaccno: String): Boolean
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun applyUserYnrccPaySign(param: YnrccPaySignApplyParam): YnrccPaySignApplyResponse
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun confirmUserYnrccPaySign(param: YnrccPaySignConfirmParam): YnrccPaySignConfirmResponse
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun cancelUserYnrccPaySign(param: YnrccPaySignCancelParam): YnrccPaySignCancelResponse
+
+    @Transactional(rollbackFor = [Exception::class], readOnly = true)
+    fun queryUserYnrccPaySign(bankcardno: String, shopaccno: String): TYnrccPaySign
+
+    @Transactional(rollbackFor = [Exception::class], readOnly = true)
+    fun queryUserYnrccPaySignInfo(bankcardno: String, shopaccno: String): TYnrccPaySign?
+
+    @Transactional(rollbackFor = [Exception::class], readOnly = true)
+    fun doYnrccPayInit(transdtl: TTransactionMain, userSign: TYnrccPaySign): YnrccPayOrderResponse
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doYnrccPayConfirm(transaction: TTransactionMain, plain: String, signature: String): AgentResponse<DtlStatus>
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doQueryYnrccPaySignList(userid: String?, bankcardno: String?): YnrccPaySignListQueryResponse
+
+    @Transactional(rollbackFor = [Exception::class])
+    fun doYnrccPayThirdAuth(thirdSrv: String, bankcardno: String, userid: String): YnrccPayThirdAuthResponse
+}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/framework_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/framework_controller.kt
index a55845f..c5e603c 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/framework_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/framework_controller.kt
@@ -1,17 +1,24 @@
 package com.supwisdom.dlpay.framework.controller
 
+import com.google.gson.Gson
 import com.jcabi.manifests.Manifests
+import com.supwisdom.dlpay.agent.service.YnrccNetPayService
 import com.supwisdom.dlpay.api.bean.ApiVersionResponse
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
+import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.http.ResponseEntity
 import org.springframework.web.bind.annotation.GetMapping
 import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RequestParam
 import org.springframework.web.bind.annotation.RestController
 
 
 @RestController
 @RequestMapping("/api/common")
 class AboutController {
+    @Autowired
+    lateinit var ynrccNetPayService: YnrccNetPayService
+
     @GetMapping("/version")
     fun version(): ResponseEntity<Any> {
         return try {
@@ -24,4 +31,27 @@
                     .success(ApiVersionResponse("unknown")))
         }
     }
+
+    /**
+     * 查看农商行快捷支付对账单
+     * */
+    @GetMapping("/ynrccpaychkfile")
+    fun testYnrccpayChkfile(
+        @RequestParam("accdate") accdate: String,
+        @RequestParam("shopaccno") shopaccno: String
+    ): ResponseEntity<Any> {
+        return try {
+            val resp = ynrccNetPayService.doQueryYnrccPayChkfile(accdate, shopaccno)
+
+            ResponseEntity.ok(
+                ResponseBodyBuilder.create()
+                    .success(Gson().toJson(resp))
+            )
+        } catch (e: IllegalArgumentException) {
+            ResponseEntity.ok(
+                ResponseBodyBuilder.create()
+                    .fail(99, "throw exception!")
+            )
+        }
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/domain/TBMobileUser.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/domain/TBMobileUser.kt
index 339e607..0fc534c 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/domain/TBMobileUser.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/domain/TBMobileUser.kt
@@ -6,7 +6,6 @@
 import org.springframework.security.core.GrantedAuthority
 import org.springframework.security.core.userdetails.UserDetails
 import javax.persistence.*
-import javax.validation.constraints.NotNull
 
 @Entity
 @Table(name = "TB_MOBILE_USER",indexes = [Index(name = "mobile_user_loginid_idx", columnList = "loginid", unique = true)])
@@ -54,8 +53,7 @@
      * 登录id
      * */
 
-    @Column(name = "loginid", length = 64)
-    @NotNull
+    @Column(name = "loginid", nullable = false, length = 64)
     var loginid: String = ""
 
     /**
diff --git a/payapi/src/main/resources/payment_merchant.properties b/payapi/src/main/resources/payment_merchant.properties
new file mode 100644
index 0000000..871bd53
--- /dev/null
+++ b/payapi/src/main/resources/payment_merchant.properties
@@ -0,0 +1,14 @@
+development=no
+# \u8BC1\u4E66\u8DEF\u5F84,\u5FC5\u987B\u6307\u5B9A\u670D\u52A1\u5668\u7AEF\u8BC1\u4E66\u5BB9\u5668\u7EDD\u5BF9\u8DEF\u5F84
+#cafile=D:/ynrcc_test/merchant.jks
+cafile=config/merchant.jks
+# \u8BC1\u4E66\u5E93\u5BC6\u7801
+store_password=111111
+# \u7528\u4E8E\u5546\u6237\u7B7E\u540D\u7684\u79D8\u94A5\u522B\u540D
+#key_alias=merchant_key
+key_alias=ynrcc
+# \u79D8\u94A5\u5BC6\u7801
+#key_password=881220
+key_password=111111
+# \u9A8C\u7B7E\u79D8\u94A5\u522B\u540D
+alias_paygate=alias_paygate
\ No newline at end of file