Merge tag '1.0.11' into develop

同步卡信息时增加更新时间字段
diff --git a/build.gradle b/build.gradle
index 3bf4e38..83b1ec8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,6 @@
 plugins {
     id 'java'
-    id 'org.springframework.boot' version '2.1.6.RELEASE' apply false
+    id 'org.springframework.boot' version '2.2.2.RELEASE' apply false
     id 'org.jetbrains.kotlin.jvm' version '1.3.31'
     id 'org.jetbrains.kotlin.plugin.spring' version '1.3.31'
     id 'org.jetbrains.kotlin.plugin.jpa' version '1.3.31' apply false
@@ -84,12 +84,13 @@
             javaxWSRSVersion = '2.1.1'
             dom4jVersion = '2.1.1'
             springSocialVersion = '1.1.6.RELEASE'
-            springKafkaVersion = '2.2.8.RELEASE'
+            springKafkaVersion = '2.3.4.RELEASE'
             postgresVersion = '42.2.5'
         }
         implementation "org.jetbrains.kotlin:kotlin-reflect"
         implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
 
+        implementation "org.springframework.boot:spring-boot-starter"
         implementation "org.springframework.boot:spring-boot-starter-data-jpa"
         implementation "org.springframework.boot:spring-boot-starter-data-redis"
         implementation "org.springframework.boot:spring-boot-starter-validation"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 7e5d2a8..36fd7d1 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/CitizenCardInfo.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/CitizenCardInfo.java
index d99daf7..dadc1ff 100644
--- a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/CitizenCardInfo.java
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/CitizenCardInfo.java
@@ -1,5 +1,6 @@
 package com.supwisdom.dlpay.api.bean;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
@@ -9,6 +10,7 @@
 @Setter
 @AllArgsConstructor
 @NoArgsConstructor
+@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
 public class CitizenCardInfo {
   private String cardno;
   private String cardphyid;
@@ -23,4 +25,5 @@
   private String idno;
   private String phone;
   private String bankcardno;
+  private String updtime;
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/card_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/card_service_impl.kt
index e03ca66..d202f78 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/card_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/card_service_impl.kt
@@ -110,7 +110,7 @@
     override fun getCardsByLastsaveDate(startdate: String, enddate: String): CardsResponse {
         var resp = CardsResponse()
 //        var ret = cardDao.findCitizencardByLastsaved(startdate,enddate)
-        val query = entityManager.createNativeQuery("select a.cardno,a.cardphyid,a.expiredate,a.status as cardstatus,a.trans_status as transstatus,a.userid,b.name as username,b.sex,b.idtype,b.idno,b.mobile as phone,c.cardno as bankcardno \n" +
+        val query = entityManager.createNativeQuery("select a.cardno,a.cardphyid,a.expiredate,a.status as cardstatus,a.trans_status as transstatus,a.userid,b.name as username,b.sex,b.idtype,b.idno,b.mobile as phone,c.cardno as bankcardno,a.lastsaved as updtime \n" +
                 "from tb_card a left join tb_person b on a.userid=b.userid left join tb_card c on a.userid=c.userid and a.cardphyid=c.cardphyid and c.cardtype='bankcard' \n" +
                 "where a.cardtype='citizencard' and a.lastsaved>:starttime and a.lastsaved<=:endtime order by a.lastsaved ")
         query.setParameter("starttime", startdate)
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
index da66271..0f6f5d6 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -33,6 +33,7 @@
 import org.springframework.web.bind.annotation.RequestMapping
 import org.springframework.web.bind.annotation.RestController
 import org.springframework.web.bind.annotation.RequestParam
+import org.springframework.web.multipart.MultipartFile
 import java.time.Duration
 import java.util.*
 
@@ -400,7 +401,7 @@
         }
         val exsitUser = mobileApiService.findUserById(card.userid)
         if (exsitUser != null) {
-            return JsonResult.error("该银行卡号已被绑定,如有疑问,请联系客服")
+            return JsonResult.error("该银行卡号已被绑定,若您本人绑定,请先解除绑定,若非本人,请联系客服")
         }
         //call api
         var resp = citizencardPayService.bindCard(cardno, name, idtype, idno, phone)
@@ -766,4 +767,89 @@
             JsonResult.error(resp.retmsg)
         }
     }
+
+    /**
+     *
+     * 解除银行协议
+     * */
+    @RequestMapping("/unsignbxy")
+    fun unSignbxy(): JsonResult {
+        val p = SecurityContextHolder.getContext().authentication
+        val user = mobileApiService.findUserById(p.name)
+                ?: return JsonResult.error("用户不存在,请注册")
+        var signed: String
+        if (!user.userid.isNullOrEmpty()) {
+            var card = mobileApiService.findCardByUserid(user.userid!!)
+                    ?: return JsonResult.error("银行卡不存在,不能解除代扣协议")
+            //call sign api
+            val person = userService.findOnePersonByUserid(card.userid)
+            var resp = citizencardPayService.signCard(card.cardno, person.name, person.idtype, person.idno, user.phone!!, YnrccUtil.TRANSTYPE_UNSIGNCARD)
+            if (resp.code != "0000") {
+                return JsonResult.error(resp.message)
+            }
+            card.signed = false
+            mobileApiService.saveCard(card)
+            signed = TradeDict.STATUS_NO
+        } else {
+            return JsonResult.error("未绑定银行卡,不能解除代扣协议")
+        }
+        return JsonResult.ok("ok")
+                .put("signed", signed)!!
+    }
+
+    /**
+     * 解除绑定
+     * */
+    @RequestMapping("/unbindcard")
+    fun unbindcard(paypwd: String): JsonResult {
+        val p = SecurityContextHolder.getContext().authentication
+        val user = mobileApiService.findUserById(p.name)
+                ?: return JsonResult.error("用户不存在,请注册")
+        if(user.paypwd.isNullOrEmpty()){
+            return JsonResult.error("支付密码未设置,请先设置")
+        }
+        val paypwdtimes = user.checkPaypwdtime()
+        if (paypwdtimes == -1) {
+            return JsonResult.error("支付密码错误次数过多,请30分钟后再试")
+        } else if (paypwdtimes == 1) {
+            mobileApiService.saveUser(user)
+        }
+        val encoder = BCryptPasswordEncoder()
+        if (!encoder.matches(paypwd, user.paypwd)) {
+            user.updatePaypwderror(false).also {
+                if (it) mobileApiService.saveUser(user)
+            }
+            return JsonResult.error("支付密码错误")
+        } else {
+            user.updatePaypwderror(true).also {
+                if (it) mobileApiService.saveUser(user)
+            }
+        }
+        var card = mobileApiService.findCardByUserid(user.userid!!)
+                ?: return JsonResult.error(-1, "银行卡未绑定,无需解绑")
+        card.signed = false
+        user.userid = null
+        mobileApiService.saveCard(card)
+        mobileApiService.saveUser(user)
+        return JsonResult.ok("OK")
+                ?.put("signed", TradeDict.STATUS_NO)!!
+    }
+
+    /**
+     * 上传头像
+     * */
+    @RequestMapping("/uploadphoto")
+    fun uploadPhoto(file: MultipartFile): JsonResult {
+        val p = SecurityContextHolder.getContext().authentication
+        val user = mobileApiService.findUserById(p.name)
+                ?: return JsonResult.error("用户不存在,请注册")
+        /**
+         * TODO
+         * 1.已有头像更新
+         * 2.没有头像上传
+         * 3.返回图片ID
+         *
+        */
+        return JsonResult.ok("OK")
+    }
 }
\ No newline at end of file