Merge tag '1.0.27' into develop

市民卡信息新增公交卡字段
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/BindCardParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/BindCardParam.java
new file mode 100644
index 0000000..92428f0
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/BindCardParam.java
@@ -0,0 +1,34 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+
+@Getter
+@Setter
+public class BindCardParam extends APIRequestParam {
+  @Sign
+  @NotEmpty(message = "卡号不能为空")
+  private String cardno;
+  @Sign
+  @NotEmpty(message = "姓名不能为空")
+  private String name;
+  @Sign
+  @NotEmpty(message = "证件类型不能为空")
+  private String idtype;
+  @Sign
+  @NotEmpty(message = "证件号不能为空")
+  private String idno;
+  @Sign
+  @NotEmpty(message = "手机号不能为空")
+  private String phone;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodeParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodeParam.java
new file mode 100644
index 0000000..cca7278
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodeParam.java
@@ -0,0 +1,31 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+
+@Getter
+@Setter
+public class QrcodeParam extends APIRequestParam {
+  @Sign
+  @NotEmpty(message = "用户id不能为空")
+  private String userid;
+  @Sign
+  @NotEmpty(message = "手机用户id不能为空")
+  private String uid;
+  @Sign
+  @NotEmpty(message = "secertkey不能为空")
+  private String secertkey;
+  @Sign
+  @NotEmpty(message = "rsapublic不能为空")
+  private String rsapublic;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
\ No newline at end of file
diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java
index 1da07a8..d336ab1 100644
--- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/UserProxy.java
@@ -45,7 +45,10 @@
   ApiResponse userTask(@RequestBody UserTaskParam param);
 
   @PostMapping("/api/user/getTask")
-  Map<String, Object> getTPointsTaskNoPage();
+  Map<String, Object> getTPointsTaskNoPage(@RequestParam("userid") String userid);
+
+  @PostMapping("/api/user/getTaskStatus")
+  Map<String, Object> getTaskStatus(@RequestParam("userid") String userid,@RequestParam("taskid")Integer taskid);
 
   @PostMapping("/api/user/getUserPoints")
   Map<String, Object> getUserPoints(@RequestBody UserPointsParam param);
@@ -68,4 +71,21 @@
   @PostMapping("/api/user/updateCardTransStatus")
   ApiResponse updateCardTransStatus(@RequestParam("cardno") String cardno,@RequestParam("status") String status);
 
+  @PostMapping("/api/user/bindcard")
+  Map<String, Object> bindCard(@RequestBody BindCardParam param);
+
+  @PostMapping("/api/user/bindcardcode")
+  Map<String, Object> bindCardCode(@RequestParam("userid") String userid,@RequestParam("phone") String phone);
+
+  @PostMapping("/api/user/signbxy")
+  ApiResponse signbxy(@RequestParam("userid") String userid,@RequestParam("code") String code,@RequestParam("phone") String phone);
+
+  @PostMapping("/api/user/unsignbxy")
+  ApiResponse unsignbxy(@RequestParam("userid") String userid,@RequestParam("phone") String phone);
+
+  @PostMapping("/api/user/qrcode")
+  Map<String, Object> qrcode(@RequestBody QrcodeParam param);
+
+  @PostMapping("/api/user/consumetask")
+  ApiResponse consumeTask(@RequestParam("userid") String userid);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersonDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersonDao.java
index 5483aa1..988afaa 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersonDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersonDao.java
@@ -19,8 +19,4 @@
     TPerson findByUserid(String userid);
 
     Page<TPerson> findAllByNameContaining(String name, Pageable pageable);
-
-    TPerson findByUseridAndAndName(String userid,String name);
-
-    TPerson findByUseridAndIdtype(String userid,String idtype);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java
index 0f39c37..3be4457 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/PersondtlDao.java
@@ -25,4 +25,6 @@
     List<TPersondtl> findAllByUseridAndTransdateStartingWithAndReverseFlagAndStatusAndTradeflag(String userid, String transdate,String reverseFlag,String status,String tradeflag);
 
     List<TPersondtl> findAllByTransdateAndReverseFlagAndStatusAndTradeflag(String transdate,String reverseFlag,String status,String tradeflag);
+
+    TPersondtl findTopByUseridAndStatusAndTradeflag(String userid, String status, String tradeFlag);
 }
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 02e6bf9..d21ff59 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
@@ -30,6 +30,9 @@
   @Column(name = "TRANS_STATUS", nullable = false, length = 20)
   private String transStatus; //normal/loss/frozen/locked/abnormal/unuse
 
+  @Column(name = "BUS_CARD_TYPE", length = 20)
+  private String busCardType; //市民卡的公交卡类型
+
   @Column(name = "EXPIREDATE", length = 20)
   private String expiredate;
 
@@ -49,12 +52,13 @@
   public TCard() {
   }
 
-  public TCard(String cardno, String cardtype, String cardphyid, String status, String transStatus, String expiredate, Boolean signed, String userid, String lastsaved) {
+  public TCard(String cardno, String cardtype, String cardphyid, String status, String transStatus, String busCardType, String expiredate, Boolean signed, String userid, String lastsaved) {
     this.cardno = cardno;
     this.cardtype = cardtype;
     this.cardphyid = cardphyid;
     this.status = status;
     this.transStatus = transStatus;
+    this.busCardType = busCardType;
     this.expiredate = expiredate;
     this.signed = signed;
     this.userid = userid;
@@ -109,6 +113,14 @@
     this.transStatus = transStatus;
   }
 
+  public String getBusCardType() {
+    return busCardType;
+  }
+
+  public void setBusCardType(String busCardType) {
+    this.busCardType = busCardType;
+  }
+
   public String getExpiredate() {
     return expiredate;
   }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCitycardTemp.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCitycardTemp.java
index 7d7f454..97a48d7 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCitycardTemp.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TCitycardTemp.java
@@ -46,6 +46,9 @@
   @Column(name = "EMAIL", length = 60)
   private String email;
 
+  @Column(name = "BUS_CARD_TYPE", length = 20)
+  private String busCardType;
+
   @Column(name = "STATUS", length = 20)
   private String status;
 
@@ -185,4 +188,12 @@
   public void setTenantid(String tenantid) {
     this.tenantid = tenantid;
   }
+
+  public String getBusCardType() {
+    return busCardType;
+  }
+
+  public void setBusCardType(String busCardType) {
+    this.busCardType = busCardType;
+  }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/PointsDtlDao.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/PointsDtlDao.java
index 0bbf7a3..5e3d58e 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/PointsDtlDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/PointsDtlDao.java
@@ -33,4 +33,5 @@
 
   TPointsdtl findAllByUseridAndRefnoAndTransdate(String userid,Integer refno,String transdate);
 
+  TPointsdtl findTopByUseridAndTypeAndRefnoOrderByIdDesc(String userid, String type, Integer refno);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsTask.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsTask.java
index 3bfb71b..c56be1e 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsTask.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsTask.java
@@ -37,6 +37,9 @@
   @Column(name = "ORDERNUM")
   private Integer ordernum;
 
+  @Transient
+  private String lasttime;
+
   public Integer getTaskid() {
     return taskid;
   }
@@ -108,4 +111,12 @@
   public void setOrdernum(Integer ordernum) {
     this.ordernum = ordernum;
   }
+
+  public String getLasttime() {
+    return lasttime;
+  }
+
+  public void setLasttime(String lasttime) {
+    this.lasttime = lasttime;
+  }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsdtl.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsdtl.java
index 34c2f98..a5fe945 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsdtl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TPointsdtl.java
@@ -5,7 +5,7 @@
 import javax.persistence.*;
 
 @Entity
-@Table(name = "TB_POINTSDTL")
+@Table(name = "TB_POINTSDTL",indexes = {@Index(name = "points_dtl_idx",columnList = "userid")})
 public class TPointsdtl {
   @Id
   @GenericGenerator(name = "idGeneratorDtl", strategy = "sequence")
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Dictionary.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Dictionary.java
index 9eac02d..6798ebc 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Dictionary.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Dictionary.java
@@ -8,6 +8,7 @@
   public static final String SEX = "sexList";
   public static final String ACCOUNT_STATUS = "accountStatusList";
   public static final String DTLTYPES = "dtltypeList";
+  public static final String BUSCARDTYPES = "busCardTypeList";
 
   /////////////////////////////////////
   public static final String SOURCE_TYPE = "sourcetypeList";
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 ff4084c..180679b 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
@@ -272,5 +272,16 @@
 //    return bankCard.charAt(bankCard.length() - 1) == bit;
   }
 
+  /**
+   * 根据卡号创建8位16进制卡物理ID
+   * */
+  public static String createCardphyid(int cardno) {
+    String hex = Integer.toHexString(cardno);
+    while (hex.length() < 8) {
+      hex = "0" + hex;
+    }
+    return hex.toUpperCase();
+  }
+
 
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/bean/CitizenCardShowBean.java b/payapi/src/main/java/com/supwisdom/dlpay/system/bean/CitizenCardShowBean.java
index 5f4961b..17fd877 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/bean/CitizenCardShowBean.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/bean/CitizenCardShowBean.java
@@ -18,6 +18,7 @@
   private String mobile;
   private String email;
   private String sex;
+  private String buscardtype;
 
   public String getCid() {
     return cid;
@@ -154,4 +155,12 @@
   public void setSex(String sex) {
     this.sex = sex;
   }
+
+  public String getBuscardtype() {
+    return buscardtype;
+  }
+
+  public void setBuscardtype(String buscardtype) {
+    this.buscardtype = buscardtype;
+  }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/controller/UserController.java b/payapi/src/main/java/com/supwisdom/dlpay/system/controller/UserController.java
index eb36de9..4c35709 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/controller/UserController.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/controller/UserController.java
@@ -210,9 +210,10 @@
                                    @RequestParam(value = "idtype", required = false) String idtype,
                                    @RequestParam(value = "idno", required = false) String idno,
                                    @RequestParam(value = "mobile", required = false) String mobile,
-                                   @RequestParam(value = "email", required = false) String email) {
+                                   @RequestParam(value = "email", required = false) String email,
+                                   @RequestParam(value = "buscardtype", required = false) String buscardtype) {
     try {
-      if (userDataService.doSaveNewCitizenCard(cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email)) {
+      if (userDataService.doSaveNewCitizenCard(cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email, buscardtype)) {
         return JsonResult.ok("新增成功!");
       } else {
         return JsonResult.error("新增失败!");
@@ -264,9 +265,10 @@
                                    @RequestParam(value = "idtype", required = false) String idtype,
                                    @RequestParam(value = "idno", required = false) String idno,
                                    @RequestParam(value = "mobile", required = false) String mobile,
-                                   @RequestParam(value = "email", required = false) String email) {
+                                   @RequestParam(value = "email", required = false) String email,
+                                   @RequestParam(value = "buscardtype", required = false) String buscardtype) {
     try {
-      if (userDataService.doUpdateCitizenCard(cid, bkid, cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email)) {
+      if (userDataService.doUpdateCitizenCard(cid, bkid, cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email, buscardtype)) {
         return JsonResult.ok("修改成功!");
       } else {
         return JsonResult.error("修改失败!");
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/PointsService.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/PointsService.java
index b32f9cf..7efce69 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/service/PointsService.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/PointsService.java
@@ -11,6 +11,7 @@
 import com.supwisdom.dlpay.system.bean.CitizenCardShowBean;
 import com.supwisdom.dlpay.system.bean.LevelBean;
 import com.supwisdom.dlpay.system.bean.PersonParamBean;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -74,6 +75,10 @@
   * 通过消费获得积分
   *
   * */
+  //消费进行积分处理
+  @Async
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
+  void consumePoints(String userid,Double amount,String billno) throws ParseException;
   //单次消费进行积分处理
   @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
   Boolean singleHandlePoints(String userid,Double amount,String billno) throws ParseException;
@@ -136,7 +141,10 @@
   JsonResult finishTask (String userid,String taskid);
 
   @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
-  JsonResult getTPointsTaskNoPage();
+  JsonResult getTPointsTaskNoPage(String userid);
+
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
+  TPointsdtl getTaskStatus(String userid,Integer taskid);
 
 
   /*
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/UserDataService.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/UserDataService.java
index 8cc7a5b..e463ae5 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/service/UserDataService.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/UserDataService.java
@@ -50,12 +50,12 @@
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     boolean doSaveNewCitizenCard(String cardno, String cardphyid, String expiredate, String cardstatus, String bankcardno,
                                  String signstatus, String username, String sex, String idtype, String idno, String mobile,
-                                 String email) throws Exception;
+                                 String email, String buscardtype) throws Exception;
 
 
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     boolean doUpdateCitizenCard(String cid, String bkid, String cardno, String cardphyid, String expiredate, String cardstatus,
                                 String bankcardno, String signstatus, String username, String sex, String idtype, String idno,
-                                String mobile, String email) throws Exception;
+                                String mobile, String email, String buscardtype) throws Exception;
 
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/PointsServiceImpl.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/PointsServiceImpl.java
index c65cd8c..2d638b6 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/PointsServiceImpl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/PointsServiceImpl.java
@@ -119,11 +119,15 @@
 
   @Override
   public PageResult getTPointsByname(LevelBean param) {
+    logger.error("通过卡号查询用户卡开始时间"+DateUtil.getNow());
     TCard tCard = cardDao.findCardByCardnoAndCardtype(param.getIdno(), ConstantUtil.CARDTYPE_CITIZENCARD);
+    logger.error("通过卡号查询用户卡结束时间"+DateUtil.getNow());
     if (tCard == null || StringUtil.isEmpty(tCard.getUserid())) {
       return new PageResult<>(99, "未查询到该用户的信息");
     }
-    TPerson tPerson = personDao.findByUseridAndAndName(tCard.getUserid(), param.getName());
+    logger.error("通过用户id和名称查询用户信息开始时间"+DateUtil.getNow());
+    TPerson tPerson = personDao.findByUserid(tCard.getUserid());
+    logger.error("通过用户id和名称查询用户信息结束时间"+DateUtil.getNow());
     if (tPerson == null) {
       return new PageResult<>(99, "未查询到该用户的信息");
     }
@@ -221,13 +225,20 @@
     consumePointsDao.deleteById(tConsumePoints.getId());
     return JsonResult.ok("成功");
   }
-
+  @Override
+  public void consumePoints(String userid, Double amount, String billno) throws ParseException {
+    singleHandlePoints(userid,amount,billno);
+    dayHandlePoints(userid,billno);
+    monthHandlePoints(userid,billno);
+  }
   @Override
   public Boolean singleHandlePoints(String userid, Double amount, String billno) throws ParseException {
     double rate = 1;
     // 1.根据当天日期判断当天是否该用户的特殊日期或者生日,得到实际倍率
     String nowDateTemp = DateUtil.getNow("yyyyMMdd");
-    TPerson person = personDao.findByUseridAndIdtype(userid, "idcard");
+    logger.error("单次消费查询用户信息开始时间"+DateUtil.getNow());
+    TPerson person = personDao.findByUserid(userid);
+    logger.error("单次消费查询用户信息结束时间"+DateUtil.getNow());
     if (person != null && !StringUtil.isEmpty(person.getIdno())) {
       String nowDate = DateUtil.getNow("MMdd");
       String brithdate = person.getIdno().substring(10, 14);
@@ -922,11 +933,25 @@
   }
 
   @Override
-  public JsonResult getTPointsTaskNoPage() {
+  public JsonResult getTPointsTaskNoPage(String userid) {
+    List<TPointsTask> list = pointsTaskDao.findAll(Sort.by(Sort.Direction.ASC, "ordernum"));
+    if (!StringUtil.isEmpty(userid)) {
+      list.forEach(task ->{
+        TPointsdtl dtl = pointsDtlDao.findTopByUseridAndTypeAndRefnoOrderByIdDesc(userid, TradeDict.TASK_FLAG_FINISH, task.getTaskid());
+        if (dtl != null) {
+          task.setLasttime(dtl.getTransdate() + dtl.getTranstime());
+        }
+      });
+    }
     return JsonResult.ok().put("dataList",pointsTaskDao.findAll(Sort.by(Sort.Direction.ASC,"ordernum")));
   }
 
   @Override
+  public TPointsdtl getTaskStatus(String userid, Integer taskid) {
+    return pointsDtlDao.findTopByUseridAndTypeAndRefnoOrderByIdDesc(userid, TradeDict.TASK_FLAG_FINISH, taskid);
+  }
+
+  @Override
   public JsonResult pointsOutdate(){
     String yesterday = DateUtil.getYesterdayDay();
     List<TPointsDetail> pointsDetails = pointsDetailDao.findAllByOutDateAndStatus("20200821","normal");
@@ -954,7 +979,9 @@
   @Override
   public JsonResult pointsCompensate() throws ParseException {
     String yesterday = DateUtil.getYesterdayDay();
+    logger.error("查询用户流水开始时间"+DateUtil.getNow());
     List<TPersondtl> tPersondtl = persondtlDao.findAllByTransdateAndReverseFlagAndStatusAndTradeflag("20200821", "none", "success","out");
+    logger.error("查询用户流水结束时间"+DateUtil.getNow());
     //消费流水补偿
     for(TPersondtl temp:tPersondtl){
       singleHandlePoints(temp.getUserid(),temp.getAmount(),temp.getRefno());
@@ -962,7 +989,9 @@
       monthHandlePoints(temp.getUserid(),temp.getRefno());
     }
     //退款流水补偿
+    logger.error("查询用户流水list开始时间"+DateUtil.getNow());
     List<TPersondtl> tPersondtlReve = persondtlDao.findAllByTransdateAndReverseFlagAndStatusAndTradeflag("20200821", "refund", "success","out");
+    logger.error("查询用户流水list结束时间"+DateUtil.getNow());
     for(TPersondtl temp:tPersondtlReve){
       //退款怎么确认,refno和支付时一样吗
       refundHandlePoints(temp.getUserid(),temp.getRefno());
@@ -972,12 +1001,16 @@
 
   public List<TPersondtl> getShopdtlByUseridAndTransdateAndReverseFlagAndStatus(String userid,String transdate,String reverseFlag,String status){
     //TAccount account = accountDao.findByUserid(userid);
+    logger.error("查询用户流水list2开始时间"+DateUtil.getNow());
     List<TPersondtl> tShopdtls = persondtlDao.findAllByUseridAndTransdateAndReverseFlagAndStatusAndTradeflag(userid, transdate, reverseFlag, status,"out");
+    logger.error("查询用户流水list2结束时间"+DateUtil.getNow());
     return tShopdtls;
   }
   public List<TPersondtl> getShopdtlByUseridAndTransdateStartingWithAndReverseFlagAndStatus(String userid,String transdate,String reverseFlag,String status){
     //TAccount account = accountDao.findByUserid(userid);
+    logger.error("查询用户流水list3开始时间"+DateUtil.getNow());
     List<TPersondtl> tShopdtls = persondtlDao.findAllByUseridAndTransdateStartingWithAndReverseFlagAndStatusAndTradeflag(userid, transdate, reverseFlag, status,"out");
+    logger.error("查询用户流水list3结束时间"+DateUtil.getNow());
     return tShopdtls;
   }
 
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/UserDataServiceImpl.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/UserDataServiceImpl.java
index 01105f8..a7ed10e 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/UserDataServiceImpl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/UserDataServiceImpl.java
@@ -196,7 +196,7 @@
 
   @Override
   public PageResult<CitizenCardShowBean> getUserCitizenCardPage(CitizenCardSearchBean param, int pageNo, int pageSize) {
-    StringBuffer querySql = new StringBuffer("select t.id as cid,t.cardno,t.cardtype,t.cardphyid,case when t.status='closed' then 'closed' else t.trans_status end as status,t.expiredate,a.id as bkid,a.cardno as bankcardno,a.signed,t.lastsaved,t.userid,p.name as username,p.idtype,p.idno,p.mobile,p.email,p.sex \n" +
+    StringBuffer querySql = new StringBuffer("select t.id as cid,t.cardno,t.cardtype,t.cardphyid,case when t.status='closed' then 'closed' else t.trans_status end as status,t.expiredate,a.id as bkid,a.cardno as bankcardno,a.signed,t.lastsaved,t.userid,p.name as username,p.idtype,p.idno,p.mobile,p.email,p.sex,t.bus_card_type as buscardtype \n" +
         "from tb_card t left join tb_card a on a.cardtype='bankcard' and a.cardphyid=t.cardphyid and a.userid=t.userid left join tb_person p on p.userid=t.userid \n" +
         "where t.cardtype='citizencard' ");
     StringBuffer countSql = new StringBuffer("select count(t.id) as cnt \n" +
@@ -255,7 +255,7 @@
 
   private boolean checkCitizenCardData(String cardno, String cardphyid, String expiredate, String cardstatus, String bankcardno,
                                        String signstatus, String username, String sex, String idtype, String idno, String mobile,
-                                       String email) throws WebCheckException {
+                                       String email, String buscardtype) throws WebCheckException {
     if (StringUtil.isEmpty(cardno)) throw new WebCheckException("市民卡号不能为空");
     if (!StringUtil.isNumber(cardno.trim())) throw new WebCheckException("请正确填写市民卡号");
 
@@ -290,14 +290,15 @@
 
     if (!StringUtil.isEmpty(mobile) && !StringUtil.isMobile(mobile.trim())) throw new WebCheckException("请正确填写手机号");
     if (!StringUtil.isEmpty(email) && !StringUtil.isEmail(email.trim())) throw new WebCheckException("请正确填写电子邮箱");
+    if (StringUtil.isEmpty(buscardtype)) throw new WebCheckException("请选择公交卡类型");
     return true;
   }
 
   @Override
   public boolean doSaveNewCitizenCard(String cardno, String cardphyid, String expiredate, String cardstatus, String bankcardno,
                                       String signstatus, String username, String sex, String idtype, String idno, String mobile,
-                                      String email) throws Exception {
-    if (checkCitizenCardData(cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email)) {
+                                      String email, String buscardtype) throws Exception {
+    if (checkCitizenCardData(cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email, buscardtype)) {
       double maxbal = systemUtilService.getSysparaValueAsDouble(SysparaUtil.BALANCE_LIMIT, SysparaUtil.DEFAULT_BALANCE_LIMIT);
       double lowfreeLimit = systemUtilService.getSysparaValueAsDouble(SysparaUtil.NOPASS_LIMIT, SysparaUtil.DEFAULT_NOPASS_LIMIT);
       double daylimit = systemUtilService.getSysparaValueAsDouble(SysparaUtil.DAY_PAY_LIMIT, SysparaUtil.DEFAULT_DAY_PAY_LIMIT);
@@ -385,6 +386,7 @@
       cityCard.setUserid(person.getUserid());
       cityCard.setLastsaved(dt.getHostdatetime());
       cityCard.setTenantid(person.getTenantid());
+      cityCard.setBusCardType(buscardtype.trim());
       cardDao.save(cityCard);
 
       bankCard = new TCard(); //新增银行卡
@@ -404,6 +406,7 @@
       if (TradeDict.STATUS_NORMAL.equals(bankCard.getStatus())) {
         cardDao.closedBankcardStatusByUserid(bankCard.getUserid());  //注销其他银行卡
       }
+      bankCard.setBusCardType(buscardtype.trim());
       cardDao.save(bankCard);
       return true;
     }
@@ -418,7 +421,7 @@
   @Override
   public boolean doUpdateCitizenCard(String cid, String bkid, String cardno, String cardphyid, String expiredate, String cardstatus,
                                      String bankcardno, String signstatus, String username, String sex, String idtype, String idno,
-                                     String mobile, String email) throws Exception {
+                                     String mobile, String email, String buscardtype) throws Exception {
     TCard cityCard = findCardById(cid);
     TCard bankCard = findCardById(bkid);
     if (null == cityCard || null == bankCard ||
@@ -431,7 +434,7 @@
     TPerson person = personDao.findByUserid(cityCard.getUserid());
     if(null==person) throw new WebCheckException("请求参数错误,请重新查询!");
 
-    if (checkCitizenCardData(cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email)) {
+    if (checkCitizenCardData(cardno, cardphyid, expiredate, cardstatus, bankcardno, signstatus, username, sex, idtype, idno, mobile, email, buscardtype)) {
       TPerson owner = null; //市民卡拥有者
       SystemDateTime dt = systemUtilService.getSysdatetime();
       if(idtype.trim().equals(person.getIdtype()) && idno.trim().equals(person.getIdno())){
@@ -539,7 +542,10 @@
         cityCard.setUserid(owner.getUserid());
         cardUpdate = true;
       }
-
+      if (!buscardtype.trim().equals(cityCard.getBusCardType())) {
+        cityCard.setBusCardType(buscardtype.trim());
+        cardUpdate = true;
+      }
       if(cardUpdate){
         cityCard.setLastsaved(dt.getHostdatetime());
         cardDao.save(cityCard);
@@ -569,6 +575,10 @@
         bankCard.setUserid(cityCard.getUserid());
         bankcardUpdate = true;
       }
+      if (!buscardtype.trim().equals(bankCard.getBusCardType())) {
+        bankCard.setBusCardType(buscardtype.trim());
+        bankcardUpdate = true;
+      }
 
       if(bankcardUpdate){
         bankCard.setLastsaved(dt.getHostdatetime());
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index f489996..2df8b69 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -30,6 +30,7 @@
 import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
 import org.springframework.data.redis.serializer.StringRedisSerializer
 import org.springframework.http.client.SimpleClientHttpRequestFactory
+import org.springframework.scheduling.annotation.EnableAsync
 import org.springframework.scheduling.annotation.EnableScheduling
 import org.springframework.stereotype.Component
 import org.springframework.web.client.RestTemplate
@@ -39,6 +40,7 @@
 
 @Configuration
 @EnableRedisRepositories
+@EnableAsync
 class AppConfig {
 
     @Autowired
@@ -164,4 +166,4 @@
 
 fun main(args: Array<String>) {
     SpringApplication.run(PayApiApplication::class.java, * args)
-}
\ No newline at end of file
+}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/citizencard_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/citizencard_service_impl.kt
index 1dbd5c7..0d97656 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/citizencard_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/citizencard_service_impl.kt
@@ -236,10 +236,7 @@
             return if (200 == respClient.status) {
                 val jsonStr = respClient.getEntity(String::class.java)
                 logger.error("refno=[$refno], url=[$url], return=[$jsonStr]")
-//                resp = Gson().fromJson(jsonStr, DlpayResp::class.java)
-                resp = DlpayResp().apply {
-                    code="0000"
-                }
+                resp = Gson().fromJson(jsonStr, DlpayResp::class.java)
                 resp
             } else {
                 resp.code = "99"
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 5eef7e5..21edbe8 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
@@ -59,7 +59,7 @@
 
 class DaliDatasyncDetail {
     var cardno: String = ""
-    var cardphyid: String = ""
+    var cardphyid: String? = null //fixme:物理卡号可能为空!
     var expiredate: String = ""
     var cardstatus: String = ""
     var bankcardno: String? = null
@@ -69,10 +69,12 @@
     var idno: String = ""
     var mobile: String? = null
     var email: String? = null
+    var cardType: String = ""
 
     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("卡片明细数据关键字段为空")
+        if (StringUtil.isEmpty(cardno) || StringUtil.isEmpty(expiredate) || StringUtil.isEmpty(cardstatus)) throw RequestParamCheckException("卡片明细数据关键字段为空")
+        if (StringUtil.isEmpty(cardType)) throw RequestParamCheckException("卡片的公交卡类型字段值为空")
         return true
     }
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
index 6779e80..87e054c 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
@@ -234,8 +234,6 @@
         val dtl = transactionService.wip(param.refno)
         val service = createAgentService<DtlStatus>(TradeDict.PAYTYPE_CITIZEN_CARD)
         val resp = service.pay(dtl)
-        resp.code = AgentCode.SUCCESS
-        resp.agentRefno = systemUtilService.refno
         when (resp.code) {
             AgentCode.SUCCESS ->
                 transactionService.success(dtl.refno, resp.agentRefno, false).let {
@@ -346,8 +344,6 @@
             transactionService.wip(refundTrans.refno)
             val service = createAgentService<Any>(mainDtl.sourceType)
             val resp = service.refund(refundTrans)
-            resp.code = AgentCode.SUCCESS
-            resp.agentRefno = systemUtilService.refno
             when (resp.code) {
                 AgentCode.SUCCESS -> {
                     transactionService.success(refundTrans.refno, resp.agentRefno, false)
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
index ce7a15a..2c80fa3 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
@@ -1,5 +1,7 @@
 package com.supwisdom.dlpay.api.controller
 
+import com.supwisdom.dlpay.agent.citizencard.YnrccUtil
+import com.supwisdom.dlpay.agent.service.CitizencardPayService
 import com.supwisdom.dlpay.api.TransactionBuilder
 import com.supwisdom.dlpay.api.bean.*
 import com.supwisdom.dlpay.api.bean.groups.ConfirmAction
@@ -14,6 +16,7 @@
 import com.supwisdom.dlpay.framework.util.TradeCode
 import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import com.supwisdom.dlpay.mobile.service.MobileApiService
 import com.supwisdom.dlpay.system.bean.LevelBean
 import com.supwisdom.dlpay.system.service.PointsService
 import org.apache.commons.beanutils.BeanUtils
@@ -41,6 +44,15 @@
 
     @Autowired
     private lateinit var pointsService: PointsService
+    @Autowired
+    private lateinit var mobileApiService: MobileApiService
+    @Autowired
+    private lateinit var userService: UserService
+    @Autowired
+    private lateinit var citizencardPayService: CitizencardPayService
+    @Autowired
+    private lateinit var qrcodeService: QRCodeService
+
 
     @Autowired
     private lateinit var transactionService: TransactionServiceProxy
@@ -393,8 +405,8 @@
     }
 
     @PostMapping("/getTask")
-    fun getTPointsTaskNoPage(): ResponseEntity<Any> {
-        val ret = pointsService.getTPointsTaskNoPage()
+    fun getTPointsTaskNoPage(userid:String?): ResponseEntity<Any> {
+        val ret = pointsService.getTPointsTaskNoPage(userid)
         return if(ret.get("code")==200){
             ResponseEntity.ok(ResponseBodyBuilder.create().data("data", ret.get("dataList")!!)
                     .success("ok"))
@@ -404,6 +416,17 @@
         }
     }
 
+    @PostMapping("/getTaskStatus")
+    fun getTaskStatus(userid:String,taskid:Int): ResponseEntity<Any> {
+        val dtl = pointsService.getTaskStatus(userid,taskid)
+        var time = ""
+        if (dtl != null) {
+            time = dtl.transdate + dtl.transtime
+        }
+        return ResponseEntity.ok(ResponseBodyBuilder.create().data("data",time)
+                .success("ok"))
+    }
+
     @PostMapping("/getUserPoints")
     fun getUserPoints(@RequestBody param: UserPointsParam): ResponseEntity<Any> {
         var lev = LevelBean()
@@ -483,4 +506,145 @@
                     .fail(ret.retcode, ret.retmsg))
         }
     }
+
+    /**
+     * 用户绑卡
+     */
+    @PostMapping("/bindcard")
+    fun bindCard(@RequestBody param: BindCardParam):ResponseEntity<Any>{
+        val card = mobileApiService.findCardByNo(param.cardno)
+                ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(400, "银行卡号有误"))
+        if (card.userid.isNullOrEmpty() || card.status != TradeDict.STATUS_NORMAL) {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(500, "银行卡号信息有误"))
+        }
+        val person = userService.findOnePersonByUserid(card.userid)
+        if (person.name != param.name) {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(400, "绑定信息有误[姓名]"))
+        }
+        if (person.idtype != param.idtype || person.idno != param.idno) {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(400, "绑定信息有误[证件类型/证件号]"))
+        }
+        var signed = ""
+        //call api
+        val resp = citizencardPayService.bindCard(param.cardno, param.name, param.idtype, param.idno, param.phone)
+        if (resp.code != "0000") {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(500, resp.message))
+        }
+        if (resp.sinstatus == YnrccUtil.TRANSTYPE_SIGNCARD ) {
+            signed = TradeDict.STATUS_YES
+            if(!card.signed){
+                card.signed = true
+                mobileApiService.saveCard(card)
+            }
+        }
+        return  ResponseEntity.ok(ResponseBodyBuilder.create().data("signed", signed)
+                .success("ok"))
+    }
+
+    /**
+     * 签约验证码
+     */
+    @PostMapping("/bindcardcode")
+    fun bindCardCode(userid: String,phone:String):ResponseEntity<Any>{
+        val card = mobileApiService.findCardByUserid(userid)
+                ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(400, "卡片不存在,请重新绑定"))
+        //call sign api
+        val person = userService.findOnePersonByUserid(card.userid)
+        var signed=""
+        //call api
+        val resp = citizencardPayService.bindCard(card.cardno, person.name, person.idtype, person.idno, phone)
+        if (resp.code != "0000") {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(500, resp.message))
+        }
+
+        if (resp.sinstatus == YnrccUtil.TRANSTYPE_SIGNCARD ) {
+            signed = TradeDict.STATUS_YES
+            if(!card.signed){
+                card.signed = true
+                mobileApiService.saveCard(card)
+            }
+        }
+        return  ResponseEntity.ok(ResponseBodyBuilder.create().data("signed", signed)
+                .success("ok"))
+    }
+
+    /**
+     * 签约银行协议
+     */
+    @PostMapping("/signbxy")
+    fun signbxy(userid: String, code: String, phone: String): ResponseEntity<Any> {
+        val card = mobileApiService.findCardByUserid(userid)
+                ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(400, "卡片不存在,请重新绑定"))
+        //call sign api
+        val person = userService.findOnePersonByUserid(card.userid)
+        val resp = citizencardPayService.signCard(card.cardno, person.name, person.idtype, person.idno, phone, YnrccUtil.TRANSTYPE_SIGNCARD, code)
+        if (resp.code != "0000") {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(500, resp.message))
+        }
+        card.signed = true
+        mobileApiService.saveCard(card)
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .success("ok"))
+    }
+
+    /**
+     * 用户解约
+     */
+    @PostMapping("/unsignbxy")
+    fun unsignbxy(userid: String,phone:String): ResponseEntity<Any> {
+        val card = mobileApiService.findCardByUserid(userid)
+                ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(400, "银行卡不存在,不能解除代扣协议"))
+        //call sign api
+        val person = userService.findOnePersonByUserid(card.userid)
+        val captcha = ""//此处为验证码,暂由此参数代替
+        var resp = citizencardPayService.signCard(card.cardno, person.name, person.idtype, person.idno, phone, YnrccUtil.TRANSTYPE_UNSIGNCARD, captcha)
+        if (resp.code != "0000") {
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(500, resp.message))
+        }
+        card.signed = false
+        mobileApiService.saveCard(card)
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .success("ok"))
+    }
+
+    /**
+     * 二维码
+     */
+    @PostMapping("/qrcode")
+    fun qrcode(@RequestBody param: QrcodeParam): ResponseEntity<Any> {
+        val resp = qrcodeService.encodeCode(param)
+        return if (resp.retcode == 0) {
+            ResponseEntity.ok(ResponseBodyBuilder.create().data("qrcode", resp.retmsg)
+                    .success("ok"))
+        } else {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(500, resp.retmsg))
+        }
+    }
+
+    /**
+     * 查询用户是否完成了首次消费任务
+     */
+    @PostMapping("/consumetask")
+    fun consumeTask(userid:String): ResponseEntity<Any> {
+        val flag = userService.findPersonIsConsume(userid)
+        return if (flag) {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success("ok"))
+        } else {
+            ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .fail(400,"未完成首次消费任务"))
+        }
+    }
 }
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 734d138..6c67732 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
@@ -6,7 +6,11 @@
 import com.supwisdom.dlpay.api.domain.TCard
 import com.supwisdom.dlpay.api.domain.TPerson
 import com.supwisdom.dlpay.api.service.CardService
