YnrccAgent
diff --git a/config/application-devel-agent.properties b/config/application-devel-agent.properties
new file mode 100644
index 0000000..8b266dd
--- /dev/null
+++ b/config/application-devel-agent.properties
@@ -0,0 +1,6 @@
+############# YNRCC SOCKET ###############
+ynrcc.socket.ip=127.0.0.1
+ynrcc.socket.port=8089
+## 超时时间(分钟)
+ynrcc.socket.timeout = 10
+ynrcc.md5.key=80816b7947ed016bff8079557735006e
\ No newline at end of file
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java
new file mode 100644
index 0000000..1d2895b
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/YnrccUtil.java
@@ -0,0 +1,46 @@
+package com.supwisdom.dlpay.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class YnrccUtil {
+  private static final String BANKCARD_BIND_TRANSCODE = "BC5510";
+  private static final String BANKCARD_SIGN_TRANSCODE = "BC5511";
+  private static final String BANKCARD_PAY_TRANSCODE = "BC5512";
+  private static final String BANKCARD_PAYREFUND_TRANSCODE = "BC5513";
+  private static final String BANKCARD_QUERYRESULT_TRANSCODE = "BC5514";
+  private static final String BANKCARD_CHKFILE_TRANSCODE = "BC5515";
+
+  public static final String DLPAY_CATEGORIE = "C001"; //消费类别
+
+  public static final String DLPAY_SIGNTYPE_BUSSINESSKEY = "ynrcc.agent.signtype"; //农商行前置signtype
+  public static final String DLPAY_SIGNKEY_BUSSINESSKEY = "ynrcc.agent.signkey"; //农商行前置md5key
+
+  public static final Map<String, String> errcode = new HashMap<>(0);
+  static {
+    errcode.put("0000", "成功");
+    errcode.put("0101", "手机号不一致");
+    errcode.put("0102", "无预留手机号");
+    errcode.put("0103", "证件类型不一致");
+    errcode.put("0104", "证件号码不一致");
+    errcode.put("0105", "户名不符");
+    errcode.put("0106", "卡状态异常");
+    errcode.put("0107", "无此卡号");
+    errcode.put("0201", "未进行银行卡绑定");
+    errcode.put("0202", "无效的交易类型");
+    errcode.put("0301", "未签约");
+    errcode.put("0302", "余额不足");
+    errcode.put("0303", "MD5校验失败");
+    errcode.put("0401", "原始流水不存在");
+    errcode.put("0402", "原始流水未成功");
+    errcode.put("0403", "原始流水已退款");
+    errcode.put("4004", "商户账户余额不足");
+    errcode.put("0405", "不在退款时间范围内");
+    errcode.put("0406", "当日无交易明细");
+  }
+
+
+
+
+}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt
index dd978bb..2397e3b 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt
@@ -6,10 +6,8 @@
 import com.supwisdom.dlpay.api.bean.*
 import com.supwisdom.dlpay.api.domain.TPersondtl
 import com.supwisdom.dlpay.api.domain.TShopdtl
-import com.supwisdom.dlpay.api.util.IDTypes
 import com.supwisdom.dlpay.framework.util.*
 import com.supwisdom.dlpay.util.Code
-import com.supwisdom.dlpay.util.DlpayUtil
 import mu.KotlinLogging
 
 class CallBackResp {
@@ -237,7 +235,7 @@
             }
         }
 
-
+        /*
         /**
          * 大理农商行银行卡绑定
          * */
@@ -615,6 +613,8 @@
             }
         }
 
