农商行快捷支付接口定义
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..678c24e
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayConfirmParam.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.NotNull;
+
+@Getter
+@Setter
+public class YnrccPayConfirmParam extends APIRequestParam {
+  @Sign
+  @NotNull(message = "交易参考号不能为空")
+  private String refno;
+
+  @Sign
+  @NotNull(message = "参数Plain不能为空")
+  private String plain;   //农商行快捷支付参数
+
+  @Sign
+  @NotNull(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..6845d83
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayLimitModifyParam.java
@@ -0,0 +1,39 @@
+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.NotEmpty;
+
+@Getter
+@Setter
+public class YnrccPayLimitModifyParam extends APIRequestParam {
+  @Sign
+  @NotEmpty(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotEmpty(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotEmpty(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..6e66c41
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayOrderParam.java
@@ -0,0 +1,56 @@
+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.NotNull;
+import javax.validation.constraints.Positive;
+
+@Getter
+@Setter
+public class YnrccPayOrderParam extends APIRequestParam {
+  @Sign
+  @NotNull(message = "用户唯一号不能为空")
+  private String userid; //用户userid
+
+  @Sign
+  @NotNull(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotNull(message = "对接系统唯一订单号不能为空")
+  private String billno;
+
+  @Sign
+  @NotNull(message = "交易金额不能为空")
+  @Positive(message = "交易金额必须大于零")
+  private Integer amount;
+
+  @Sign
+  @NotNull(message = "请指定交易商户")
+  private String shopaccno;
+
+  @Sign
+  @NotNull(message = "交易日期不能为空")
+  private String transdate;
+  @Sign
+  @NotNull(message = "交易时间不能为空")
+  private String transtime;
+
+  @Sign
+  @NotNull(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..decc341
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPayRefundParam.java
@@ -0,0 +1,51 @@
+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.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
+  @NotNull(message = "撤销或退款流水号不能为空")
+  private String requestbillno;
+  @Sign
+  @NotNull(message = "交易日期不能为空")
+  private String transdate;
+  @Sign
+  @NotNull(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..581316b
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignApplyParam.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.NotEmpty;
+
+@Getter
+@Setter
+public class YnrccPaySignApplyParam extends APIRequestParam {
+  @Sign
+  @NotEmpty(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotEmpty(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotEmpty(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..17e3b57
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignCancelParam.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.NotEmpty;
+
+@Getter
+@Setter
+public class YnrccPaySignCancelParam extends APIRequestParam {
+  @Sign
+  @NotEmpty(message = "用户ID不能为空")
+  private String userid;
+
+  @Sign
+  @NotEmpty(message = "银行卡号不能为空")
+  private String bankcardno;
+
+  @Sign
+  @NotEmpty(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..136bc58
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/YnrccPaySignConfirmParam.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.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class YnrccPaySignConfirmParam extends APIRequestParam {
+  @Sign
+  @NotEmpty(message = "签约号不能为空")
+  private String signNo; //申请时返回的签约号
+
+  @Sign
+  @NotNull(message = "参数Plain不能为空")
+  private String plain;   //农商行快捷支付参数
+
+  @Sign
+  @NotNull(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/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-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..18f1521 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,14 @@
 
     @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);
+
 }
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..e1a5991 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,16 @@
 
   @PostMapping("/api/user/queryCitizenCard")
   DoorQrcodeResponse queryCitizenCard(@RequestParam("uid") String uid);
+
+  @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);
 }
diff --git a/payapi/build.gradle b/payapi/build.gradle
index d144174..c6d7dd4 100644
--- a/payapi/build.gradle
+++ b/payapi/build.gradle
@@ -115,6 +115,7 @@
 //    implementation files('libs/ojdbc6.jar')
     implementation 'commons-dbcp:commons-dbcp:1.4'
     implementation 'commons-beanutils:commons-beanutils:1.9.3'
+    implementation files('libs/ynrcc-mbp-1.0-RELEASE.jar')
 
     implementation 'log4j:log4j:1.2.17'
     implementation 'com.alibaba:fastjson:1.2.60'
diff --git a/payapi/libs/ynrcc-mbp-1.0-RELEASE.jar b/payapi/libs/ynrcc-mbp-1.0-RELEASE.jar
new file mode 100644
index 0000000..0a481dd
--- /dev/null
+++ b/payapi/libs/ynrcc-mbp-1.0-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..acf987c
--- /dev/null
+++ b/payapi/sql/update-210106.sql
@@ -0,0 +1,10 @@
+-- 农商行网关支付
+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;
+
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/YnrccPayUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayUtil.java
new file mode 100644
index 0000000..17959f3
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/ynrccpay/YnrccPayUtil.java
@@ -0,0 +1,40 @@
+package com.supwisdom.dlpay.agent.ynrccpay;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class YnrccPayUtil {
+
+  public static final Map<String, String> transName;
+
+  static {
+    transName = new HashMap<String, String>(0);
+    transName.put("IQSR","QueryMerchantEpay.do");  //单笔查询交易IQSR
+    transName.put("IPSR","MerchantWithdraw.do");  //单笔退货交易IPSR
+    transName.put("IDFR","MerchantCheckFileQry.do");  //清算对账IDFR
+    //网关支付IFPR有三种可供选择
+    transName.put("IFPR","PayGateFastPay4M.do"); //网关快捷支付IFPR
+    transName.put("IFPR_PC","PayGateFastPay.do"); //fixme:普通网关支付IFPR
+    transName.put("IFPR_H5","PayGateFastPay4MNoCtrl.do"); //fixme:手机端普通网关支付IFPR
+
+    transName.put("IFCR","PayGateFastPayCancelSign.do"); //网关快捷支付解约IFCR
+
+    //网关支付限额修改IFMR有两种可供选择
+    transName.put("IFMR","PayGateFastPayModify4M.do"); //网关快捷支付限额修改IFMR
+    transName.put("IFMR_PC","PayGateFastPayModify.do"); //fixme:普通网关支付限额修改IFMR
+  }
+
+
+  /**
+   * 接口名称
+   * */
+  public static final String TRANSNAME_IQSR="QueryMerchantEpay.do";
+
+
+  /**
+   * 交易码
+   * */
+  public static final String IQSR="IQSR";
+
+}
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..2d94e30
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/ynrcc_netpay_service_impl.kt
@@ -0,0 +1,62 @@
+package com.supwisdom.dlpay.agent.service.impl
+
+import com.supwisdom.dlpay.agent.service.YnrccNetPayService
+import com.supwisdom.dlpay.agent.ynrccpay.YnrccPayUtil
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import org.springframework.http.HttpEntity
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+import org.springframework.http.ResponseEntity
+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.nio.charset.StandardCharsets
+
+@Service
+class YnrccNetPayServiceImpl(val restTemplate: RestTemplate,
+                             val systemUtilService: SystemUtilService,
+                             val sourceTypeService: SourceTypeService): YnrccNetPayService {
+
+    private fun postForm(url: String, params: Map<String, String>): ResponseEntity<String> {
+        val httpHeaders = HttpHeaders()
+        httpHeaders.contentType = MediaType.APPLICATION_FORM_URLENCODED //Form表单提交
+
+        val requestParams = LinkedMultiValueMap<String, String>()
+        params.forEach(requestParams::add)
+        val httpEntity = HttpEntity<MultiValueMap<String, String>>(requestParams, httpHeaders)
+
+        restTemplate.messageConverters[1] = StringHttpMessageConverter(StandardCharsets.UTF_8) //UTF-8接收
+        return restTemplate.postForEntity(url, httpEntity, String::class.java)
+    }
+
+    override fun doYnrccPaySign() {
+        val params = hashMapOf<String, String>()
+//        params["stuempno"]="111"
+//        params["partner_id"]="100006"
+//        params["timestamp"]=systemUtilService.sysdatetime.hostdatetime
+//        params["sign_method"]="HMAC"
+//        params["sign"]="X"
+//        val url = "http://localhost:8581/epayapi/services/servicehall//common/queryaccountinfo"
+
+        val url ="http://220.163.130.136:8087/pweb/PayGateFastPaySign4MNoCtrl.do?LoginType=C&BankId=9999&_locale=zh_CN"
+        val plain = "TransId=IFSR~~Mer_Id=700003~~MerURL=http://ykt.supwisdom.com"
+//        val sign = YnrccPayUtil.sign(plain);
+        val sign = "123"
+
+        params["TransName"]="IFSR"
+        params["Plain"]=plain
+        params["Signature"]=sign
+
+        var resp = postForm(url,params)
+        if(200 == resp.statusCodeValue){
+            //success
+            println("return json=${resp.body}")
+        } else {
+            //fail
+            println("return status=${resp.statusCodeValue},json=${resp.body}")
+        }
+    }
+}
\ 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..e6ab5fb
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/ynrcc_netpay_service.kt
@@ -0,0 +1,5 @@
+package com.supwisdom.dlpay.agent.service
+
+interface YnrccNetPayService {
+    fun doYnrccPaySign()
+}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
index 692be0c..d539a41 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
@@ -838,5 +838,57 @@
         })
     }
 
+    /**
+     * ============================================================================
+     *                           农商行网关快捷支付【初始化下单】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpay/order")
+    fun ynrccPayOrder(@Valid @RequestBody param: YnrccPayOrderParam): ResponseEntity<Any>{
+        val success=true
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPayOrderResponse(), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>"))
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行网关快捷支付【下单支付确认】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpay/confirm")
+    fun ynrccPayConfirm(@Valid @RequestBody param: YnrccPayConfirmParam): ResponseEntity<Any> {
+        val success=true
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPayConfirmResponse(), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>"))
+
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行网关快捷支付【退款】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpay/refund")
+    fun ynrccPayRefund(@Valid @RequestBody param:YnrccPayRefundParam): ResponseEntity<Any>{
+        val success=true
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPayRefundResponse(), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>"))
+
+    }
 
 }
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..90cbd5c 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
@@ -20,6 +20,7 @@
 import org.springframework.http.ResponseEntity
 import org.springframework.web.bind.annotation.*
 import java.net.URLDecoder
+import javax.validation.Valid
 
 @RestController
 @RequestMapping("/api/user")
@@ -446,4 +447,76 @@
                     .fail(ret.retcode, ret.retmsg))
         }
     }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【签约申请】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignApply")
+    fun applyYnrccPaySign(@Valid @RequestBody param: YnrccPaySignApplyParam): ResponseEntity<Any> {
+        val success=true
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPaySignApplyResponse(), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>"))
+
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【签约确认】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignConfirm")
+    fun confirmYnrccPaySign(@Valid @RequestBody param:YnrccPaySignConfirmParam): ResponseEntity<Any>{
+        val success=true
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPaySignConfirmResponse(), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>"))
+
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【解约】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpaySignCancel")
+    fun cancelYnrccPaySign(@Valid @RequestBody param:YnrccPaySignCancelParam):ResponseEntity<Any>{
+        val success=true
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPaySignCancelResponse(), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>"))
+
+    }
+
+    /**
+     * ============================================================================
+     *                           农商行快捷支付【修改限额】
+     * ============================================================================
+     * */
+    @PostMapping("/ynrccpayModifyLimit")
+    fun modifyYnrccPayLimit(@Valid @RequestBody param:YnrccPayLimitModifyParam):ResponseEntity<Any>{
+        val success=true
+        if(success){
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(YnrccPayLimitModifyResponse(), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>"))
+
+    }
 }
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..b80d573 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,8 +1,11 @@
 package com.supwisdom.dlpay.framework.controller
 
 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 com.supwisdom.dlpay.framework.redisrepo.ApiClientRepository
+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
@@ -12,9 +15,13 @@
 @RestController
 @RequestMapping("/api/common")
 class AboutController {
+    @Autowired
+    lateinit var ynrccNetPayService: YnrccNetPayService
+
     @GetMapping("/version")
     fun version(): ResponseEntity<Any> {
         return try {
+            ynrccNetPayService.doYnrccPaySign()
             Manifests.read("Payapi-Version").let {
                 ResponseEntity.ok(ResponseBodyBuilder.create()
                         .success(ApiVersionResponse(it)))
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..b2f94dc
--- /dev/null
+++ b/payapi/src/main/resources/payment_merchant.properties
@@ -0,0 +1,11 @@
+development=no
+# \u8BC1\u4E66\u8DEF\u5F84,\u5FC5\u987B\u6307\u5B9A\u670D\u52A1\u5668\u7AEF\u8BC1\u4E66\u5BB9\u5668\u7EDD\u5BF9\u8DEF\u5F84
+cafile=D:/ynrccpay/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
+# \u79D8\u94A5\u5BC6\u7801
+key_password=111111
+# \u9A8C\u7B7E\u79D8\u94A5\u522B\u540D
+alias_paygate=alias_paygate
\ No newline at end of file