+import com.supwisdom.dlpay.citizencard.dao.CitizencardLossApplyDao
+import com.supwisdom.dlpay.citizencard.domain.TCitizencardLossApply
 import com.supwisdom.dlpay.exception.TransactionProcessException
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.Constants
 import com.supwisdom.dlpay.framework.util.StringUtil
 import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
@@ -24,6 +28,10 @@
     lateinit var cardDao: CardDao
     @Autowired
     lateinit var personDao: PersonDao
+    @Autowired
+    lateinit var citizencardLossApplyDao:CitizencardLossApplyDao
+    @Autowired
+    lateinit var systemUtilService: SystemUtilService
 
     @PersistenceContext
     private lateinit var entityManager: EntityManager
@@ -164,9 +172,9 @@
 
     override fun getCardByCardNoOrUserid(param: QueryCardParam): TCard? {
         if (!StringUtil.isEmpty(param.cardno)) {
-            return cardDao.findCardByCardnoAndCardtype(param.cardno,param.cardtype)
+            return cardDao.findCardByCardnoAndCardtype(param.cardno, param.cardtype)
         }else if (!StringUtil.isEmpty(param.userid)) {
-            return cardDao.findCardByUseridAndCardtype(param.userid,param.cardtype)
+            return cardDao.findCardByUseridAndCardtype(param.userid, param.cardtype)
         }
         return null
     }
