TCard定义和同步
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java
index 91c7bac..174a3a3 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java
@@ -3,10 +3,7 @@
 import com.supwisdom.dlpay.api.domain.TAccount;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Lock;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.jpa.repository.QueryHints;
+import org.springframework.data.jpa.repository.*;
 import org.springframework.data.repository.query.Param;
 
 import javax.persistence.LockModeType;
@@ -39,4 +36,8 @@
 
   @Query("select a from TAccount a where a.person.name like CONCAT('%',:accname,'%') ")
   Page<TAccount> findAllByAccnameContaining(@Param("accname") String accname, Pageable pageable);
+
+  @Modifying
+  @Query("update TAccount set accname=?1 where userid=?2")
+  void updateAccnameByUserid(String accname, String userid);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/CardDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/CardDao.java
new file mode 100644
index 0000000..74473d8
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/CardDao.java
@@ -0,0 +1,16 @@
+package com.supwisdom.dlpay.api.dao;
+
+import com.supwisdom.dlpay.api.domain.TCard;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+public interface CardDao extends JpaRepository<TCard, String> {
+
+  @Query("from TCard t where t.cardno=?1 and t.cardtype=?2")
+  TCard findCardByCardnoAndCardtype(String cardno, String cardtype);
+
+  @Modifying
+  @Query("update TCard set status='closed' where userid=?1 and cardtype='bankcard' ")
+  void closedBankcardStatusByUserid(String userid);
+}
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
new file mode 100644
index 0000000..dcf8f49
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCard.java
@@ -0,0 +1,151 @@
+package com.supwisdom.dlpay.api.domain;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+
+@Entity
+@Table(name = "TB_CARD",
+    indexes = {@Index(name = "tb_card_uk", columnList = "cardno,cardtype", unique = true)})
+public class TCard {
+  @Id
+  @GenericGenerator(name = "idGenerator", strategy = "uuid")
+  @GeneratedValue(generator = "idGenerator")
+  @Column(name = "ID", nullable = false, length = 32)
+  private String id;
+
+  @Column(name = "CARDNO", nullable = false, length = 32)
+  private String cardno;
+
+  @Column(name = "CARDTYPE", nullable = false, length = 20)
+  private String cardtype;
+
+  @Column(name = "CARDPHYID", length = 20)
+  private String cardphyid;
+
+  @Column(name = "STATUS", nullable = false, length = 20)
+  private String status; //normal/closed
+
+  @Column(name = "TRANS_STATUS", nullable = false, length = 20)
+  private String transStatus; //normal/loss/frozen/locked
+
+  @Column(name = "EXPIREDATE", length = 20)
+  private String expiredate;
+
+  @Column(name = "SIGNED", nullable = false, length = 10)
+  private Boolean signed = false; //签约状态
+
+  @Column(name = "USERID", nullable = false, length = 20)
+  private String userid;
+
+  @Column(name = "LASTSAVED", length = 20)
+  private String lastsaved;
+
+  @Column(name = "tenantid", length = 20)
+  @NotNull
+  private String tenantid = "";
+
+  public TCard() {
+  }
+
+  public TCard(String cardno, String cardtype, String cardphyid, String status, String transStatus, String expiredate, Boolean signed, String userid, String lastsaved) {
+    this.cardno = cardno;
+    this.cardtype = cardtype;
+    this.cardphyid = cardphyid;
+    this.status = status;
+    this.transStatus = transStatus;
+    this.expiredate = expiredate;
+    this.signed = signed;
+    this.userid = userid;
+    this.lastsaved = lastsaved;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getCardno() {
+    return cardno;
+  }
+
+  public void setCardno(String cardno) {
+    this.cardno = cardno;
+  }
+
+  public String getCardtype() {
+    return cardtype;
+  }
+
+  public void setCardtype(String cardtype) {
+    this.cardtype = cardtype;
+  }
+
+  public String getCardphyid() {
+    return cardphyid;
+  }
+
+  public void setCardphyid(String cardphyid) {
+    this.cardphyid = cardphyid;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public String getTransStatus() {
+    return transStatus;
+  }
+
+  public void setTransStatus(String transStatus) {
+    this.transStatus = transStatus;
+  }
+
+  public String getExpiredate() {
+    return expiredate;
+  }
+
+  public void setExpiredate(String expiredate) {
+    this.expiredate = expiredate;
+  }
+
+  public Boolean getSigned() {
+    return signed;
+  }
+
+  public void setSigned(Boolean signed) {
+    this.signed = signed;
+  }
+
+  public String getUserid() {
+    return userid;
+  }
+
+  public void setUserid(String userid) {
+    this.userid = userid;
+  }
+
+  public String getLastsaved() {
+    return lastsaved;
+  }
+
+  public void setLastsaved(String lastsaved) {
+    this.lastsaved = lastsaved;
+  }
+
+  public String getTenantid() {
+    return tenantid;
+  }
+
+  public void setTenantid(String tenantid) {
+    this.tenantid = tenantid;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/XssHttpServletRequestWrapper.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/XssHttpServletRequestWrapper.java
index ddc4d15..ba7ac78 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/XssHttpServletRequestWrapper.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/XssHttpServletRequestWrapper.java
@@ -110,6 +110,7 @@
     value = value.replaceAll("'", "& #39;");
     value = value.replaceAll("eval\\((.*)\\)", "");
     value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
+//    value = value.replaceAll("'", "‘").replaceAll(";", ";").replaceAll("=", "").replaceAll("%", "").replaceAll("\\+", "");
     value = value.replaceAll("script", "");
     value = cleanSqlKeyWords(value);
     return value;
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java
index 3ccb2a7..95c4a86 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/SysparaUtil.java
@@ -11,12 +11,15 @@
 
 
   public static final int SYSPARAID_NO1 = 1; //系统默认最大余额限制的ID
-  public static final int SYSPARAID_NO2 = 2; //paraid=2
+  public static final int SYSPARAID_NO2 = 2; //默认免密额度
+  public static final int SYSPARAID_NO3 = 3; //默认日累计额度
 
   public static final int SYSPARAID_NO2019 = 2019; //与卡管系统对接的应用ID
   public static final int SYSPARAID_NO2020 = 2020; //与卡管系统对接的应用appkey
   public static final int SYSPARAID_NO2021 = 2021; //与卡管系统对接的业务参数deskey
 
   public static final double SYSPARA_NO1_DEFAULT = 10000.0; // 系统默认最大余额限制
+  public static final double SYSPARA_NO2_DEFAULT = 100.0; // 系统默认最大余额限制
+  public static final double SYSPARA_NO3_DEFAULT = 200.0; // 系统默认最大余额限制
 
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
index a525547..02afd88 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
@@ -33,4 +33,11 @@
    * */
   public static final int DICTTYPE_NO1 = 1; //冲正状态字典
   public static final int DICTTYPE_NO2 = 2; //流水状态字典
+
+
+  /**
+   * 卡库同步的Cardtype
+   * */
+  public static final String CARDTYPE_CITIZENCARD = "citizencard";
+  public static final String CARDTYPE_BANKCARD = "bankcard";
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
index 564689e..d373525 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt
@@ -66,6 +66,18 @@
     var idno: String = ""
     var mobile: String? = null
     var email: String? = null
+
+    fun checkParam(): Boolean {
+        if (StringUtil.isEmpty(idtype) || StringUtil.isEmpty(idno) || StringUtil.isEmpty(username)) throw RequestParamCheckException("用户明细数据关键字段为空")
+        if (StringUtil.isEmpty(cardno) || StringUtil.isEmpty(cardphyid) || StringUtil.isEmpty(expiredate) || StringUtil.isEmpty(cardstatus)) throw RequestParamCheckException("卡片明细数据关键字段为空")
+        return true
+    }
+}
+
+class DaliDatasyncErrorDetail{
+    var cardno:String=""
+    var errcode:String=""
+    var errmsg:String=""
 }
 
 
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 3f909c5..dea3d29 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
@@ -1,7 +1,10 @@
 package com.supwisdom.dlpay.api.controller
 
+import com.google.gson.Gson
+import com.supwisdom.dlpay.api.bean.DaliDatasyncErrorDetail
 import com.supwisdom.dlpay.api.bean.DaliDatasyncParam
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
+import com.supwisdom.dlpay.api.service.DaliDatasyncService
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.util.StringUtil
@@ -14,6 +17,8 @@
 class DaliDatasyncApiController {
     @Autowired
     lateinit var systemUtilService: SystemUtilService
+    @Autowired
+    lateinit var daliDatasyncService: DaliDatasyncService
 
     /**
      * ============================================================================
@@ -45,14 +50,34 @@
                         .fail(2002, "请求参数错误[数据条数不匹配]"))
             }
 
-            datalist.forEach {
-                TODO("更新数据逻辑")
+            var errlist = ArrayList<DaliDatasyncErrorDetail>(0)
+
+            datalist.forEach {detail->
+                try {
+                    detail.checkParam()
+                    daliDatasyncService.doUpdateUserInfos(detail)
+                } catch (e1: RequestParamCheckException) {
+                    errlist.add(DaliDatasyncErrorDetail().apply {
+                        cardno = detail.cardno
+                        errcode = "2001"
+                        errmsg = e1.message?:"明细数据关键字段为空"
+                    })
+                }catch (e2: Exception){
+                    errlist.add(DaliDatasyncErrorDetail().apply {
+                        cardno = detail.cardno
+                        errcode = "3000"
+                        errmsg = e2.message?:"明细处理错误"
+                    })
+                }
             }
 
-            return return ResponseEntity.ok(mapOf("retcode" to "0000", "retmsg" to "SUCCESS"))
+            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)))
+            }
         } catch (ex: RequestParamCheckException) {
             return ResponseEntity.ok(ResponseBodyBuilder.create()
-                    .fail(ex.errCode, ex.message ?: "请求参数错误"))
+                    .fail(2001, ex.message ?: "请求参数错误"))
         } catch (e: Exception) {
             e.printStackTrace()
             return ResponseEntity.ok(ResponseBodyBuilder.create()
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/dali_datasync_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/dali_datasync_service.kt
new file mode 100644
index 0000000..b85342f
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/dali_datasync_service.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.dlpay.api.service
+
+import com.supwisdom.dlpay.api.bean.DaliDatasyncDetail
+import org.springframework.transaction.annotation.Propagation
+import org.springframework.transaction.annotation.Transactional
+
+interface DaliDatasyncService{
+
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = arrayOf(Exception::class))
+    fun doUpdateUserInfos(bean: DaliDatasyncDetail): Boolean
+
+}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/dali_datasync_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/dali_datasync_service_impl.kt
new file mode 100644
index 0000000..c93f514
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/dali_datasync_service_impl.kt
@@ -0,0 +1,134 @@
+package com.supwisdom.dlpay.api.service.impl
+
+import com.supwisdom.dlpay.api.bean.DaliDatasyncDetail
+import com.supwisdom.dlpay.api.dao.AccountDao
+import com.supwisdom.dlpay.api.dao.CardDao
+import com.supwisdom.dlpay.api.dao.PersonDao
+import com.supwisdom.dlpay.api.domain.TAccount
+import com.supwisdom.dlpay.api.domain.TCard
+import com.supwisdom.dlpay.api.domain.TPerson
+import com.supwisdom.dlpay.api.service.DaliDatasyncService
+import com.supwisdom.dlpay.exception.TransactionProcessException
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.tenant.TenantContext
+import com.supwisdom.dlpay.framework.util.*
+import com.supwisdom.dlpay.util.ConstantUtil
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+
+@Service
+class DaliDatasyncServiceImpl : DaliDatasyncService {
+    @Autowired
+    lateinit var accountDao: AccountDao
+    @Autowired
+    lateinit var personDao: PersonDao
+    @Autowired
+    lateinit var cardDao: CardDao
+    @Autowired
+    lateinit var systemUtilService: SystemUtilService
+
+    override fun doUpdateUserInfos(bean: DaliDatasyncDetail): Boolean {
+        val maxbal = systemUtilService.getSysparaValueAsDouble(SysparaUtil.SYSPARAID_NO1, SysparaUtil.SYSPARA_NO1_DEFAULT)
+        val lowfreeLimit = systemUtilService.getSysparaValueAsDouble(SysparaUtil.SYSPARAID_NO2, SysparaUtil.SYSPARA_NO2_DEFAULT)
+        val daylimit = systemUtilService.getSysparaValueAsDouble(SysparaUtil.SYSPARAID_NO3, SysparaUtil.SYSPARA_NO3_DEFAULT)
+
+        val systime = systemUtilService.sysdatetime
+        var person = personDao.findByIdentity(bean.idtype.trim(), bean.idno.trim())
+        if (null != person) {
+            if (person.name != bean.username) {
+                person.name = bean.username
+                person.lastsaved = systime.hostdatetime
+                person = personDao.save(person)
+                accountDao.updateAccnameByUserid(person.name, person.userid)
+            }
+        } else {
+            person = TPerson().apply {
+                name = bean.username
+                status = TradeDict.STATUS_NORMAL
+                idtype = bean.idtype.trim()
+                idno = bean.idno.trim()
+                email = bean.email
+                mobile = bean.mobile
+                lastsaved = systime.hostdatetime
+            }
+            person.tenantid = TenantContext.getTenantSchema()
+            person = personDao.save(person)
+
+            var account = TAccount().apply {
+                accname = person.name
+                subjno = Subject.SUBJNO_PERSONAL_DEPOSIT
+                userid = person.userid
+                transStatus = person.status
+                balance = 0.00
+                availbal = 0.00
+                frozebal = 0.00
+                lowfreeFlag = false
+                this.lowfreeLimit = lowfreeLimit
+                this.daylimit = daylimit
+                this.maxbal = maxbal
+                lasttranstime = systime.sysdate
+                lastdayTransamt = 0.00
+                lastdayDpsamt = 0.00
+                opendate = systime.hostdate
+            }
+            account.generateTac()
+            account.tenantid = TenantContext.getTenantSchema()
+            accountDao.save(account)
+        }
+
+        var cityCard = cardDao.findCardByCardnoAndCardtype(bean.cardno.trim(), ConstantUtil.CARDTYPE_CITIZENCARD)
+        if (null != cityCard) {
+            //仅修改有效期和状态
+            if (cityCard.expiredate != bean.expiredate.trim()) {
+                cityCard.expiredate = bean.expiredate.trim()
+            }
+            //fixme: bean.cardstatus 判断修改状态
+
+            cardDao.save(cityCard)
+        } else {
+            cityCard = TCard().apply {
+                cardno = bean.cardno.trim()
+                cardtype = ConstantUtil.CARDTYPE_CITIZENCARD
+                cardphyid = bean.cardphyid.trim()
+                status = TradeDict.STATUS_NORMAL // fixme: bean.cardstatus 判断
+                transStatus = TradeDict.STATUS_NORMAL
+                expiredate = bean.expiredate.trim()
+                signed = false
+                userid = person.userid
+                lastsaved = systime.hostdatetime
+            }
+            cityCard.tenantid = TenantContext.getTenantSchema()
+            cardDao.save(cityCard)
+        }
+
+        if (!StringUtil.isEmpty(bean.bankcardno)) {
+            var bankCard = cardDao.findCardByCardnoAndCardtype(bean.bankcardno!!.trim(), ConstantUtil.CARDTYPE_BANKCARD)
+            if (null == bankCard) {
+                bankCard = TCard().apply {
+                    cardno = bean.bankcardno!!.trim()
+                    cardtype = ConstantUtil.CARDTYPE_BANKCARD
+                    cardphyid = ""
+                    status = TradeDict.STATUS_NORMAL // fixme: bean.cardstatus 判断
+                    transStatus = TradeDict.STATUS_NORMAL
+                    expiredate = "21991231"
+                    signed = false
+                    userid = person.userid
+                    lastsaved = systime.hostdatetime
+                }
+                cardDao.closedBankcardStatusByUserid(bankCard.userid)  //注销其他银行卡
+                bankCard.tenantid = TenantContext.getTenantSchema()
+                cardDao.save(bankCard) //绑定新的银行卡
+
+            } else {
+                if (bankCard.userid != person.userid) {
+                    throw TransactionProcessException(3000, "银行卡已被人绑定")
+                }
+            }
+        }
+
+        return true
+    }
+
+
+
+}
\ No newline at end of file