手机绑卡流程修改
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCard.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCard.java
index dcf8f49..41dba29 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCard.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCard.java
@@ -36,7 +36,7 @@
   @Column(name = "SIGNED", nullable = false, length = 10)
   private Boolean signed = false; //签约状态
 
-  @Column(name = "USERID", nullable = false, length = 20)
+  @Column(name = "USERID", nullable = false, length = 32)
   private String userid;
 
   @Column(name = "LASTSAVED", length = 20)
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/StringUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/StringUtil.java
index 20756cc..d5bebe9 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/StringUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/StringUtil.java
@@ -151,4 +151,6 @@
   public static String nameReplace(String s){
     return  s.replaceAll("([\\d\\D]{1})(.*)", "$1**");
   }
+
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
index d193d3a..57f5b3b 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
@@ -6,10 +6,14 @@
    * normal -- 正常
    * closed -- 注销
    * locked -- 锁定、冻结
+   * frozen -- 冻结
+   * lost -- 挂失
    */
   public static final String STATUS_NORMAL = "normal";
   public static final String STATUS_CLOSED = "closed";
   public static final String STATUS_LOCKED = "locked";
+  public static final String STATUS_LOST = "lost";
+  public static final String STATUS_FROZEN = "frozen";
 
   public static final String STATUS_YES = "yes";
   public static final String STATUS_NO = "no";
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
index bd43e6f..0f66df7 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/AuthLoginHandler.kt
@@ -12,6 +12,7 @@
 import com.supwisdom.dlpay.mobile.dao.MobileUserDao
 import com.supwisdom.dlpay.mobile.domain.TBMobileUser
 import com.supwisdom.dlpay.mobile.exception.UserLoginFailException
+import com.supwisdom.dlpay.mobile.service.MobileApiService
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.http.HttpStatus
 import org.springframework.security.authentication.BadCredentialsException