@@ -194,7 +202,23 @@
         val card = cardDao.findCardByCardnoAndCardtype(cardno, ConstantUtil.CARDTYPE_BANKCARD)
                 ?: return result
         card.transStatus = status
+        card.lastsaved = systemUtilService.sysdatetime.hostdatetime
         cardDao.save(card)
+        if (TradeDict.STATUS_LOST == status) {
+            //保存挂失申请,异步通知卡管系统
+            cardDao.findBankcardByCitizencard(card.userid, ConstantUtil.CARDTYPE_CITIZENCARD, card.cardphyid)?.let { cityCard ->
+                citizencardLossApplyDao.save(TCitizencardLossApply().apply {
+                    this.refno = systemUtilService.refno
+                    this.cardno = cityCard.cardno //银行卡对应的市民卡号
+                    this.applytime = systemUtilService.sysdatetime.hostdatetime
+                    this.termtype = "app"
+                    this.status = ConstantUtil.CITIZENCARD_LOSSAPPLY_STATUS_APPLY
+                    this.sendcnt = 0
+                    this.lastsaved = systemUtilService.sysdatetime.sysdate
+                    this.tenantId = card.tenantid ?: Constants.DEFAULT_TENANTID
+                })
+            }
+        }
         return result.apply {
             this.retcode = 0
             this.retmsg = "ok"
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
index 96b13f8..ff32235 100644
--- 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
@@ -146,7 +146,7 @@
                     cityCard.status = TradeDict.STATUS_CLOSED
                 }
             } else {
-                //卡片的其他状态,代表交易状态
+                //卡片的其他状态,代表交易状态。主状态改为正常,交易状态覆盖
                 if (TradeDict.STATUS_NORMAL != cityCard.transStatus) {
                     cardUpdateFlag = true
                     cityCard.status = TradeDict.STATUS_NORMAL
@@ -157,6 +157,12 @@
                 }
             }
 