+        */
+
         fun CallCitizenCardPay(config: Map<String, String?>, paydtl: TShopdtl): CallBackResp {
             val resp = CallBackResp()
             resp.retcode = "0"
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 5b5c19c..5f08635 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
@@ -73,7 +73,7 @@
 
             return when(StringUtil.isEmpty(errlist)){
                 true -> ResponseEntity.ok(mapOf("retcode" to "0000", "retmsg" to "SUCCESS", "resultcode" to "0000", "resultmsg" to ""))
-                false -> ResponseEntity.ok(mapOf("retcode" to "0000", "retmsg" to "请求成功接收", "resultcode" to "0000", "resultmsg" to "明细数据处理有错", "data" to Gson().toJson(errlist)))
+                false -> ResponseEntity.ok(mapOf("retcode" to "0000", "retmsg" to "请求成功接收", "resultcode" to "4000", "resultmsg" to "明细数据处理有错", "data" to Gson().toJson(errlist)))
             }
         } catch (ex: RequestParamCheckException) {
             return ResponseEntity.ok(ResponseBodyBuilder.create()
diff --git a/settings.gradle b/settings.gradle
index 00adefd..42be481 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,2 @@
 rootProject.name = 'payapi'
-include 'payapi', 'payapi-sdk', 'payapi-common'
+include 'payapi', 'payapi-sdk', 'payapi-common', 'ynrcc-agent'
diff --git a/ynrcc-agent/build.gradle b/ynrcc-agent/build.gradle
new file mode 100644
index 0000000..4431bd6
--- /dev/null
+++ b/ynrcc-agent/build.gradle
@@ -0,0 +1,73 @@
+plugins {
+    id 'java'
+    id 'org.springframework.boot' version '2.1.6.RELEASE'
+    id 'org.jetbrains.kotlin.jvm' version '1.3.31'
+    id 'org.jetbrains.kotlin.plugin.spring' version '1.3.31'
+    id "com.palantir.git-version" version "0.12.0-rc2"
+    id 'com.palantir.docker' version '0.22.1'
+}
+
+apply plugin: 'java'
+apply plugin: 'io.spring.dependency-management'
+
+payapiVersion = gitVersion()
+
+group = rootProject.group
+version = '1'
+sourceCompatibility = jdkVersion
+def startClass = 'com.supwisdom.agent.YnrccAgentApplication'
+
+println("Build version: $payapiVersion")
+
+bootJar {
+    mainClassName = startClass
+    manifest {
+        attributes('YnrccAgent-Version': payapiVersion)
+    }
+}
+
+jar {
+    baseName = 'YnrccAgent'
+}
+
+docker {
+    name 'harbor.supwisdom.com/dali/ynrcc:' + version
+    println(jar.archivePath)
+    files jar.archivePath
+}
+
+docker.dependsOn(jar)
+
+dependencies {
+
+    implementation 'org.springframework.boot:spring-boot-starter-web'
+    implementation 'org.springframework.boot:spring-boot-autoconfigure'
+    implementation 'commons-codec:commons-codec:1.12'
+    implementation 'com.jcabi:jcabi-manifests:1.1'
+    implementation 'org.slf4j:slf4j-parent:1.7.26'
+    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
+    implementation group: 'com.sun.jersey', name: 'jersey-client', version: '1.19'
+    implementation group: 'javax.servlet', name: 'jstl', version: '1.2'
+    implementation group: 'taglibs', name: 'standard', version: '1.1.2'
+    implementation group: 'commons-codec', name: 'commons-codec', version: '1.6'
+    implementation 'org.dom4j:dom4j:2.1.1'
+
+    testImplementation 'org.springframework.boot:spring-boot-starter-test'
+    testImplementation 'io.rest-assured:rest-assured:3.3.0'
+    testImplementation 'io.rest-assured:spring-mock-mvc:3.3.0'
+    testImplementation 'org.hamcrest:hamcrest:2.1'
+}
+
+compileKotlin {
+    kotlinOptions {
+        freeCompilerArgs = ['-Xjsr305=strict']
+        jvmTarget = jdkVersion
+    }
+}
+
+compileTestKotlin {
+    kotlinOptions {
+        freeCompilerArgs = ['-Xjsr305=strict']
+        jvmTarget = jdkVersion
+    }
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/BussinessException.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/BussinessException.java
new file mode 100644
index 0000000..cad7023
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/BussinessException.java
@@ -0,0 +1,7 @@
+package com.supwisdom.agent.Util;
+
+public class BussinessException extends Exception {
+  public BussinessException(String message) {
+    super(message);
+  }
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/DateUtil.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/DateUtil.java
new file mode 100644
index 0000000..b9f451f
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/DateUtil.java
@@ -0,0 +1,361 @@
+package com.supwisdom.agent.Util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class DateUtil {
+  private static final Logger logger = LoggerFactory.getLogger(DateUtil.class);
+  public static final String DATE_FMT = "yyyyMMdd";
+  public static final String TIME_FMT = "HHmmss";
+  public static final String DATETIME_FMT = "yyyyMMddHHmmss";
+
+  /**
+   * Description: 返回一个当前时间 @return String 格式:yyyyMMddHHmmss @exception Modify
+   * History:
+   */
+  public static String getNow() {
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+    return sdf.format(new Date());
+  }
+
+
+  /**
+   * Description: 根据类型返回一个当前时间 @param partten String @return String 格式:partten
+   */
+  public static String getNow(String partten) {
+    SimpleDateFormat sdf = new SimpleDateFormat(partten);
+    return sdf.format(new Date());
+  }
+  /*
+  *
+  * */
+  public static String getNowInterDay(int intervalday) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+      Date d = new Date();
+      Calendar calendar = Calendar.getInstance();
+      calendar.setTimeInMillis(d.getTime());
+      calendar.add(Calendar.DATE, intervalday);
+      return sdf.format(calendar.getTime());
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  /**
+   * Description: 得到一个特殊的时间 @param startTime String 格式:yyyyMMddHHmmss @param
+   * interval int 秒 @return String 格式:partten @exception Modify History:
+   */
+  public static String getNewTime(String startTime, int interval) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+      Date d = sdf.parse(startTime);
+      Calendar calendar = Calendar.getInstance();
+      calendar.setTimeInMillis(d.getTime());
+      calendar.add(Calendar.SECOND, interval);
+      return sdf.format(calendar.getTime());
+    } catch (ParseException e) {
+      return startTime;
+    }
+  }
+
+  /**
+   * Description: 得到一个特殊的时间 @param startTime String 格式:partten @param
+   * interval int 秒 @return String 格式:partten @exception Modify History:
+   */
+  public static String getNewTime(String startTime, int interval, String partten) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat(partten);
+      Date d = sdf.parse(startTime);
+      Calendar calendar = Calendar.getInstance();
+      calendar.setTimeInMillis(d.getTime());
+      calendar.add(Calendar.SECOND, interval);
+      return sdf.format(calendar.getTime());
+    } catch (ParseException e) {
+      return startTime;
+    }
+  }
+
+  public static String getNewDay(String startDay, int intervalday) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+      Date d = sdf.parse(startDay);
+      Calendar calendar = Calendar.getInstance();
+      calendar.setTimeInMillis(d.getTime());
+      calendar.add(Calendar.DATE, intervalday);
+      return sdf.format(calendar.getTime());
+    } catch (ParseException e) {
+      return startDay;
+    }
+  }
+
+  /**
+   * 得到两个日期相差的天数 格式 yyyyMMdd @return diffdays = secondDay - firstDay
+   */
+  public static long getIntervalDay(String firstDay, String secondDay) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+      Date f = sdf.parse(firstDay);
+      Date s = sdf.parse(secondDay);
+      long time = s.getTime() - f.getTime();
+      return time / (24 * 60 * 60 * 1000);
+    } catch (ParseException e) {
+      return 0;
+    }
+  }
+
+  /**
+   * Description: 比较两个时间字符串的前后关系 @param firstTime String 格式:yyyyMMddHHmmss
+   *
+   * @param secondTime String 格式: yyyyMMddHHmmss @return int |
+   *                   firstTime=second int=0 | firstTime>secondTime int>0 |
+   *                   firstTime<secondTime int<0 @exception Modify History:
+   */
+  public static int compareDatetime(String firstTime, String secondTime) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+      Date f = sdf.parse(firstTime);
+      Date s = sdf.parse(secondTime);
+      return f.compareTo(s);
+    } catch (ParseException e) {
+      return 0;
+    }
+  }
+
+  /**
+   * Description: 比较两个时间字符串的前后关系 @param firstTime String 格式:pattern
+   *
+   * @param secondTime String 格式: yyyyMMddHHmmss @return int |
+   *                   firstTime=second int=0 | firstTime>secondTime int>0 |
+   *                   firstTime<secondTime int<0 @exception Modify History:
+   */
+  public static int compareDatetime(String firstTime, String secondTime, String pattern) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+      Date f = sdf.parse(firstTime);
+      Date s = sdf.parse(secondTime);
+      return f.compareTo(s);
+    } catch (ParseException e) {
+      return 0;
+    }
+  }
+
+  /**
+   * Description: 比较两个时间字符串的时间差 @param firstTime String 格式:yyyyMMddHHmmss
+   *
+   * @param secondTime String 格式: yyyyMMddHHmmss @param second int 格式 @return
+   *                   int | firstTime+seconds=secondTime int=0 | firstTime+seconds>secondTime
+   *                   int>0 | firstTime+seconds<secondTime int<0 @exception Modify History:
+   */
+  public static int compareDatetime(String firstTime, String secondTime, int seconds) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+      Date f = sdf.parse(firstTime);
+      Date s = sdf.parse(secondTime);
+      Calendar calendar = Calendar.getInstance();
+      calendar.setTimeInMillis(f.getTime());
+      calendar.add(Calendar.SECOND, seconds);
+      Date temp = calendar.getTime();
+      return temp.compareTo(s);
+    } catch (Exception e) {
+      return 0;
+    }
+  }
+
+  /**
+   * Description: 对time重新格式化
+   */
+  public static String reformatDatetime(String time, String fromPattern, String toPattern) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat(fromPattern);
+      Date d = sdf.parse(time);
+      Calendar calendar = Calendar.getInstance();
+      calendar.setTimeInMillis(d.getTime());
+      sdf = new SimpleDateFormat(toPattern);
+      return sdf.format(calendar.getTime());
+    } catch (Exception e) {
+      e.printStackTrace();
+      return time;
+    }
+  }
+
+  /**
+   * 获得两个字符串日期之间的时间差(单位毫秒) 格式 yyyyMMddHHmmss
+   */
+  public static long getInterval(String startTime, String endTime) {
+    long duration = 0;
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+      duration = sdf.parse(endTime).getTime() - sdf.parse(startTime).getTime();
+    } catch (ParseException e) {
+      logger.error("Hi guys,there is an error when you try to parse the date string");
+    }
+    return duration;
+  }
+
+  /**
+   * 获得两个字符串日期之间的时间差(单位毫秒)
+   */
+  public static long getIntervalTime(String startTime, String endTime, String pattern) {
+    long duration = 0;
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+      duration = sdf.parse(endTime).getTime() - sdf.parse(startTime).getTime();
+    } catch (ParseException e) {
+      logger.error("Hi guys,there is an error when you try to parse the date string");
+    }
+    return duration;
+  }
+
+  /**
+   * 转换成日期格式
+   * 短格式:20140401 -> 2014-04-01
+   * 中格式:201404011200 -> 2014-04-01 12:00
+   * 长格式:20140401123025 -> 2014-04-01 12:30:25
+   **/
+  public static String parseToDateFormat(String str) {
+    switch (str.length()) {
+      case 8:
+        str = str.substring(0, 4) + "-" + str.substring(4, 6) + "-" + str.substring(6, 8);
+        break;
+      case 12:
+        str = str.substring(0, 4) + "-" + str.substring(4, 6) + "-" + str.substring(6, 8) + " " + str.substring(8, 10) + ":" + str.substring(10, 12);
+        break;
+      case 14:
+        str = str.substring(0, 4) + "-" + str.substring(4, 6) + "-" + str.substring(6, 8) + " " + str.substring(8, 10) + ":" + str.substring(10, 12) + ":" + str.substring(12, 14);
+        break;
+      default:
+        break;
+    }
+    return str;
+  }
+
+  /**
+   * 解日期格式
+   * 短格式:2014-04-01 -> 20140401
+   * 中格式:2014-04-01 12:00 -> 201404011200
+   * 长格式:2014-04-01 12:30:25 -> 20140401123025
+   **/
+  public static String unParseToDateFormat(String str) {
+    return str.replaceAll("-", "").replaceAll(" ", "").replaceAll(":", "");
+  }
+
+  /**
+   * 检验时间格式
+   */
+  public static boolean checkDatetimeValid(String datetime, String pattern) {
+    if (null == datetime) return false;
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+      Date d = sdf.parse(datetime);
+      return datetime.trim().equals(sdf.format(d));
+    } catch (Exception e) {
+    }
+    return false;
+  }
+
+  /**
+   * 获取指定日期是星期几 格式 yyyyMMdd
+   * MON|TUE|WED|THU|FRI|SAT|SUN
+   * 1		2		3		4		5		6		7
+   */
+  public static int getWeekday(String datestr) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+      Calendar calendar = Calendar.getInstance();
+      boolean isFirstSunday = (calendar.getFirstDayOfWeek() == Calendar.SUNDAY); //一周第一天是否为星期天
+      Date d = sdf.parse(datestr);
+      calendar.setTimeInMillis(d.getTime());
+      int weekDay = calendar.get(calendar.DAY_OF_WEEK);
+      if (isFirstSunday) {
+        weekDay = weekDay - 1;
+        if (weekDay == 0) {
+          weekDay = 7;
+        }
+      }
+      return weekDay;
+    } catch (Exception e) {
+      return -1;
+    }
+  }
+
+  /**
+   * 获取指定日期
+   */
+  public static Date getSpecifyDate(String datestr, String pattern) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+      Date result = sdf.parse(datestr);
+      return result;
+    } catch (Exception e) {
+      return new Date();
+    }
+  }
+
+  public static Integer getLastDayOfMonth(Integer year, Integer month) {
+    Calendar cal = Calendar.getInstance();
+    cal.set(Calendar.YEAR, year);
+    cal.set(Calendar.MONTH, month - 1);
+    cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
+    String str = new SimpleDateFormat("yyyyMMdd ").format(cal.getTime()).toString();
+    Integer result = Integer.parseInt(str.substring(0, 4) + str.substring(4, 6) + str.substring(6, 8));
+    return result;
+  }
+
+  private static Date set(Date date, int calendarField, int amount) {
+    Calendar c = Calendar.getInstance();
+    c.setLenient(false);
+    c.setTime(date);
+    c.add(calendarField, amount);
+    return c.getTime();
+  }
+
+
+  public static Date setMinutes(Date date, int amount) {
+    return set(date, Calendar.MINUTE, amount);
+  }
+
+
+  public static long getNowSecond() {
+    Calendar calendar = Calendar.getInstance();
+    return calendar.getTimeInMillis() / 1000;
+  }
+
+
+  public static String getUTCTime(Long timeInMillisSecond) {
+    Calendar time = Calendar.getInstance();
+    SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
+    fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
+    time.setTimeInMillis(timeInMillisSecond);
+    return fmt.format(time.getTime());
+  }
+
+  public static String getUTCTime() {
+    return getUTCTime(System.currentTimeMillis());
+  }
+
+  public static int compareDay(Timestamp d1, Timestamp d2) {
+    Calendar cd1 = Calendar.getInstance();
+    cd1.setTimeInMillis(d1.getTime());
+    Calendar cd2 = Calendar.getInstance();
+    cd2.setTimeInMillis(d2.getTime());
+
+    if (cd1.get(Calendar.YEAR) != cd2.get(Calendar.YEAR)) {
+      return cd1.compareTo(cd2);
+    }
+
+    return Integer.compare(cd1.get(Calendar.DAY_OF_YEAR), cd2.get(Calendar.DAY_OF_YEAR));
+  }
+
+  public static Boolean sameDay(Timestamp d1, Timestamp d2) {
+    return (compareDay(d1, d2) == 0);
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/DlpayUtil.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/DlpayUtil.java
similarity index 71%
rename from payapi/src/main/java/com/supwisdom/dlpay/util/DlpayUtil.java
rename to ynrcc-agent/src/main/java/com/supwisdom/agent/Util/DlpayUtil.java
index 7f8bf3f..4dbd2bb 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/DlpayUtil.java
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/DlpayUtil.java
@@ -1,4 +1,4 @@
-package com.supwisdom.dlpay.util;
+package com.supwisdom.agent.Util;
 
 import org.dom4j.Document;
 import org.dom4j.Element;
@@ -13,29 +13,12 @@
 import java.util.Random;
 
 public class DlpayUtil {
-  public static final Map<String, String> errcode = new HashMap<>(0);
-
-  static {
-    errcode.put("0000", "成功");
-    errcode.put("0101", "手机号不一致");
-    errcode.put("0102", "无预留手机号");
-    errcode.put("0103", "证件类型不一致");
-    errcode.put("0104", "证件号码不一致");
-    errcode.put("0105", "户名不符");
-    errcode.put("0106", "卡状态异常");
-    errcode.put("0107", "无此卡号");
-    errcode.put("0201", "未进行银行卡绑定");
-    errcode.put("0202", "无效的交易类型");
-    errcode.put("0301", "未签约");
-    errcode.put("0302", "余额不足");
-    errcode.put("0303", "MD5校验失败");
-    errcode.put("0401", "原始流水不存在");
-    errcode.put("0402", "原始流水未成功");
-    errcode.put("0403", "原始流水已退款");
-    errcode.put("4004", "商户账户余额不足");
-    errcode.put("0405", "不在退款时间范围内");
-    errcode.put("0406", "当日无交易明细");
-  }
+  public static final String OPTYPE_BINDCARD = "bindcard"; //绑定银行卡
+  public static final String OPTYPE_SIGNCARD = "signcard"; //签(解)约银行卡
+  public static final String OPTYPE_CARDPAY = "cardpay"; //代扣消费
+  public static final String OPTYPE_PAYREFUND = "payrefund"; //消费退款
+  public static final String OPTYPE_QUERYRESULT = "queryresult"; //消费结果查询
+  public static final String OPTYPE_CHKDTL = "chkdtl"; //流水对账
 
   /**
    * socket方式请求农商行
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/ErrorCode.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/ErrorCode.java
new file mode 100644
index 0000000..ecc83dc
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/ErrorCode.java
@@ -0,0 +1,10 @@
+package com.supwisdom.agent.Util;
+
+public class ErrorCode {
+  public static final String SYSTEM_ERROR = "10000";
+
+  public static final String REQ_PARAM_ERROR = "20000";
+  public static final String REQ_SIGN_ERROR = "21000";
+
+  public static final String BUSSINESS_ERROR = "30000";
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/MD5.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/MD5.java
new file mode 100644
index 0000000..aeea2f6
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/MD5.java
@@ -0,0 +1,96 @@
+package com.supwisdom.agent.Util;
+
+import java.security.MessageDigest;
+
+public class MD5 {
+  //十六进制下数字到字符的映射数组
+  private final static String[] hexDigits = {"0", "1", "2", "3", "4",
+      "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
+
+  /**
+   * 把inputString加密
+   */
+  public static String generatePassword(String data, String salt) {
+    String enyptString = data + "{" + salt + "}";
+    return encodeByMD5(enyptString);
+  }
+
+  /**
+   * 验证输入的密码是否正确
+   *
+   * @param password    加密后的密码
+   * @param inputString 输入的字符串
+   * @return 验证结果,TRUE:正确 FALSE:错误
+   */
+  public static boolean validatePassword(String password, String inputString) {
+    if (password.equals(encodeByMD5(inputString))) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /**
+   * 对字符串进行MD5加密
+   */
+  public static String encodeByMD5(String originString) {
+    if (originString != null) {
+      try {
+        //创建具有指定算法名称的信息摘要
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        //使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
+        byte[] results = md.digest(originString.getBytes("UTF-8"));
+        //将得到的字节数组变成字符串返回
+        String resultString = byteArrayToHexString(results);
+        return resultString.toUpperCase();
+      } catch (Exception ex) {
+        ex.printStackTrace();
+      }
+    }
+    return null;
+  }
+
+  /**
+   * 转换字节数组为十六进制字符串
+   *
+   * @param 字节数组
+   * @return 十六进制字符串
+   */
+  private static String byteArrayToHexString(byte[] b) {
+    StringBuffer resultSb = new StringBuffer();
+    for (int i = 0; i < b.length; i++) {
+      resultSb.append(byteToHexString(b[i]));
+    }
+    return resultSb.toString();
+  }
+
+  /**
+   * 将一个字节转化成十六进制形式的字符串
+   */
+  private static String byteToHexString(byte b) {
+    int n = b;
+    if (n < 0)
+      n = 256 + n;
+    int d1 = n / 16;
+    int d2 = n % 16;
+    return hexDigits[d1] + hexDigits[d2];
+  }
+
+  public static String encodeByMD5ForYnrcc(String originString) {
+    if (originString != null) {
+      try {
+        //创建具有指定算法名称的信息摘要
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        //使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
+        byte[] results = md.digest(originString.getBytes("GBK"));
+        //将得到的字节数组变成字符串返回
+        String resultString = byteArrayToHexString(results);
+        return resultString;
+      } catch (Exception ex) {
+        ex.printStackTrace();
+      }
+    }
+    return null;
+  }
+
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/RandomUtils.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/RandomUtils.java
new file mode 100644
index 0000000..6883fba
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/RandomUtils.java
@@ -0,0 +1,104 @@
+package com.supwisdom.agent.Util;
+
+import org.apache.commons.codec.binary.Base32;
+import org.apache.commons.codec.binary.Hex;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * 获取随机数类
+ * 
+ * @author yanhua_mao
+ * 
+ */
+public class RandomUtils {
+
+	/**
+	 * 获取随机数
+	 * 
+	 * @param length
+	 *          位数
+	 * @return 返回随机数
+	 */
+	public static final String randomNumber(int length) {
+		char[] numbersAndLetters = null;
+		java.util.Random randGen = null;
+		if (length < 1) {
+			return null;
+		}
+		if (randGen == null) {
+			randGen = new java.util.Random();
+			numbersAndLetters = ("0123456789").toCharArray();
+		}
+		char[] randBuffer = new char[length];
+		for (int i = 0; i < randBuffer.length; i++) {
+			randBuffer[i] = numbersAndLetters[randGen.nextInt(9)];
+		}
+		return new String(randBuffer);
+	}
+
+	/**
+	 * 产生一个随机的字符串
+	 * 
+	 * @param 字符串长度
+	 * @return
+	 */
+	public static String getRandomString(int length) {
+		String base = "abcdefghijklmnopqrstuvwxyz234567";
+		Random random = new Random();
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < length; i++) {
+			int number = random.nextInt(base.length());
+			sb.append(base.charAt(number));
+		}
+		return sb.toString();
+	}
+
+	public static String getSecureRandom() {
+		SecureRandom a = new SecureRandom();
+		byte[] phonesecret = new byte[10];
+		a.nextBytes(phonesecret);
+
+		Base32 c = new Base32();
+		String s = c.encodeAsString(phonesecret);
+		String savesecret = Hex.encodeHexString(phonesecret);
+		String result = s + "_" + savesecret;
+		return result;
+	}
+
+	public static String getSecureRandomHex() {
+		SecureRandom a = new SecureRandom();
+		byte[] phonesecret = new byte[10];
+		a.nextBytes(phonesecret);
+
+		String savesecret = Hex.encodeHexString(phonesecret);
+		return savesecret;
+	}
+
+	/**
+	 * 
+	 * @param length
+	 * @return
+	 */
+	public static String getCharAndNumr(int length) {
+		String val = "";
+
+		Random random = new Random();
+		for (int i = 0; i < length; i++) {
+			String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 输出字母还是数字
+
+			if ("char".equalsIgnoreCase(charOrNum)) // 字符串
+			{
+				int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; // 取得大写字母还是小写字母
+				val += (char) (choice + random.nextInt(26));
+			} else if ("num".equalsIgnoreCase(charOrNum)) // 数字
+			{
+				val += String.valueOf(random.nextInt(10));
+			}
+		}
+
+		return val;
+	}
+
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/StringUtil.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/StringUtil.java
new file mode 100644
index 0000000..e5fe750
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/StringUtil.java
@@ -0,0 +1,170 @@
+package com.supwisdom.agent.Util;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class StringUtil {
+  /**
+   * 判断字符串是否为空
+   */
+  public static boolean isEmpty(String str) {
+    if (null == str || "".equals(str) || "".equals(str.trim())) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * 判断List是否为空
+   */
+  public static boolean isEmpty(List list) {
+    if (null == list || list.size() <= 0) {
+      return true;
+    }
+    return false;
+  }
+
+  public static boolean equalsIgnoreCase(String str1, String str2) {
+    return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
+  }
+
+  public static boolean equals(String str1, String str2) {
+    return str1 == null ? str2 == null : str1.equals(str2);
+  }
+
+  /**
+   * 手机号验证
+   *
+   * @param str
+   * @return
+   */
+  public static boolean isMobile(String str) {
+    Pattern p = Pattern.compile("^1[0-9]{10}$"); // 验证手机号
+    Matcher m = p.matcher(str);
+    return m.matches();
+  }
+
+  /**
+   * 邮箱格式验证
+   */
+  public static boolean isEmail(String email) {
+    boolean ret = true;
+    Pattern pattern = Pattern.compile("^([a-zA-Z0-9]+[_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\.]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$");
+    final Matcher mat = pattern.matcher(email);
+    if (!mat.find()) {
+      ret = false;
+    }
+    return ret;
+  }
+
+  /**
+   * 身份证格式验证
+   *
+   * @param str
+   * @return
+   */
+  public static boolean isIdentity(String str) {
+    // 中国公民身份证格式:长度为15或18位,最后一位可以为字母
+    Pattern pattern = Pattern.compile("(\\d{14}[0-9a-zA-Z])|(\\d{17}[0-9a-zA-Z])");
+    final Matcher m = pattern.matcher(str);
+    return m.matches();
+  }
+
+  /**
+   * 除去数组中的空值和签名参数
+   *
+   * @param sArray 签名参数组
+   * @return 去掉空值与签名参数后的新签名参数组
+   */
+  public static Map<String, String> paraFilter(Map<String, String> sArray) {
+    Map<String, String> result = new HashMap<String, String>();
+    if (sArray == null || sArray.size() <= 0) {
+      return result;
+    }
+    for (String key : sArray.keySet()) {
+      String value = sArray.get(key);
+      if (null == value || "".equals(value.trim()) || "null".equalsIgnoreCase(value.trim()) || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type")) {
+        continue;
+      }
+      result.put(key, value);
+    }
+    return result;
+  }
+
+  /**
+   * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
+   *
+   * @param params 需要排序并参与字符拼接的参数组
+   * @return 拼接后字符串
+   */
+  public static String createLinkString(Map<String, String> params) {
+
+    List<String> keys = new ArrayList<String>(params.keySet());
+    Collections.sort(keys);
+
+    String prestr = "";
+
+    for (int i = 0; i < keys.size(); i++) {
+      String key = keys.get(i);
+      String value = params.get(key);
+
+      if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
+        prestr = prestr + key + "=" + value;
+      } else {
+        prestr = prestr + key + "=" + value + "&";
+      }
+    }
+
+    return prestr;
+  }
+
+  public static boolean isCharAndNum(String inputStr) {
+    //有问题
+    /*Pattern p = Pattern.compile("\\w+");
+    Matcher m = p.matcher(inputStr);
+    if (m.matches()) {
+      // 除字母和数字外还包含其它字符
+      return false;
+    } else {
+      return true;
+    }*/
+    return true;
+  }
+  /**
+   * 手机号遮掩中间4位
+   * */
+  public static String phoneReplace(String phone){
+    return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
+  }
+
+  /**
+   * 邮箱只显示@前面的首位和末位
+   * */
+  public static String emailReplace(String s){
+    return  s.replaceAll("(\\w?)(\\w+)(\\w)(@\\w+\\.[a-z]+(\\.[a-z]+)?)", "$1****$3$4");
+  }
+
+  /**
+   * 名字显示姓
+   * */
+  public static String nameReplace(String s){
+    return  s.replaceAll("([\\d\\D]{1})(.*)", "$1**");
+  }
+
+
+  /**
+   * 检验时间格式
+   */
+  public static boolean checkDatetimeValid(String datetime, String pattern) {
+    if (null == datetime) return false;
+    try {
+      java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(pattern);
+      Date d = sdf.parse(datetime);
+      return datetime.trim().equals(sdf.format(d));
+    } catch (Exception e) {
+    }
+    return false;
+  }
+
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/XmlUtils.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/XmlUtils.java
new file mode 100644
index 0000000..c4a3eb2
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/Util/XmlUtils.java
@@ -0,0 +1,75 @@
+package com.supwisdom.agent.Util;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import java.io.*;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class XmlUtils {
+  public static <T> String getObjectToXml(T object) throws IOException {
+    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+    try {
+      JAXBContext context = JAXBContext.newInstance(object.getClass());
+      // 将对象转变为xml Object------XML
+      // 指定对应的xml文件
+      Marshaller marshaller = context.createMarshaller();
+      marshaller.setProperty(Marshaller.JAXB_ENCODING, "gbk");//编码格式 
+      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);// 是否格式化生成的xml串
+      marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);// 是否省略xml头信息
+
+      // 将对象转换为对应的XML文件
+      marshaller.marshal(object, byteArrayOutputStream);
+    } catch (JAXBException e) {
+
+      e.printStackTrace();
+    }
+    // 转化为字符串返回
+    String xmlContent = new String(byteArrayOutputStream.toByteArray(),
+        "gbk");
+    return xmlContent;
+  }
+
+  public static <T> T getXmlToObject(String xmlContent, String charset, Class clazz) {
+    try {
+      JAXBContext context = JAXBContext.newInstance(clazz);
+      // xml转换为对象 XML------Object
+      InputStream inputStream;
+      try {
+        inputStream = new ByteArrayInputStream(
+            xmlContent.getBytes(charset));
+        Unmarshaller um = context.createUnmarshaller();
+
+        return (T) um.unmarshal(inputStream);
+      } catch (UnsupportedEncodingException e) {
+        // TODO Auto-generated catch block
+        e.printStackTrace();
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+    } catch (JAXBException e) {
+
+      e.printStackTrace();
+    }
+    return null;
+  }
+
+  public static Map<String, String> parseXml(String xml) throws Exception {
+    Map<String, String> map = new HashMap<String, String>();
+    Document document = DocumentHelper.parseText(xml);
+    Element root = document.getRootElement();
+    List<Element> elementList = root.elements();
+    for (Element e : elementList)
+      map.put(e.getName(), e.getText());
+    return map;
+  }
+
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/YnrccAgentApplication.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/YnrccAgentApplication.java
new file mode 100644
index 0000000..8e1bb6e
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/YnrccAgentApplication.java
@@ -0,0 +1,11 @@
+package com.supwisdom.agent;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class YnrccAgentApplication {
+  public static void main(String[] args) {
+    SpringApplication.run(YnrccAgentApplication.class, args);
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/DlpayReq.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/DlpayReq.java
similarity index 91%
rename from payapi/src/main/java/com/supwisdom/dlpay/api/bean/DlpayReq.java
rename to ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/DlpayReq.java
index 0af068f..8ef13f7 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/DlpayReq.java
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/DlpayReq.java
@@ -1,6 +1,6 @@
-package com.supwisdom.dlpay.api.bean;
+package com.supwisdom.agent.api.bean;
 
-import com.supwisdom.dlpay.framework.util.MD5;
+import com.supwisdom.agent.Util.MD5;
 
 public class DlpayReq {
   private static final String prefix = "<?xml version=\"1.0\" encoding=\"GBK\"?>";
@@ -13,6 +13,7 @@
 
   public static final String DLPAY_CATEGORIE = "C001"; //消费类别
 
+  private String transcode;
   private String transdate; //交易日期
   private String transtime; //交易时间
   private String sn; //应用系统唯一流水号
@@ -40,7 +41,7 @@
     StringBuffer xml = new StringBuffer();
     xml.append(prefix)
         .append("<root>")
-        .append("<TRANSCODE>").append(BANKCARD_BIND_TRANSCODE).append("</TRANSCODE>")
+        .append("<TRANSCODE>").append(transcode).append("</TRANSCODE>")
         .append("<TRANSDATE>").append(transdate).append("</TRANSDATE>")
         .append("<TRANSTIME>").append(transtime).append("</TRANSTIME>")
         .append("<SN>").append(sn).append("</SN>")
@@ -61,7 +62,7 @@
     StringBuffer xml = new StringBuffer();
     xml.append(prefix)
         .append("<root>")
-        .append("<TRANSCODE>").append(BANKCARD_SIGN_TRANSCODE).append("</TRANSCODE>")
+        .append("<TRANSCODE>").append(transcode).append("</TRANSCODE>")
         .append("<TRANSDATE>").append(transdate).append("</TRANSDATE>")
         .append("<TRANSTIME>").append(transtime).append("</TRANSTIME>")
         .append("<SN>").append(sn).append("</SN>")
@@ -83,7 +84,7 @@
     StringBuffer xml = new StringBuffer();
     xml.append(prefix)
         .append("<root>")
-        .append("<TRANSCODE>").append(BANKCARD_PAY_TRANSCODE).append("</TRANSCODE>")
+        .append("<TRANSCODE>").append(transcode).append("</TRANSCODE>")
         .append("<TRANSDATE>").append(transdate).append("</TRANSDATE>")
         .append("<TRANSTIME>").append(transtime).append("</TRANSTIME>")
         .append("<SN>").append(sn).append("</SN>")
@@ -96,7 +97,7 @@
         .append("<MERCHANT_NAME>").append(merchantName).append("</MERCHANT_NAME>")
         .append("<AMOUNT>").append(amount).append("</AMOUNT>")
         .append("<DESCRIPTION>").append(description).append("</DESCRIPTION>")
-        .append("<MAC>").append(MD5.encodeByMD5ForDlpay(merchantBcno + bcNo + amount)).append("</MAC>")
+        .append("<MAC>").append(MD5.encodeByMD5ForYnrcc(merchantBcno + bcNo + amount)).append("</MAC>")
         .append("</root>");
     return String.format("%08d", xml.toString().length()) + xml.toString();
   }
@@ -108,7 +109,7 @@
     StringBuffer xml = new StringBuffer();
     xml.append(prefix)
         .append("<root>")
-        .append("<TRANSCODE>").append(BANKCARD_PAYREFUND_TRANSCODE).append("</TRANSCODE>")
+        .append("<TRANSCODE>").append(transcode).append("</TRANSCODE>")
         .append("<TRANSDATE>").append(transdate).append("</TRANSDATE>")
         .append("<TRANSTIME>").append(transtime).append("</TRANSTIME>")
         .append("<SN>").append(sn).append("</SN>")
@@ -126,7 +127,7 @@
     StringBuffer xml = new StringBuffer();
     xml.append(prefix)
         .append("<root>")
-        .append("<TRANSCODE>").append(BANKCARD_QUERYRESULT_TRANSCODE).append("</TRANSCODE>")
+        .append("<TRANSCODE>").append(transcode).append("</TRANSCODE>")
         .append("<TRANSDATE>").append(transdate).append("</TRANSDATE>")
         .append("<TRANSTIME>").append(transtime).append("</TRANSTIME>")
         .append("<SN>").append(sn).append("</SN>")
@@ -142,7 +143,7 @@
     StringBuffer xml = new StringBuffer();
     xml.append(prefix)
         .append("<root>")
-        .append("<TRANSCODE>").append(BANKCARD_CHKFILE_TRANSCODE).append("</TRANSCODE>")
+        .append("<TRANSCODE>").append(transcode).append("</TRANSCODE>")
         .append("<TRANSDATE>").append(transdate).append("</TRANSDATE>")
         .append("<TRANSTIME>").append(transtime).append("</TRANSTIME>")
         .append("<SN>").append(sn).append("</SN>")
@@ -279,4 +280,12 @@
   public void setChkdate(String chkdate) {
     this.chkdate = chkdate;
   }
+
+  public String getTranscode() {
+    return transcode;
+  }
+
+  public void setTranscode(String transcode) {
+    this.transcode = transcode;
+  }
 }
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/DlpayResp.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/DlpayResp.java
new file mode 100644
index 0000000..7c18daf
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/bean/DlpayResp.java
@@ -0,0 +1,92 @@
+package com.supwisdom.agent.api.bean;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "root")
+public class DlpayResp {
+  private String code;
+  private String message;
+  private String transdate;
+  private String transtime;
+  private String bankjourno;
+  private String captcha;
+  private String status;
+  private String filename;
+
+  @XmlElement(name = "CODE")
+  public String getCode() {
+    return code;
+  }
+
+  public void setCode(String code) {
+    this.code = code;
+  }
+
+  @XmlElement(name = "MESSAGE")
+  public String getMessage() {
+    return message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+
+  @XmlElement(name = "TRANSDATE")
+  public String getTransdate() {
+    return transdate;
+  }
+
+  public void setTransdate(String transdate) {
+    this.transdate = transdate;
+  }
+
+  @XmlElement(name = "TRANSTIME")
+  public String getTranstime() {
+    return transtime;
+  }
+
+  public void setTranstime(String transtime) {
+    this.transtime = transtime;
+  }
+
+  @XmlElement(name = "BANKJOURNO")
+  public String getBankjourno() {
+    return bankjourno;
+  }
+
+  public void setBankjourno(String bankjourno) {
+    this.bankjourno = bankjourno;
+  }
+
+  @XmlElement(name = "CAPTCHA")
+  public String getCaptcha() {
+    return captcha;
+  }
+
+  public void setCaptcha(String captcha) {
+    this.captcha = captcha;
+  }
+
+  @XmlElement(name = "STATUS")
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  @XmlElement(name = "FILENAME")
+  public String getFilename() {
+    return filename;
+  }
+
+  public void setFilename(String filename) {
+    this.filename = filename;
+  }
+
+  public String errPrint() {
+    return "error: code=[" + this.code + "],message=[" + this.message + "]";
+  }
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/controller/YnrccApiController.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/controller/YnrccApiController.java
new file mode 100644
index 0000000..d414447
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/controller/YnrccApiController.java
@@ -0,0 +1,377 @@
+package com.supwisdom.agent.api.controller;
+
+import com.supwisdom.agent.Util.BussinessException;
+import com.supwisdom.agent.Util.DlpayUtil;
+import com.supwisdom.agent.Util.ErrorCode;
+import com.supwisdom.agent.Util.StringUtil;
+import com.supwisdom.agent.api.bean.DlpayReq;
+import com.supwisdom.agent.api.bean.DlpayResp;
+import com.supwisdom.agent.api.service.YnrccApiService;
+import com.supwisdom.agent.api.service.YnrccParamCheckService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.ws.rs.FormParam;
+import java.util.HashMap;
+import java.util.Map;
+
+
+@RestController
+@RequestMapping("/ynrcc")
+public class YnrccApiController {
+  @Autowired
+  private YnrccApiService ynrccApiService;
+  @Autowired
+  private YnrccParamCheckService ynrccParamCheckService;
+
+  private static final Logger logger = LoggerFactory.getLogger(YnrccApiController.class);
+
+  private boolean checkYnrccSign(Map<String, String> params, DlpayResp resp) {
+    if (!ynrccParamCheckService.checkSign(params)) {
+      resp.setCode(ErrorCode.REQ_SIGN_ERROR);
+      resp.setMessage("签名错误");
+      logger.error(resp.errPrint());
+      return false;
+    }
+    return true;
+  }
+
+  private void doSystemError(Exception e, DlpayResp resp) {
+    e.printStackTrace();
+    resp.setCode(ErrorCode.SYSTEM_ERROR);
+    resp.setMessage(StringUtil.isEmpty(e.getMessage()) ? "业务处理异常" : e.getMessage());
+    logger.error(resp.errPrint());
+  }
+
+  /**
+   * 绑定银行卡
+   */
+  @PostMapping("/bindcard")
+  public DlpayResp bindBankcard(@FormParam("transcode") String transcode, @FormParam("transdate") String transdate,
+                                @FormParam("transtime") String transtime, @FormParam("refno") String refno,
+                                @FormParam("bankcardno") String bankcardno, @FormParam("username") String username,
+                                @FormParam("idtype") String idtype, @FormParam("idno") String idno,
+                                @FormParam("phone") String phone,
+                                @FormParam("sign_type") String sign_type, @FormParam("sign") String sign) {
+    DlpayResp resp = new DlpayResp();
+    if (!ynrccParamCheckService.checkBindCardParam(transcode, transdate, transtime, refno, bankcardno, username, idtype, idno, phone, sign_type, sign, resp)) {
+      logger.error(resp.errPrint());
+      return resp;
+    }
+
+    Map<String, String> params = new HashMap<>(0);
+    params.put("transcode", transcode);
+    params.put("transdate", transdate);
+    params.put("transtime", transtime);
+    params.put("refno", refno);
+    params.put("bankcardno", bankcardno);
+    params.put("username", username);
+    params.put("idtype", idtype);
+    params.put("idno", idno);
+    params.put("phone", phone);
+    params.put("sign_type", sign_type);
+    params.put("sign", sign);
+    if (!checkYnrccSign(params, resp)) {
+      return resp;
+    }
+
+    try {
+      DlpayReq req = new DlpayReq();
+      req.setTranscode(transcode);
+      req.setTransdate(transdate);
+      req.setTranstime(transtime);
+      req.setSn(refno);
+      req.setBcNo(bankcardno);
+      req.setName(username);
+      req.setIdType(idtype);
+      req.setIdNo(idno);
+      req.setPhone(phone);
+      return ynrccApiService.sendToYnrcc(DlpayUtil.OPTYPE_BINDCARD, req);
+    } catch (BussinessException be) {
+      resp.setCode(ErrorCode.BUSSINESS_ERROR);
+      resp.setMessage(be.getMessage());
+      logger.error(resp.errPrint());
+      return resp;
+    } catch (Exception e) {
+      doSystemError(e, resp);
+      return resp;
+    }
+  }
+
+  /**
+   * 银行卡签约/解约
+   */
+  @PostMapping("/signcard")
+  public DlpayResp signBankcard(@FormParam("transcode") String transcode, @FormParam("transdate") String transdate,
+                                @FormParam("transtime") String transtime, @FormParam("refno") String refno,
+                                @FormParam("categorie") String categorie, @FormParam("transtype") String transtype,
+                                @FormParam("bankcardno") String bankcardno, @FormParam("username") String username,
+                                @FormParam("idtype") String idtype, @FormParam("idno") String idno,
+                                @FormParam("phone") String phone,
+                                @FormParam("sign_type") String sign_type, @FormParam("sign") String sign) {
+    DlpayResp resp = new DlpayResp();
+    if (!ynrccParamCheckService.checkSignCardParam(transcode, transdate, transtime, refno, categorie, bankcardno,
+        username, idtype, idno, phone, transtype, sign_type, sign, resp)) {
+      logger.error(resp.errPrint());
+      return resp;
+    }
+
+    Map<String, String> params = new HashMap<>(0);
+    params.put("transcode", transcode);
+    params.put("transdate", transdate);
+    params.put("transtime", transtime);
+    params.put("refno", refno);
+    params.put("categorie", categorie);
+    params.put("bankcardno", bankcardno);
+    params.put("username", username);
+    params.put("idtype", idtype);
+    params.put("idno", idno);
+    params.put("phone", phone);
+    params.put("transtype", transtype);
+    params.put("sign_type", sign_type);
+    params.put("sign", sign);
+    if (!checkYnrccSign(params, resp)) {
+      return resp;
+    }
+
+    try {
+      DlpayReq req = new DlpayReq();
+      req.setTranscode(transcode);
+      req.setTransdate(transdate);
+      req.setTranstime(transtime);
+      req.setSn(refno);
+      req.setCategorie(categorie);
+      req.setBcNo(bankcardno);
+      req.setName(username);
+      req.setIdType(idtype);
+      req.setIdNo(idno);
+      req.setPhone(phone);
+      req.setTransType(transtype);
+      return ynrccApiService.sendToYnrcc(DlpayUtil.OPTYPE_SIGNCARD, req);
+    } catch (BussinessException be) {
+      resp.setCode(ErrorCode.BUSSINESS_ERROR);
+      resp.setMessage(be.getMessage());
+      logger.error(resp.errPrint());
+      return resp;
+    } catch (Exception e) {
+      doSystemError(e, resp);
+      return resp;
+    }
+  }
+
+  /**
+   * 银行卡代扣
+   */
+  @PostMapping("/cardpay")
+  public DlpayResp cardpay(@FormParam("transcode") String transcode, @FormParam("transdate") String transdate,
+                           @FormParam("transtime") String transtime, @FormParam("refno") String refno,
+                           @FormParam("categorie") String categorie,
+                           @FormParam("bankcardno") String bankcardno, @FormParam("username") String username,
+                           @FormParam("idtype") String idtype, @FormParam("idno") String idno,
+                           @FormParam("merchant_bankcardno") String merchant_bankcardno,
+                           @FormParam("merchant_bankaccname") String merchant_bankaccname,
+                           @FormParam("amount") Integer amount,
+                           @FormParam("description") String description,
+                           @FormParam("sign_type") String sign_type, @FormParam("sign") String sign) {
+    DlpayResp resp = new DlpayResp();
+    if (!ynrccParamCheckService.checkCardPayParam(transcode, transdate, transtime, refno, categorie, bankcardno,
+        username, idtype, idno, merchant_bankcardno, merchant_bankaccname, amount, description, sign_type, sign, resp)) {
+      logger.error(resp.errPrint());
+      return resp;
+    }
+
+    Map<String, String> params = new HashMap<>(0);
+    params.put("transcode", transcode);
+    params.put("transdate", transdate);
+    params.put("transtime", transtime);
+    params.put("refno", refno);
+    params.put("categorie", categorie);
+    params.put("bankcardno", bankcardno);
+    params.put("username", username);
+    params.put("idtype", idtype);
+    params.put("idno", idno);
+    params.put("merchant_bankcardno", merchant_bankcardno);
+    params.put("merchant_bankaccname", merchant_bankaccname);
+    params.put("amount", String.valueOf(amount));
+    params.put("description", description);
+    params.put("sign_type", sign_type);
+    params.put("sign", sign);
+    if (!checkYnrccSign(params, resp)) {
+      return resp;
+    }
+
+    try {
+      DlpayReq req = new DlpayReq();
+      req.setTranscode(transcode);
+      req.setTransdate(transdate);
+      req.setTranstime(transtime);
+      req.setSn(refno);
+      req.setCategorie(categorie);
+      req.setBcNo(bankcardno);
+      req.setName(username);
+//      req.setIdType(idtype);
+      req.setIdNo(idno);
+      req.setMerchantBcno(merchant_bankcardno);
+      req.setMerchantName(merchant_bankaccname);
+      req.setAmount(amount);
+      req.setDescription(description);
+      return ynrccApiService.sendToYnrcc(DlpayUtil.OPTYPE_CARDPAY, req);
+    } catch (BussinessException be) {
+      resp.setCode(ErrorCode.BUSSINESS_ERROR);
+      resp.setMessage(be.getMessage());
+      logger.error(resp.errPrint());
+      return resp;
+    } catch (Exception e) {
+      doSystemError(e, resp);
+      return resp;
+    }
+  }
+
+  /**
+   * 银行卡代扣退款
+   */
+  @PostMapping("/cardpayrefund")
+  public DlpayResp cardpayRefund(@FormParam("transcode") String transcode, @FormParam("transdate") String transdate,
+                                 @FormParam("transtime") String transtime, @FormParam("refno") String refno,
+                                 @FormParam("refund_refno") String refundRefno,
+                                 @FormParam("amount") Integer amount, @FormParam("description") String description,
+                                 @FormParam("sign_type") String sign_type, @FormParam("sign") String sign) {
+    DlpayResp resp = new DlpayResp();
+    if (!ynrccParamCheckService.checkPayRefundParam(transcode, transdate, transtime, refno, refundRefno, amount, description, sign_type, sign, resp)) {
+      logger.error(resp.errPrint());
+      return resp;
+    }
+
+    Map<String, String> params = new HashMap<>(0);
+    params.put("transcode", transcode);
+    params.put("transdate", transdate);
+    params.put("transtime", transtime);
+    params.put("refno", refno);
+    params.put("refund_refno", refundRefno);
+    params.put("amount", String.valueOf(amount));
+    params.put("description", description);
+    params.put("sign_type", sign_type);
+    params.put("sign", sign);
+    if (!checkYnrccSign(params, resp)) {
+      return resp;
+    }
+
+    try {
+      DlpayReq req = new DlpayReq();
+      req.setTranscode(transcode);
+      req.setTransdate(transdate);
+      req.setTranstime(transtime);
+      req.setSn(refno);
+      req.setOriSn(refundRefno);
+      req.setAmount(amount);
+      req.setDescription(description);
+      return ynrccApiService.sendToYnrcc(DlpayUtil.OPTYPE_PAYREFUND, req);
+    } catch (BussinessException be) {
+      resp.setCode(ErrorCode.BUSSINESS_ERROR);
+      resp.setMessage(be.getMessage());
+      logger.error(resp.errPrint());
+      return resp;
+    } catch (Exception e) {
+      doSystemError(e, resp);
+      return resp;
+    }
+  }
+
+  /**
+   * 查询消费结果
+   */
+  @PostMapping("/queryresult")
+  public DlpayResp queryResult(@FormParam("transcode") String transcode, @FormParam("transdate") String transdate,
+                               @FormParam("transtime") String transtime, @FormParam("refno") String refno,
+                               @FormParam("orign_refno") String orignRefno,
+                               @FormParam("sign_type") String sign_type, @FormParam("sign") String sign) {
+    DlpayResp resp = new DlpayResp();
+    if (!ynrccParamCheckService.checkQueryResultParam(transcode, transdate, transtime, refno, orignRefno, sign_type, sign, resp)) {
+      logger.error(resp.errPrint());
+      return resp;
+    }
+
+    Map<String, String> params = new HashMap<>(0);
+    params.put("transcode", transcode);
+    params.put("transdate", transdate);
+    params.put("transtime", transtime);
+    params.put("refno", refno);
+    params.put("orign_refno", orignRefno);
+    params.put("sign_type", sign_type);
+    params.put("sign", sign);
+    if (!checkYnrccSign(params, resp)) {
+      return resp;
+    }
+
+    try {
+      DlpayReq req = new DlpayReq();
+      req.setTranscode(transcode);
+      req.setTransdate(transdate);
+      req.setTranstime(transtime);
+      req.setSn(refno);
+      req.setOriSn(orignRefno);
+      return ynrccApiService.sendToYnrcc(DlpayUtil.OPTYPE_QUERYRESULT, req);
+    } catch (BussinessException be) {
+      resp.setCode(ErrorCode.BUSSINESS_ERROR);
+      resp.setMessage(be.getMessage());
+      logger.error(resp.errPrint());
+      return resp;
+    } catch (Exception e) {
+      doSystemError(e, resp);
+      return resp;
+    }
+  }
+
+  /**
+   * 查询消费结果
+   */
+  @PostMapping("/checkdtl")
+  public DlpayResp checkDtl(@FormParam("transcode") String transcode, @FormParam("transdate") String transdate,
+                            @FormParam("transtime") String transtime, @FormParam("refno") String refno,
+                            @FormParam("checkdate") String checkdate, @FormParam("merchant_bankcardno") String merchant_bankcardno,
+                            @FormParam("sign_type") String sign_type, @FormParam("sign") String sign) {
+    DlpayResp resp = new DlpayResp();
+    if (!ynrccParamCheckService.checkChkfileParam(transcode, transdate, transtime, refno, checkdate, merchant_bankcardno, sign_type, sign, resp)) {
+      logger.error(resp.errPrint());
+      return resp;
+    }
+
+    Map<String, String> params = new HashMap<>(0);
+    params.put("transcode", transcode);
+    params.put("transdate", transdate);
+    params.put("transtime", transtime);
+    params.put("refno", refno);
+    params.put("checkdate", checkdate);
+    params.put("merchant_bankcardno", merchant_bankcardno);
+    params.put("sign_type", sign_type);
+    params.put("sign", sign);
+    if (!checkYnrccSign(params, resp)) {
+      return resp;
+    }
+
+    try {
+      DlpayReq req = new DlpayReq();
+      req.setTranscode(transcode);
+      req.setTransdate(transdate);
+      req.setTranstime(transtime);
+      req.setSn(refno);
+      req.setChkdate(checkdate);
+      req.setMerchantBcno(merchant_bankcardno);
+      return ynrccApiService.sendToYnrcc(DlpayUtil.OPTYPE_CHKDTL, req);
+    } catch (BussinessException be) {
+      resp.setCode(ErrorCode.BUSSINESS_ERROR);
+      resp.setMessage(be.getMessage());
+      logger.error(resp.errPrint());
+      return resp;
+    } catch (Exception e) {
+      doSystemError(e, resp);
+      return resp;
+    }
+  }
+
+
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/YnrccApiService.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/YnrccApiService.java
new file mode 100644
index 0000000..78241a1
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/YnrccApiService.java
@@ -0,0 +1,8 @@
+package com.supwisdom.agent.api.service;
+
+import com.supwisdom.agent.api.bean.DlpayReq;
+import com.supwisdom.agent.api.bean.DlpayResp;
+
+public interface YnrccApiService {
+  DlpayResp sendToYnrcc(String optype, DlpayReq req) throws Exception;
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/YnrccParamCheckService.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/YnrccParamCheckService.java
new file mode 100644
index 0000000..88b1fa8
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/YnrccParamCheckService.java
@@ -0,0 +1,27 @@
+package com.supwisdom.agent.api.service;
+
+import com.supwisdom.agent.api.bean.DlpayResp;
+
+import java.util.Map;
+
+public interface YnrccParamCheckService {
+  boolean checkBindCardParam(String transcode, String transdate, String transtime, String refno,
+                             String bankcardno, String username, String idtype, String idno,
+                             String phone, String sign_type, String sign, DlpayResp resp);
+
+  boolean checkSign(Map<String, String> param);
+
+  boolean checkSignCardParam(String transcode, String transdate, String transtime, String refno, String categorie, String bankcardno, String username,
+                             String idtype, String idno, String phone, String transtype, String sign_type, String sign, DlpayResp resp);
+
+  boolean checkCardPayParam(String transcode, String transdate, String transtime, String refno, String categorie, String bankcardno, String username,
+                            String idtype, String idno, String merchant_bankcardno, String merchant_bankaccname, Integer amount, String description,
+                            String sign_type, String sign, DlpayResp resp);
+
+  boolean checkPayRefundParam(String transcode, String transdate, String transtime, String refno, String refundRefno, Integer amount, String description,
+                              String sign_type, String sign, DlpayResp resp);
+
+  boolean checkQueryResultParam(String transcode, String transdate, String transtime, String refno, String orignRefno, String sign_type, String sign, DlpayResp resp);
+
+  boolean checkChkfileParam(String transcode, String transdate, String transtime, String refno, String checkdate, String merchant_bankcardno, String sign_type, String sign, DlpayResp resp);
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/impl/YnrccApiServiceImpl.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/impl/YnrccApiServiceImpl.java
new file mode 100644
index 0000000..3f55da7
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/impl/YnrccApiServiceImpl.java
@@ -0,0 +1,81 @@
+package com.supwisdom.agent.api.service.impl;
+
+import com.supwisdom.agent.Util.BussinessException;
+import com.supwisdom.agent.Util.DlpayUtil;
+import com.supwisdom.agent.Util.StringUtil;
+import com.supwisdom.agent.Util.XmlUtils;
+import com.supwisdom.agent.api.bean.DlpayReq;
+import com.supwisdom.agent.api.bean.DlpayResp;
+import com.supwisdom.agent.api.service.YnrccApiService;
+import com.supwisdom.agent.config.YnrccSocketConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class YnrccApiServiceImpl implements YnrccApiService {
+  @Autowired
+  private YnrccSocketConfig ynrccSocketConfig;
+
+  private static final Logger logger = LoggerFactory.getLogger(YnrccApiServiceImpl.class);
+
+  @Override
+  public DlpayResp sendToYnrcc(String optype, DlpayReq req) throws Exception {
+    String ip = ynrccSocketConfig.getIp();
+    Integer port = ynrccSocketConfig.getPort();
+    int timeout = ynrccSocketConfig.getTimeout();
+    if (StringUtil.isEmpty(ip) || null == port) {
+      throw new BussinessException("农商行Socket的IP和端口未配置");
+    }
+
+    String sendXml = null;
+    if (DlpayUtil.OPTYPE_BINDCARD.equals(optype)) {
+      //绑定银行卡
+      sendXml = req.getBindCardXml();
+      logger.error("请求【绑定银行卡】发送报文:\n" + sendXml);
+
+    } else if (DlpayUtil.OPTYPE_SIGNCARD.equals(optype)) {
+      sendXml = req.getSignXml();
+      logger.error("请求【银行卡签(解)约】发送报文:\n" + sendXml);
+
+    } else if (DlpayUtil.OPTYPE_CARDPAY.equals(optype)) {
+      sendXml = req.getCardpayXml();
+      logger.error("请求【银行卡代扣】发送报文:\n" + sendXml);
+
+    } else if (DlpayUtil.OPTYPE_CARDPAY.equals(optype)) {
+      sendXml = req.getCardpayXml();
+      logger.error("请求【银行卡代扣】发送报文:\n" + sendXml);
+
+    } else if (DlpayUtil.OPTYPE_PAYREFUND.equals(optype)) {
+      sendXml = req.getPayRefundXml();
+      logger.error("请求【代扣消费退款】发送报文:\n" + sendXml);
+
+    } else if (DlpayUtil.OPTYPE_QUERYRESULT.equals(optype)) {
+      sendXml = req.getQueryResultXml();
+      logger.error("请求【消费结果查询】发送报文:\n" + sendXml);
+
+    } else if (DlpayUtil.OPTYPE_CHKDTL.equals(optype)) {
+      sendXml = req.getChkfileXml();
+      logger.error("请求【获取对账单=" + req.getChkdate() + "】发送报文:\n" + sendXml);
+
+    } else {
+      throw new BussinessException("请求类型[" + optype + "]错误!");
+    }
+
+    String returnXml = DlpayUtil.send(ip, port, timeout, sendXml);
+    logger.error("refno=[" + req.getSn() + "]返回报文:\n" + returnXml);
+
+    if (StringUtil.isEmpty(returnXml)) {
+      throw new Exception("返回报文为空");
+    }
+
+    try {
+      DlpayResp resp = XmlUtils.getXmlToObject(returnXml, "GBK", DlpayResp.class);
+      return resp;
+    } catch (Exception e) {
+      throw new BussinessException("返回报文解析异常!");
+    }
+  }
+
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/impl/YnrccParamCheckServiceImpl.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/impl/YnrccParamCheckServiceImpl.java
new file mode 100644
index 0000000..c490e1b
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/api/service/impl/YnrccParamCheckServiceImpl.java
@@ -0,0 +1,232 @@
+package com.supwisdom.agent.api.service.impl;
+
+import com.supwisdom.agent.Util.ErrorCode;
+import com.supwisdom.agent.Util.MD5;
+import com.supwisdom.agent.Util.StringUtil;
+import com.supwisdom.agent.api.bean.DlpayResp;
+import com.supwisdom.agent.api.service.YnrccParamCheckService;
+import com.supwisdom.agent.config.YnrccSocketConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+@Service
+public class YnrccParamCheckServiceImpl implements YnrccParamCheckService {
+  @Autowired
+  private YnrccSocketConfig ynrccSocketConfig;
+
+  private static final Logger logger = LoggerFactory.getLogger(YnrccParamCheckServiceImpl.class);
+
+  private boolean checkYnrccBaseParam(String transcode, String transdate, String transtime, String refno, String sign_type, String sign, DlpayResp resp) {
+    if (StringUtil.isEmpty(transcode)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[报文业务类型为空]");
+      return false;
+    }
+    if (!StringUtil.checkDatetimeValid(transdate, "yyyyMMdd")) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[交易日期错误]");
+      return false;
+    }
+    if (!StringUtil.checkDatetimeValid(transtime, "HHmmss")) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[交易时间错误]");
+      return false;
+    }
+    if (StringUtil.isEmpty(refno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[业务请求交易流水号为空]");
+      return false;
+    }
+
+    if (StringUtil.isEmpty(sign_type)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[签名方式为空]");
+      return false;
+    }
+
+    if (StringUtil.isEmpty(sign)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[签名为空]");
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public boolean checkBindCardParam(String transcode, String transdate, String transtime, String refno, String bankcardno, String username, String idtype, String idno, String phone, String sign_type, String sign, DlpayResp resp) {
+    if (!checkYnrccBaseParam(transcode, transdate, transtime, refno, sign_type, sign, resp)) {
+      return false;
+    }
+    if (StringUtil.isEmpty(bankcardno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[用户银行卡号为空]");
+      return false;
+    }
+    if (StringUtil.isEmpty(username)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[用户名为空]");
+      return false;
+    }
+    if (StringUtil.isEmpty(idtype)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[证件类型为空]");
+      return false;
+    }
+    if (StringUtil.isEmpty(idno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[证件号为空]");
+      return false;
+    }
+    if (StringUtil.isEmpty(phone)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[手机号]");
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public boolean checkSign(Map<String, String> param) {
+    String sign = param.get("sign");
+    String signType = param.get("sign_type");
+    if (!StringUtil.isEmpty(sign)) {
+      String signdata = StringUtil.createLinkString(StringUtil.paraFilter(param));
+      logger.info(signdata);
+
+      String calcSign = null;
+      String md5Key = ynrccSocketConfig.getMd5Key();
+      if ("MD5".equalsIgnoreCase(signType)) {
+        calcSign = MD5.encodeByMD5(signdata + md5Key); //默认MD5
+      }
+
+      if (sign.equalsIgnoreCase(calcSign)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  @Override
+  public boolean checkSignCardParam(String transcode, String transdate, String transtime, String refno, String categorie, String bankcardno, String username,
+                                    String idtype, String idno, String phone, String transtype, String sign_type, String sign, DlpayResp resp) {
+    if (!checkBindCardParam(transcode, transdate, transtime, refno, bankcardno, username, idtype, idno, phone, sign_type, sign, resp)) {
+      return false;
+    }
+    if (StringUtil.isEmpty(categorie)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[消费类别]");
+      return false;
+    }
+    if (StringUtil.isEmpty(transtype)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[签约标志]");
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public boolean checkCardPayParam(String transcode, String transdate, String transtime, String refno, String categorie, String bankcardno, String username, String idtype, String idno, String merchant_bankcardno, String merchant_bankaccname, Integer amount, String description, String sign_type, String sign, DlpayResp resp) {
+    if (!checkYnrccBaseParam(transcode, transdate, transtime, refno, sign_type, sign, resp)) {
+      return false;
+    }
+    if (StringUtil.isEmpty(categorie)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[消费类别]");
+      return false;
+    }
+    if (StringUtil.isEmpty(bankcardno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[用户银行卡号为空]");
+      return false;
+    }
+    if (StringUtil.isEmpty(username)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[用户名为空]");
+      return false;
+    }
+//    if(StringUtil.isEmpty(idtype)){
+//      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+//      resp.setMessage("请求参数错误[证件类型为空]");
+//      return false;
+//    }
+
+    if (StringUtil.isEmpty(idno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[证件号为空]");
+      return false;
+    }
+    if (StringUtil.isEmpty(merchant_bankcardno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[商户银行卡号为空]");
+      return false;
+    }
+    if (StringUtil.isEmpty(merchant_bankaccname)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[商户银行开户名为空]");
+      return false;
+    }
+    if (null == amount) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[交易金额为空]");
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public boolean checkPayRefundParam(String transcode, String transdate, String transtime, String refno, String refundRefno, Integer amount, String description,
+                                     String sign_type, String sign, DlpayResp resp) {
+    if (!checkYnrccBaseParam(transcode, transdate, transtime, refno, sign_type, sign, resp)) {
+      return false;
+    }
+    if (StringUtil.isEmpty(refundRefno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[原交易流水号为空]");
+      return false;
+    }
+    if (null == amount) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[交易金额为空]");
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public boolean checkQueryResultParam(String transcode, String transdate, String transtime, String refno, String orignRefno, String sign_type, String sign, DlpayResp resp) {
+    if (!checkYnrccBaseParam(transcode, transdate, transtime, refno, sign_type, sign, resp)) {
+      return false;
+    }
+    if (StringUtil.isEmpty(orignRefno)) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[原交易流水号为空]");
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public boolean checkChkfileParam(String transcode, String transdate, String transtime, String refno, String checkdate, String merchant_bankcardno, String sign_type, String sign, DlpayResp resp) {
+    if (!checkYnrccBaseParam(transcode, transdate, transtime, refno, sign_type, sign, resp)) {
+      return false;
+    }
+
+    if (StringUtil.checkDatetimeValid(checkdate,"yyyyMMdd")) {
+      resp.setCode(ErrorCode.REQ_PARAM_ERROR);
+      resp.setMessage("请求参数错误[对账日期]");
+      return false;
+    }
+
+    return true;
+  }
+}
diff --git a/ynrcc-agent/src/main/java/com/supwisdom/agent/config/YnrccSocketConfig.java b/ynrcc-agent/src/main/java/com/supwisdom/agent/config/YnrccSocketConfig.java
new file mode 100644
index 0000000..e11398c
--- /dev/null
+++ b/ynrcc-agent/src/main/java/com/supwisdom/agent/config/YnrccSocketConfig.java
@@ -0,0 +1,32 @@
+package com.supwisdom.agent.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class YnrccSocketConfig {
+  @Value("${ynrcc.socket.ip}")
+  private String ip;
+  @Value("${ynrcc.socket.port}")
+  private Integer port;
+  @Value("${ynrcc.socket.timeout}")
+  private int timeout = 10;
+  @Value("${ynrcc.md5.key}")
+  private String md5Key;
+
+  public String getIp() {
+    return ip;
+  }
+
+  public Integer getPort() {
+    return port;
+  }
+
+  public int getTimeout() {
+    return timeout;
+  }
+
+  public String getMd5Key() {
+    return md5Key;
+  }
+}
diff --git a/ynrcc-agent/src/main/resources/application.properties b/ynrcc-agent/src/main/resources/application.properties
new file mode 100644
index 0000000..167f4ac
--- /dev/null
+++ b/ynrcc-agent/src/main/resources/application.properties
@@ -0,0 +1,36 @@
+#######################################springboot配置 start#################################
+#spring.application.name=supwisdom.ynrcc.agent
+#spring.cloud.consul.discovery.health-check-path=${management.context-path}/api/common/version
+#spring.cloud.consul.discovery.health-check-interval=10s
+#spring.cloud.consul.discovery.instanceId=${spring.application.name}:${spring.application.instance_id:${random.value}}
+##################### 单库数据库配置 ##############################
+#spring.jpa.show-sql=true
+#s#pring.datasource.hikari.connection-timeout=60000
+#spring.datasource.hikari.maximum-pool-size=5
+#spring.jpa.hibernate.ddl-auto=update
+##################### redis ##############################
+#spring.redis.host=172.28.201.101
+#spring.redis.port=16379
+#spring.redis.password=kingstar
+#spring.redis.database=0
+
+# logging
+logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
+logging.level.org.hibernate.SQL=debug
+#################### JSP PAGE ####################
+server.servlet.context-path=/ynrccagent
+################## 全局字符编码设置 ######################
+spring.http.encoding.force=true
+spring.http.encoding.charset=UTF-8
+spring.http.encoding.enabled=true
+server.tomcat.uri-encoding=UTF-8
+##################################################
+## quartz task scheduler
+#dayend.settletask.cron = 0 0/2 * * * ?
+
+############# YNRCC SOCKET ###############
+ynrcc.socket.ip=127.0.0.1
+ynrcc.socket.port=8089
+## 超时时间(分钟)
+ynrcc.socket.timeout = 10
+ynrcc.md5.key=80816b7947ed016bff8079557735006e