@@ -29,7 +30,7 @@
 @Component("authLoginSuccessHandler")
 class AuthLoginSuccessHandler : SimpleUrlAuthenticationSuccessHandler() {
     @Autowired
-    lateinit var mobileUserDao: MobileUserDao
+    lateinit var mobileApiService: MobileApiService
     @Autowired
     lateinit var objectMapper: ObjectMapper
     @Autowired
@@ -45,7 +46,7 @@
     override fun onAuthenticationSuccess(request: HttpServletRequest, response: HttpServletResponse, authentication: Authentication) {
         logger.error(request.getParameter("platform"))
         val temp = authentication.principal as TBMobileUser
-        val user = mobileUserDao.findByPhone(temp.phone)
+        val user = mobileApiService.findUserByPhone(temp.phone)
         val exp = systemUtilService.getSysparaValueAsInt(SysparaUtil.MOBILE_LOGIN_EXPIRE_IN_SECONDS,60*60*24*3)
         jwtConfig.expiration = exp.toLong()
         if (user != null) {
@@ -73,17 +74,21 @@
             }
             user.lastlogin = DateUtil.getNow()
             user.jti = jwt.jti
-            mobileUserDao.save(user)
+            mobileApiService.saveUser(user)
             var payseted = false
             if(!user.paypwd.isNullOrEmpty()){
                 payseted = true
             }
             var name = ""
+            var signed=""
             if (!user.userid.isNullOrEmpty()) {
                 val person = userService.findOnePersonByUserid(user.userid!!)
+                var card = mobileApiService.findCardByUserid(user.userid!!)
                 name = person.name
+                if(card!=null&&card.signed){
+                    signed = TradeDict.STATUS_YES
+                }
             }
-
             response.status = HttpStatus.OK.value()
             response.contentType = "application/json;charset=UTF-8"
             response.writer.write(objectMapper.writeValueAsString(JsonResult.ok()
@@ -94,7 +99,7 @@
                     ?.put("name", name)
                     ?.put("phone", StringUtil.phoneReplace(user.phone))
                     ?.put("paypwdset",payseted)
-                    ?.put("signed", if (user.issigned.isNullOrEmpty()) "" else user.issigned)
+                    ?.put("signed", signed)
                     ?.put("userid",if(user.userid.isNullOrEmpty()) "" else user.userid)))
         } else {
             throw UserLoginFailException("登录错误")
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 dc9457e..2f77261 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -1,9 +1,8 @@
 package com.supwisdom.dlpay.mobile
 
 import com.supwisdom.dlpay.api.bean.JsonResult
-import com.supwisdom.dlpay.api.dao.PersonDao
-import com.supwisdom.dlpay.api.domain.TPersonIdentity
 import com.supwisdom.dlpay.api.service.UserService
+import com.supwisdom.dlpay.api.util.MobileNumberCheck
 import com.supwisdom.dlpay.framework.core.JwtConfig
 import com.supwisdom.dlpay.framework.core.JwtTokenUtil
 import com.supwisdom.dlpay.framework.domain.JwtRedis
@@ -65,8 +64,8 @@
      * */
     @RequestMapping("/code")
     fun code(@RequestParam phone: String, @RequestParam type: String?): JsonResult {
-        if (phone.isEmpty() || phone.length != 11 || !StringUtil.isMobile(phone)) {
-            return JsonResult.error("手机号有误")
+        if (phone.isEmpty() || !MobileNumberCheck.isPhone(phone)) {
+            return JsonResult.error("手机号不合法")
         }
         val user = mobileApiService.findUserByPhone(phone)
         if (type.isNullOrEmpty() || "new" == type) {
@@ -187,13 +186,20 @@
         if (!user.paypwd.isNullOrEmpty()) {
             payseted = true
         }
+        var signed=""
+        if(!user.userid.isNullOrEmpty()){
+            val card = mobileApiService.findCardByUserid(user.userid!!)
+            if(card!=null&&card.signed){
+                signed = TradeDict.STATUS_YES
+            }
+        }
         return JsonResult.ok("OK").put("token", token.jwtToken)
                 ?.put("userid", if (user.userid.isNullOrEmpty()) "" else user.userid)
                 ?.put("expire", token.expiration.valueInMillis)
                 ?.put("now", System.currentTimeMillis())
                 ?.put("phone", StringUtil.phoneReplace(user.phone))
                 ?.put("paypwdset", payseted)
-                ?.put("signed", if (user.issigned.isNullOrEmpty()) "" else user.issigned)
+                ?.put("signed", signed)
                 ?.put("tenantid", "mobile")!!
     }
 }
@@ -208,8 +214,6 @@
     lateinit var userService: UserService
     @Autowired
     lateinit var redisTemplate: RedisTemplate<String, String>
-    @Autowired
-    lateinit var personDao: PersonDao
 
     /**
      * 用户信息
@@ -265,7 +269,7 @@
      * 绑卡
      * */
     @RequestMapping("/bindcard")
-    fun bindcard(card: String, name: String, code: String): JsonResult {
+    fun bindcard(cardno: String, name: String, code: String): JsonResult {
         val p = SecurityContextHolder.getContext().authentication
         val user = mobileApiService.findUserById(p.name)
                 ?: return JsonResult.error("用户不存在,请注册")
@@ -275,34 +279,38 @@
             if (temp != code) {
                 return JsonResult.error("验证码错误")
             }
-            if (user.userid.isNullOrEmpty()) {
-                val identy: TPersonIdentity? = userService.findPersonIdentity(card)
-                        ?: return JsonResult.error("银行卡号有误")
-                if (identy!!.person == null || identy.status != TradeDict.STATUS_NORMAL) {
-                    return JsonResult.error("银行卡号信息有误")
-                }
-                if (identy.person.name != name) {
-                    return JsonResult.error("姓名有误")
-                }
-                val exsitUser = mobileApiService.findUserById(identy.person.userid)
-                if (exsitUser != null) {
-                    return JsonResult.error("该银行卡号已被绑定,如有疑问,请联系客服")
-                }
-                user.bindtime = DateUtil.getNow()
-                user.userid = identy.person.userid
-                mobileApiService.saveUser(user)
-                redisTemplate.delete(phone)
-                var payseted = false
-                if (!user.paypwd.isNullOrEmpty()) {
-                    payseted = true
-                }
-                return JsonResult.ok("OK").put("userid", user.userid)
-                        ?.put("paypwdset", payseted)
-                        ?.put("signed", if (user.issigned.isNullOrEmpty()) "" else user.issigned)!!
-            } else {
-                return JsonResult.error(-1, "用户已绑定银行卡")
-                        .put("userid", if (user.userid.isNullOrEmpty()) "" else user.userid)!!
+            val card = mobileApiService.findCardByNo(cardno)
+                    ?: return JsonResult.error("银行卡号有误")
+            if (card.userid.isNullOrEmpty() || card.status != TradeDict.STATUS_NORMAL) {
+                return JsonResult.error("银行卡号信息有误")
             }
+            if (card.transStatus==TradeDict.STATUS_NORMAL) {
+                return JsonResult.error("该卡片非正常卡,无法绑定,请联系客服人员,更新卡状态")
+            }
+            val person = userService.findOnePersonByUserid(card.userid)
+            if(name!=person.name){
+                return JsonResult.error("姓名错误")
+            }
+            val exsitUser = mobileApiService.findUserById(card.userid)
+            if (exsitUser != null) {
+                return JsonResult.error("该银行卡号已被绑定,如有疑问,请联系客服")
+            }
+            user.bindtime = DateUtil.getNow()
+            user.userid = card.userid
+            mobileApiService.saveUser(user)
+            redisTemplate.delete(phone)
+            var payseted = false
+            if (!user.paypwd.isNullOrEmpty()) {
+                payseted = true
+            }
+            var signed=""
+            if(card.signed){
+                signed = TradeDict.STATUS_YES
+            }
+            return JsonResult.ok("OK").put("userid", user.userid)
+                    ?.put("paypwdset", payseted)
+                    ?.put("signed", signed)!!
+
         } else {
             return JsonResult.error(-1, "验证码无效或已过期,请重新获取")
         }
@@ -338,21 +346,21 @@
                     if (oldpwd.isNullOrEmpty()) {
                         return JsonResult.error("原支付密码错误")
                     }
-                    if (user.paypwderror >= 5 && (System.currentTimeMillis() - user.paypwderrortime!!) < 1000 * 60 * 30) {
+                    val paypwdtimes = user.checkPaypwdtime()
+                    if(paypwdtimes==-1){
                         return JsonResult.error("密码错误次数过多,请30分钟后再试")
-                    } else if (user.paypwderror >= 5 && (System.currentTimeMillis() - user.paypwderrortime!!) > 1000 * 60 * 30) {
-                        //更新时间
-                        user.paypwderror = 0
-                        user.paypwderrortime = null
-                    }
-                    if (!encoder.matches(oldpwd, user.paypwd)) {
-                        if (user.paypwderror == 0) {
-                            user.paypwderror = 0
-                            user.paypwderrortime = System.currentTimeMillis()
-                        }
-                        user.paypwderror += 1
+                    }else if(paypwdtimes==1){
                         mobileApiService.saveUser(user)
+                    }
+                    if(!encoder.matches(oldpwd, user.paypwd)){
+                        user.updatePaypwderror(false).also {
+                            if(it) mobileApiService.saveUser(user)
+                        }
                         return JsonResult.error("原支付密码错误")
+                    }else{
+                        user.updatePaypwderror(true).also {
+                            if(it) mobileApiService.saveUser(user)
+                        }
                     }
                     user.paypwd = encoder.encode(pwd)
                     mobileApiService.saveUser(user)
@@ -385,7 +393,17 @@
     fun xieyi(): JsonResult {
         val page = mobileApiService.findPageById(ConstantUtil.PAGE_BANKXIEYI)
         if (page != null) {
-            return JsonResult.ok("OK").put("page", page.pageContent)!!
+            val p = SecurityContextHolder.getContext().authentication
+            val user = mobileApiService.findUserById(p.name)
+                    ?: return JsonResult.error("用户不存在,请注册")
+            var signed=""
+            if(!user.userid.isNullOrEmpty()){
+                var card = mobileApiService.findCardByUserid(user.userid!!) ?: return JsonResult.error("卡片不存在,请重新绑定")
+                if(card.signed){
+                    signed = TradeDict.STATUS_YES
+                }
+            }
+            return JsonResult.ok("OK").put("page", page.pageContent)?.put("signed",signed)!!
         }
         return JsonResult.error("页面未配置")
     }
@@ -401,10 +419,19 @@
                 ?: return JsonResult.error("用户不存在,请注册")
         user.issigned = TradeDict.STATUS_YES
         user.signedtime = DateUtil.getNow()
+        var signed=""
+        if(!user.userid.isNullOrEmpty()){
+            var card = mobileApiService.findCardByUserid(user.userid!!) ?: return JsonResult.error("卡片不存在,请重新绑定")
+            if(card.signed){
+                signed = TradeDict.STATUS_YES
+            }
+            card.signed = true
+            mobileApiService.saveCard(card)
+        }
         mobileApiService.saveUser(user)
         //TODO 调用第三方接口签约
         return JsonResult.ok("ok")
-                .put("signed", if (user.issigned.isNullOrEmpty()) "" else user.issigned)!!
+                .put("signed", signed)!!
     }
 
     /**
@@ -445,6 +472,17 @@
             payseted = true
         }
         val person = userService.findOnePersonByUserid(user.userid!!)
+        val card = mobileApiService.findCardByUserid(user.userid!!)
+        var needrebind = false
+        var signed=""
+        if(card==null){
+            //卡片已补办,或绑定失败,需要重新绑定
+            needrebind = true
+        }else{
+            if(card.signed){
+                signed = TradeDict.STATUS_YES
+            }
+        }
         var name = person.name
         val page = userService.findPersondtlByUserid(user.userid!!, no)
         return JsonResult.ok("OK").put("page", page)
@@ -454,7 +492,8 @@
                 ?.put("amount", amount)
                 ?.put("paypwdset", payseted)
                 ?.put("name", name)
-                ?.put("signed", if (user.issigned.isNullOrEmpty()) "" else user.issigned)
+                ?.put("needrebind",needrebind)
+                ?.put("signed", signed)
                 ?.put("userid", if (user.userid.isNullOrEmpty()) "" else user.userid)!!.put("t", t)!!
     }
 
@@ -487,24 +526,51 @@
         if (newpwd.isEmpty() || newpwd.length < 6) {
             return JsonResult.error("请重新设置密码,密码不能小于6位字符")
         }
-        if (user.loginpwderror > 5) {
-            return JsonResult.error(-1, "原密码错误次数过多,将退出系统,请重新登录系统或点击忘记密码功能找回密码")
+        val pwdtimes = user.checkLoginpwdtime()
+        if(pwdtimes==-1){
+            return JsonResult.error(-1,"原密码错误次数过多,将退出系统,请重新登录系统或点击忘记密码功能找回密码")
+        }else if(pwdtimes==1){
+            mobileApiService.saveUser(user)
         }
         val encoder = BCryptPasswordEncoder()
-        if (!encoder.matches(oldpwd, user.loginpwd)) {
-            user.loginpwderror += 1
-            mobileApiService.saveUser(user)
+        if(!encoder.matches(oldpwd, user.loginpwd)){
+            user.updateLoginpwderror(false).also {
+                if(it) mobileApiService.saveUser(user)
+            }
             return JsonResult.error("原密码错误")
-        }
-        if (user.loginpwderror > 0) {
-            user.loginpwderror = 0
-            user.loginpwderrortime = null
+        }else{
+            user.updateLoginpwderror(true)
         }
         user.loginpwd = encoder.encode(newpwd)
         mobileApiService.saveUser(user)
         return JsonResult.ok("密码修改成功")
     }
-
+    /**
+     *
+     * 市民卡挂失
+     * */
+    @RequestMapping("/cardinfor")
+    fun cardinfor(): JsonResult {
+        val p = SecurityContextHolder.getContext().authentication
+        val user = mobileApiService.findUserById(p.name)
+                ?: return JsonResult.error("用户不存在,请注册")
+        if(user.userid.isNullOrEmpty()){
+            return JsonResult.error(-1,"银行卡未绑定,请先绑定")
+        }
+        val person = userService.findOnePersonByUserid(user.userid!!)
+        val card = mobileApiService.findCardByUserid(user.userid!!) ?: return JsonResult.error(-1,"银行卡未绑定,请先绑定")
+        var status=""
+        //normal/loss/frozen/locked
+        when(card.transStatus){
+            TradeDict.STATUS_NORMAL-> status = "正常"
+            TradeDict.STATUS_LOST-> status = "已挂失"
+            TradeDict.STATUS_LOCKED-> status = "已锁定"
+            TradeDict.STATUS_FROZEN-> status = "已冻结"
+        }
+        return JsonResult.ok("ok").put("name",person.name)
+                ?.put("cardno",card.cardno)
+                ?.put("cardstatus",status)!!
+    }
     /**
      *
      * 市民卡挂失
@@ -512,9 +578,31 @@
     @RequestMapping("/cardlost")
     fun cardlost(paypwd: String): JsonResult {
         val p = SecurityContextHolder.getContext().authentication
-        mobileApiService.findUserById(p.name)
+        val user = mobileApiService.findUserById(p.name)
                 ?: return JsonResult.error("用户不存在,请注册")
-        //TODO cardlost
+        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,"银行卡未绑定,请先绑定")
+        if(card.transStatus!=TradeDict.STATUS_NORMAL){
+            return JsonResult.error("卡状态非正常,不能挂失")
+        }
+        card.transStatus=TradeDict.STATUS_LOST
+        mobileApiService.saveCard(card)
         return JsonResult.ok("ok")
     }
 
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 285546a..68b9155 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
@@ -1,5 +1,6 @@
 package com.supwisdom.dlpay.mobile.domain
 
+import com.supwisdom.dlpay.api.bean.JsonResult
 import com.supwisdom.dlpay.framework.util.TradeDict
 import org.hibernate.annotations.GenericGenerator
 import org.springframework.security.core.GrantedAuthority
@@ -36,6 +37,7 @@
     override fun isAccountNonLocked(): Boolean {
         return TradeDict.STATUS_LOCKED != this.status
     }
+
     @Transient
     var auths: Collection<GrantedAuthority>? = null
 
@@ -158,4 +160,65 @@
      * */
     @Column(name = "ulogo", length = 100)
     var ulogo: String? = null
+
+
+    fun checkLoginpwdtime():Int{
+        if (this.loginpwderror >= 5 && (System.currentTimeMillis() - this.loginpwderrortime!!) < 1000 * 60 * 30) {
+            return -1
+        } else if (this.loginpwderror >= 5 && (System.currentTimeMillis() - this.loginpwderrortime!!) > 1000 * 60 * 30) {
+            //更新时间
+            this.loginpwderror = 0
+            this.loginpwderrortime = null
+            return 1
+        }
+        return 0
+    }
+
+    fun updateLoginpwderror(ok: Boolean): Boolean {
+        return if (ok) {
+            if (this.loginpwderror > 0) {
+                this.loginpwderror = 0
+                this.loginpwderrortime = null
+                true
+            } else {
+                false
+            }
+        } else {
+            if (this.loginpwderror == 0) {
+                this.loginpwderrortime = System.currentTimeMillis()
+            }
+            this.loginpwderror += 1
+            true
+        }
+    }
+
+    fun checkPaypwdtime():Int{
+        if (this.paypwderror >= 5 && (System.currentTimeMillis() - this.paypwderrortime!!) < 1000 * 60 * 30) {
+            return -1
+        } else if (this.paypwderror >= 5 && (System.currentTimeMillis() - this.paypwderrortime!!) > 1000 * 60 * 30) {
+            //更新时间
+            this.paypwderror = 0
+            this.paypwderrortime = null
+            return 1
+        }
+        return 0
+    }
+
+    fun updatePaypwderror(ok: Boolean): Boolean {
+        return if (ok) {
+            if (this.paypwderror > 0) {
+                this.paypwderror = 0
+                this.paypwderrortime = null
+                true
+            } else {
+                false
+            }
+        } else {
+            if (this.paypwderror == 0) {
+                this.paypwderrortime = System.currentTimeMillis()
+            }
+            this.paypwderror += 1
+            true
+        }
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileApiService.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileApiService.kt
index e5eaa5f..6b28b01 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileApiService.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/MobileApiService.kt
@@ -16,4 +16,6 @@
     fun findCardByNo(cardno: String):TCard?
 
     fun findCardByUserid(userid :String) :TCard?
+
+    fun saveCard(card:TCard):TCard
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
index fe600e4..38411cb 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
@@ -49,4 +49,8 @@
     override fun findCardByUserid(userid: String): TCard? {
         return cardDao.findCardByUseridAndCardtype(userid,ConstantUtil.CARDTYPE_CITIZENCARD)
     }
+
+    override fun saveCard(card: TCard): TCard {
+        return cardDao.save(card)
+    }
 }
\ No newline at end of file