+            //fixme: 公交卡类型
+            if (bean.cardType.trim() != cityCard.busCardType) {
+                cardUpdateFlag = true
+                cityCard.busCardType = bean.cardType.trim()
+            }
+
             if (cardUpdateFlag) {
                 cityCard.lastsaved = systime.hostdatetime
                 cardDao.save(cityCard) //更新
@@ -165,7 +171,10 @@
             cityCard = TCard().apply {
                 cardno = bean.cardno.trim()
                 cardtype = ConstantUtil.CARDTYPE_CITIZENCARD
-                cardphyid = bean.cardphyid.trim()
+                cardphyid = when (bean.cardphyid.isNullOrBlank()) {
+                    true -> bean.cardno.trim()
+                    false -> bean.cardphyid!!.trim()
+                }
                 status = when (TradeDict.STATUS_CLOSED == cardStatus) {
                     true -> TradeDict.STATUS_CLOSED
                     false -> TradeDict.STATUS_NORMAL
@@ -174,6 +183,7 @@
                     true -> TradeDict.STATUS_ABNORMAL
                     false -> cardStatus
                 }
+                busCardType = bean.cardType.trim()
                 expiredate = bean.expiredate.trim()
                 signed = false
                 userid = person.userid
@@ -189,12 +199,19 @@
                 bankCard = TCard().apply {
                     cardno = bean.bankcardno!!.trim()
                     cardtype = ConstantUtil.CARDTYPE_BANKCARD
-                    cardphyid = bean.cardphyid.trim()
+                    cardphyid = when (bean.cardphyid.isNullOrBlank()) {
+                        true -> bean.cardno.trim()
+                        false -> bean.cardphyid!!.trim()
+                    }
                     status = when (TradeDict.STATUS_CLOSED == cardStatus) {
                         true -> TradeDict.STATUS_CLOSED
                         false -> TradeDict.STATUS_NORMAL
                     }
-                    transStatus = TradeDict.STATUS_NORMAL
+                    transStatus = when (TradeDict.STATUS_CLOSED == cardStatus) {
+                        true -> TradeDict.STATUS_ABNORMAL
+                        false -> cardStatus
+                    }
+                    busCardType = bean.cardType.trim()
                     expiredate = "21991231"
                     signed = false
                     userid = person.userid
@@ -209,6 +226,36 @@
                 if (bankCard.userid != person.userid) {
                     throw TransactionProcessException(3000, "银行卡已被人绑定")
                 }
+
+                var bankUpdate = false
+                if (TradeDict.STATUS_CLOSED == cardStatus) {
+                    //注销卡片
+                    if (bankCard.status != TradeDict.STATUS_CLOSED) {
+                        bankUpdate = true
+                        bankCard.status = TradeDict.STATUS_CLOSED
+                    }
+                } else {
+                    //卡片的其他状态,代表交易状态。主状态改为正常,交易状态覆盖
+                    if (TradeDict.STATUS_NORMAL != bankCard.transStatus) {
+                        bankUpdate = true
+                        bankCard.status = TradeDict.STATUS_NORMAL
+                    }
+                    if (cardStatus != bankCard.transStatus) {
+                        bankUpdate = true
+                        bankCard.transStatus = cardStatus
+                    }
+                }
+
+                //fixme: 公交卡类型
+                if (bean.cardType.trim() != bankCard.busCardType) {
+                    bankUpdate = true
+                    bankCard.busCardType = bean.cardType.trim()
+                }
+
+                if(bankUpdate){
+                    bankCard.lastsaved = systime.hostdatetime
+                    cardDao.save(bankCard) //更新
+                }
             }
         }
 
@@ -236,6 +283,7 @@
             this.idno = bean.idno
             this.mobile = bean.mobile
             this.email = bean.email
+            this.busCardType = bean.cardType
             this.status = TradeDict.DTL_STATUS_FAIL
             this.remark = errmsg
             this.lastsaved = systemUtilService.sysdatetime.hostdatetime
@@ -264,6 +312,7 @@
             this.idno = temp.idno
             this.mobile = temp.mobile
             this.email = temp.email
+            this.cardType = temp.busCardType
         }
         bean.checkParam()
         if (doUpdateUserInfos(bean)) {
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/qrcode_srvice_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/qrcode_srvice_impl.kt
index f26dafa..38b6374 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/qrcode_srvice_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/qrcode_srvice_impl.kt
@@ -3,6 +3,8 @@
 import com.google.gson.Gson
 import com.supwisdom.dlpay.api.bean.ApiResponse
 import com.supwisdom.dlpay.api.bean.DoorQrcodeResponse
+import com.supwisdom.dlpay.api.bean.QrcodeParam
+import com.supwisdom.dlpay.api.service.CardService
 import com.supwisdom.dlpay.api.service.QRCodeService
 import com.supwisdom.dlpay.api.service.UserService
 import com.supwisdom.dlpay.framework.service.SystemUtilService
@@ -26,6 +28,8 @@
     @Autowired
     lateinit var userService: UserService
     @Autowired
+    lateinit var cardService: CardService
+    @Autowired
     lateinit var redisTemplate: RedisTemplate<String, String>
 
     val logger = KotlinLogging.logger { }
@@ -50,6 +54,17 @@
             resp.retmsg = "用户未绑定身份"
             return resp
         }
+        val bankCard = cardService.getBankcardByUserid(muser.userid!!)
+        if (null == bankCard) {
+            resp.retcode = 1
+            resp.retmsg = "用户未绑定银行卡"
+            return resp
+        } else if (!bankCard.signed) {
+            resp.retcode = 1
+            resp.retmsg = "银行卡未签约"
+            return resp
+        }
+
         val totp = QrCodeTotpUtil.generateTOTP(muser.secertkey)
         val rowdata = QrcodeRawData()
         rowdata.userid = muser.userid
@@ -66,6 +81,32 @@
         return resp
     }
 
+    override fun encodeCode(param: QrcodeParam): ApiResponse {
+        var resp = ApiResponse()
+        val uid = param.uid
+        val rootkey = systemUtilService.getBusinessValue("aes.cfb.rootkey")
+        val iv = systemUtilService.getBusinessValue("aes.cfb.iv")
+        if (rootkey.isNullOrEmpty()||iv.isNullOrEmpty()) {
+            resp.retcode = 1
+            resp.retmsg = "秘钥未配置"
+            return resp
+        }
+        val totp = QrCodeTotpUtil.generateTOTP(param.secertkey)
+        val rowdata = QrcodeRawData()
+        rowdata.userid = param.userid
+        rowdata.setTotp(totp)
+        val orgData = Gson().toJson(rowdata)
+        val publicKey = RSAKeysGenerate.getPublicKey(param.rsapublic)
+        val encdata = org.apache.commons.codec.binary.Base64.encodeBase64String(RSAKeysGenerate.encryptbyte(publicKey, orgData))
+        val qrcode = AesUtil.encryptCFB("$uid:$encdata", rootkey, iv, "AES/CFB/NoPadding")
+
+        val key = MD5.encodeByMD5ToURLSafeBase64(qrcode)
+        redisTemplate.opsForValue().set(key,qrcode, Duration.ofSeconds(20))
+        resp.retcode = 0
+        resp.retmsg = key
+        return resp
+    }
+
     override fun decodeCode(qrcode :String): DoorQrcodeResponse {
 
         //解密
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/user_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/user_service_impl.kt
index ce708b1..b98129a 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/user_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/user_service_impl.kt
@@ -230,4 +230,8 @@
             return null
         }
     }
+
+    override fun findPersonIsConsume(userid: String): Boolean {
+        return persondtlDao.findTopByUseridAndStatusAndTradeflag(userid, TradeDict.DTL_STATUS_SUCCESS, TradeDict.TRADE_FLAG_OUT) != null
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/qrcode_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/qrcode_service.kt
index 029f6a8..d8b21ce 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/qrcode_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/qrcode_service.kt
@@ -2,8 +2,10 @@
 
 import com.supwisdom.dlpay.api.bean.ApiResponse
 import com.supwisdom.dlpay.api.bean.DoorQrcodeResponse
+import com.supwisdom.dlpay.api.bean.QrcodeParam
 
 interface QRCodeService {
     fun encodeCode(uid: String): ApiResponse
+    fun encodeCode(param: QrcodeParam): ApiResponse
     fun decodeCode(qrcode: String): DoorQrcodeResponse
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
index 33e9f2f..4d18a91 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
@@ -116,11 +116,7 @@
             }
             if(-it.personDtl.amount>=0) {
                 //支付成功  进行积分处理
-                pointsService.singleHandlePoints(it.personDtl.userid, -it.personDtl.amount, refno);
-                pointsService.dayHandlePoints(it.personDtl.userid, refno);
-                pointsService.monthHandlePoints(it.personDtl.userid, refno);
-               // pointsService.pointsOutdate();
-                pointsService.pointsCompensate();
+                pointsService.consumePoints(it.personDtl.userid, -it.personDtl.amount, refno);
             }else {
                 //退款之后进行积分处理
                 pointsService.refundHandlePoints(it.personDtl.userid, it.reverseRefno);
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/user_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/user_service.kt
index 26fc2ff..a439f44 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/user_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/user_service.kt
@@ -54,4 +54,7 @@
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = arrayOf(Exception::class), readOnly = true)
     fun findPersondtlDetailByUserid(userid:String, billno :String) : TPersondtl?
 
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = arrayOf(Exception::class), readOnly = true)
+    fun findPersonIsConsume(userid:String): Boolean
+
 }
\ No newline at end of file
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 299fd7f..8de6f1e 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -6,6 +6,8 @@
 import com.supwisdom.dlpay.api.service.QRCodeService
 import com.supwisdom.dlpay.api.service.UserService
 import com.supwisdom.dlpay.api.util.MobileNumberCheck
+import com.supwisdom.dlpay.citizencard.domain.TCitizencardLossApply
+import com.supwisdom.dlpay.citizencard.service.CitizencardManagerService
 import com.supwisdom.dlpay.framework.core.JwtConfig
 import com.supwisdom.dlpay.framework.core.JwtTokenUtil
 import com.supwisdom.dlpay.framework.domain.JwtRedis
@@ -267,6 +269,10 @@
     lateinit var jwtConfig: JwtConfig
     @Autowired
     lateinit var qrcodeService:QRCodeService
+    @Autowired
+    lateinit var citizencardManagerService: CitizencardManagerService
+    @Autowired
+    lateinit var systemUtilService: SystemUtilService
     val logger = KotlinLogging.logger { }
 
     @RequestMapping("/idtypes")
@@ -850,6 +856,19 @@
         }
         card.transStatus = TradeDict.STATUS_LOST
         mobileApiService.saveCard(card)
+        mobileApiService.findCardByUseridAndCardphyid(card.userid, ConstantUtil.CARDTYPE_CITIZENCARD, card.cardphyid)?.let { cityCard ->
+            citizencardManagerService.saveOrUpdateCitizencardLossApply(TCitizencardLossApply().apply {
+                this.refno = systemUtilService.refno
+                this.cardno = cityCard.cardno //银行卡对应的市民卡号
+                this.applytime = systemUtilService.sysdatetime.hostdatetime
+                this.termtype = "app"
+                this.uid = user.uid
+                this.status = ConstantUtil.CITIZENCARD_LOSSAPPLY_STATUS_APPLY
+                this.sendcnt = 0
+                this.lastsaved = systemUtilService.sysdatetime.sysdate
+                this.tenantId = card.tenantid ?: Constants.DEFAULT_TENANTID
+            })
+        }
         return JsonResult.ok("ok")
     }
 
diff --git a/payapi/src/main/resources/static/libs/custom.js b/payapi/src/main/resources/static/libs/custom.js
index 0307a2d..8c81562 100644
--- a/payapi/src/main/resources/static/libs/custom.js
+++ b/payapi/src/main/resources/static/libs/custom.js
@@ -67,6 +67,7 @@
                     .addNewDict("accountStatusList")
                     .addNewDict("allSubjectList")
                     .addNewDict("transcodeList")
+                    .addNewDict("busCardTypeList")
             },
             getDict: function (dictType) {
                 var dict, that = this;
diff --git a/payapi/src/main/resources/templates/system/user/addcard.html b/payapi/src/main/resources/templates/system/user/addcard.html
index 0151106..1fb8fc1 100644
--- a/payapi/src/main/resources/templates/system/user/addcard.html
+++ b/payapi/src/main/resources/templates/system/user/addcard.html
@@ -120,6 +120,21 @@
         </div>
     </div>
 
+    <div class="layui-form-item">
+        <div class="layui-inline">
+            <label class="layui-form-label"><span style="color: red;">*</span>公交卡类型</label>
+            <div class="layui-input-inline">
+                <select name="buscardtype" class="layui-input layui-select" lay-verify="required">
+                    <option value="80" selected>80_普通卡</option>
+                    <option value="81" selected>81_学生卡</option>
+                    <option value="82" selected>82_老年卡</option>
+                    <option value="83" selected>83_爱心卡</option>
+                    <option value="84" selected>84_阳光卡</option>
+                </select>
+            </div>
+        </div>
+    </div>
+
     <div class="layui-form-item model-form-footer">
         <button class="layui-btn" lay-filter="citizencard-add-form-submit" lay-submit  id="citizencard-add-ok">保存</button>
         <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
diff --git a/payapi/src/main/resources/templates/system/user/card.html b/payapi/src/main/resources/templates/system/user/card.html
index 251daa4..1759183 100644
--- a/payapi/src/main/resources/templates/system/user/card.html
+++ b/payapi/src/main/resources/templates/system/user/card.html
@@ -81,12 +81,18 @@
             url: '[[@{/user/cardlist}]]',
             page: true,
             toolbar: '#citizencard-table-toolbar',
+            defaultToolbar: ['filter'],
             cols: [
                 [
                     {type:'radio', align: 'center', width: 35, fixed: 'left'},
                     {field:'cardno',title:'市民卡号', align: 'center', width: 120, fixed: 'left', sort: true},
                     {field:'cardphyid',title:'物理卡号', align: 'center', width: 120, fixed: 'left'},
                     {
+                        field: 'buscardtype', title: '公交卡类型', align: 'center', width: 100, templet: function (d) {
+                          return getTempDictValue('busCardTypeList', d.buscardtype);
+                        }
+                    },
+                    {
                         field: 'expiredate', title: '有效期', align: 'center', width: 120, templet: function (d) {
                             return dateFormat('' + d.expiredate);
                         }
diff --git a/payapi/src/main/resources/templates/system/user/updatecard.html b/payapi/src/main/resources/templates/system/user/updatecard.html
index 7e1cb74..49d0002 100644
--- a/payapi/src/main/resources/templates/system/user/updatecard.html
+++ b/payapi/src/main/resources/templates/system/user/updatecard.html
@@ -122,6 +122,21 @@
         </div>
     </div>
 
+    <div class="layui-form-item">
+        <div class="layui-inline">
+            <label class="layui-form-label"><span style="color: red;">*</span>公交卡类型</label>
+            <div class="layui-input-inline">
+                <select name="buscardtype" class="layui-input layui-select" lay-verify="required">
+                    <option value="80" selected>80_普通卡</option>
+                    <option value="81" selected>81_学生卡</option>
+                    <option value="82" selected>82_老年卡</option>
+                    <option value="83" selected>83_爱心卡</option>
+                    <option value="84" selected>84_阳光卡</option>
+                </select>
+            </div>
+        </div>
+    </div>
+
     <div class="layui-form-item model-form-footer">
         <button class="layui-btn" lay-filter="citizencard-modify-form-submit" lay-submit  id="citizencard-modify-ok">保存</button>
         <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
@@ -159,7 +174,8 @@
                 idtype:cardBean.idtype,
                 idno:cardBean.idno,
                 mobile:cardBean.mobile,
-                email:cardBean.email
+                email:cardBean.email,
+                buscardtype:cardBean.buscardtype
             });
         }