改进支付业务,增加了办卡业务接口
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java
index e80344a..e11c171 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Subject.java
@@ -104,7 +104,6 @@
   public static final String SUBJNO_PERSONAL_REFUND = "220211";
 
 
-
   //======================= 损益类 =====================//
   /**
    * 手续费收入 - 支付宝充值手续费
@@ -121,6 +120,10 @@
    */
   public static final String SUBJNO_SERVICEFEE_UNIONPAY = "602103";
 
+  /**
+   * 手续费收入 - 默认
+   */
+  public static final String SUBJNO_SERVICEFEE_DEFAULT = "602104";
 
   /**
    * 销售费用 - (消费)折扣优惠款
@@ -137,4 +140,9 @@
    */
   public static final String SUBJNO_MANAGEFEE = "6602";
 
+  /**
+   * 卡成本费
+   */
+  public static final String SUBJNO_CARD_COST = "6025";
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
index b78049f..d1a85b8 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
@@ -30,5 +30,6 @@
 
   public static final int TRANSCODE_ERCHARGE = 3500; //账户充值
 
+  public static final int TRANSCODE_CARD_BIZ = 1007; // 卡务业务
 
 }
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 3688191..271af87 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,35 +1,40 @@
 package com.supwisdom.dlpay.api.controller
 
-import com.supwisdom.dlpay.api.bean.ModifyUserParam
-import com.supwisdom.dlpay.api.bean.OpenUserParam
-import com.supwisdom.dlpay.api.bean.QueryCardsParam
-import com.supwisdom.dlpay.api.bean.QueryUserParam
+import com.supwisdom.dlpay.api.TransactionBuilder
+import com.supwisdom.dlpay.api.bean.*
+import com.supwisdom.dlpay.api.bean.groups.ConfirmAction
+import com.supwisdom.dlpay.api.bean.groups.InitAction
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
-import com.supwisdom.dlpay.api.service.CardService
-import com.supwisdom.dlpay.api.service.KafkaSendMsgService
-import com.supwisdom.dlpay.api.service.UserService
+import com.supwisdom.dlpay.api.service.*
 import com.supwisdom.dlpay.exception.TransactionException
-import com.supwisdom.dlpay.exception.TransactionProcessException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
-import com.supwisdom.dlpay.framework.service.CommonService
+import com.supwisdom.dlpay.framework.util.Subject
+import com.supwisdom.dlpay.framework.util.TradeCode
+import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.http.ResponseEntity
+import org.springframework.validation.annotation.Validated
 import org.springframework.web.bind.annotation.*
 import java.net.URLDecoder
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletResponse
+import javax.validation.Valid
 
 @RestController
 @RequestMapping("/api/user")
 class UserAPIController {
     @Autowired
     private lateinit var useService: UserService
+
+    @Autowired
+    private lateinit var accountUtilServcie: AccountUtilServcie
     @Autowired
     private lateinit var cardService: CardService
     @Autowired
     private lateinit var kafkaSendMsgService: KafkaSendMsgService
 
+    @Autowired
+    private lateinit var transactionService: TransactionServiceProxy
+
 
     @PostMapping("/open")
     fun openAccount(@RequestBody param: OpenUserParam): ResponseEntity<Any> {
@@ -127,16 +132,17 @@
                     .transException(et, "业务处理错误"))
         }
     }
+
     @PostMapping("/querybycardno")
     fun querybycardno(@RequestBody param: QueryUserParam): ResponseEntity<Any> {
         val ret = when (!param.userid.isNullOrEmpty()) {
             true -> cardService.getPersonByUserid(param.userid)
             false -> cardService.getPersonByCardno(param.citizencardno, param.bankcardno)
         }
-        return if(ret.retcode==0){
+        return if (ret.retcode == 0) {
             ResponseEntity.ok(ResponseBodyBuilder.create()
-                    .success(ret,"ok"))
-        }else{
+                    .success(ret, "ok"))
+        } else {
             ResponseEntity.ok(ResponseBodyBuilder.create()
                     .fail(ret.retcode, ret.retmsg))
         }
@@ -145,10 +151,10 @@
     @PostMapping("/querycards")
     fun querycards(@RequestBody param: QueryCardsParam): ResponseEntity<Any> {
         val ret = cardService.getCardsByLastsaveDate(param.starttime, param.endtime)
-        return if(ret.retcode==0){
+        return if (ret.retcode == 0) {
             ResponseEntity.ok(ResponseBodyBuilder.create()
-                    .success(ret,"ok"))
-        }else{
+                    .success(ret, "ok"))
+        } else {
             ResponseEntity.ok(ResponseBodyBuilder.create()
                     .fail(ret.retcode, ret.retmsg))
         }
@@ -156,8 +162,104 @@
 
     @PostMapping("/testmsg")
     fun testmsg(): ResponseEntity<Any> {
-       kafkaSendMsgService.sendJpushMessage("402882816c2727a2016c2728165f0001","交易提醒","你有一笔0.01元的支出,点击查看详情","20190725133506000018", mutableMapOf(),"")
-       return  ResponseEntity.ok(ResponseBodyBuilder.create()
+        kafkaSendMsgService.sendJpushMessage("402882816c2727a2016c2728165f0001", "交易提醒",
+                "你有一笔0.01元的支出,点击查看详情", "20190725133506000018", mutableMapOf(), "")
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
                 .success("ok"))
     }
+
+    @PostMapping("/biz_init")
+    fun userBizInit(@RequestBody @Validated(InitAction::class) request: PublishCardParam): ResponseEntity<Any> {
+        val builder = TransactionBuilder().apply {
+            setTransInfo(request.transdate, request.transtime, TradeCode.TRANSCODE_CARD_BIZ, "balance")
+            setOutTransInfo(request.operid, request.operSeqno)
+            dtltype = "cardservice"
+            description = request.summary
+        }
+        val result = PublishCardResponse()
+
+        val user = useService.findAccountByUserid(request.userid, null)
+                ?: return ResponseBodyBuilder.failEntity(result,
+                        TradeErrorCode.ACCOUNT_NOT_EXISTS,
+                        "用户ID ${request.userid} 不存在")
+
+        if (user.transStatus != TradeDict.STATUS_NORMAL) {
+            return ResponseBodyBuilder.failEntity(result,
+                    TradeErrorCode.ACCOUNT_NOT_EXISTS,
+                    "用户ID ${request.userid} 状态异常")
+        }
+
+        val capitalSubj = accountUtilServcie.readSubject(request.capitalSubjno)
+
+        builder.person(user).apply {
+            setAmount(request.totalAmount / 100.0, TradeDict.TRADE_FLAG_IN)
+            setOpposite(capitalSubj.subjno, capitalSubj.subjname)
+        }
+
+        val depositAmount = request.totalAmount - request.cost - request.cashPledge - request.charge
+
+        if (depositAmount < 0) {
+            return ResponseBodyBuilder.failEntity(result,
+                    TradeErrorCode.INPUT_DATA_ERROR,
+                    "交易金额错误")
+        }
+        if (depositAmount != 0 && request.totalAmount != 0) {
+            if (depositAmount > 0) {
+                builder.addDebitCreditRecord(capitalSubj.subjno, capitalSubj.subjname,
+                        user.accno, Subject.SUBJNO_PERSONAL_DEPOSIT, request.totalAmount / 100.0, request.summary)
+            }
+            val transDesc = arrayListOf<String>()
+            if (request.cost > 0) {
+                val subject = accountUtilServcie.readSubject(Subject.SUBJNO_CARD_COST)
+                builder.addDebitCreditRecord(user.accno, Subject.SUBJNO_PERSONAL_DEPOSIT,
+                        subject.subjno, subject.subjno, request.cost / 100.0,
+                        request.summary)
+                transDesc.add("卡成本费" + "%.2f".format(request.cost / 100.0) + " 元")
+
+            }
+            if (request.cashPledge > 0) {
+                val subject = accountUtilServcie.readSubject(Subject.SUBJNO_FOREGIFT)
+                builder.addDebitCreditRecord(user.accno, Subject.SUBJNO_PERSONAL_DEPOSIT,
+                        subject.subjno, subject.subjno, request.cashPledge / 100.0,
+                        request.summary)
+                transDesc.add("卡押金" + "%.2f".format(request.cashPledge / 100.0) + " 元")
+            }
+            if (request.charge > 0) {
+                val subject = accountUtilServcie.readSubject(Subject.SUBJNO_SERVICEFEE_DEFAULT)
+                builder.addDebitCreditRecord(user.accno, Subject.SUBJNO_PERSONAL_DEPOSIT,
+                        subject.subjno, subject.subjno, request.charge / 100.0,
+                        request.summary)
+                transDesc.add("手续费" + "%.2f".format(request.charge / 100.0) + " 元")
+            }
+            builder.description += transDesc.joinToString(";")
+        }
+        val transaction = transactionService.init(builder)
+
+        result.apply {
+            accdate = transaction.accdate
+            refno = transaction.refno
+            description = builder.description
+        }
+        return ResponseBodyBuilder.successEntity(result, "${request.summary}初始化成功")
+    }
+
+    @PostMapping("/biz_confirm")
+    fun userBizConfirm(@RequestBody @Validated(ConfirmAction::class) request: PublishCardParam): ResponseEntity<Any> {
+        val transaction = transactionService.success(request.refno)
+        val response = PublishCardResponse().apply {
+            accdate = transaction.accdate
+            refno = transaction.refno
+        }
+        return ResponseBodyBuilder.successEntity(response, "${request.summary}确认成功")
+    }
+
+    @PostMapping("/biz_refund")
+    fun userBizRefund(@RequestBody @Valid request: PublishCardParam): ResponseEntity<Any> {
+        return ResponseEntity.ok(ResponseBodyBuilder.create().success())
+    }
+
+    @GetMapping("/biz_query")
+    fun userBizQuery(@RequestBody @Valid request: PublishCardParam): ResponseEntity<Any> {
+        return ResponseEntity.ok(ResponseBodyBuilder.create().success())
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt
index 1f63e38..c9d61a1 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt
@@ -8,6 +8,7 @@
 import com.supwisdom.dlpay.exception.TransactionException
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import mu.KotlinLogging
+import org.springframework.http.ResponseEntity
 
 
 class ResponseBodyBuilder private constructor() {
@@ -16,6 +17,14 @@
         private val RESERVED_KEY = setOf("retcode", "retmsg")
         private val LOGGER = KotlinLogging.logger {}
         fun create() = ResponseBodyBuilder()
+
+        fun successEntity(bean: ApiResponse, msg: String? = null): ResponseEntity<Any> {
+            return ResponseEntity.ok(create().success(bean, msg))
+        }
+
+        fun failEntity(bean: ApiResponse, code: Int, msg: String): ResponseEntity<Any> {
+            return ResponseEntity.ok(create().fail(bean, code, msg))
+        }
     }
 
     private var retCode = INVALIDE_RETCODE
@@ -44,6 +53,7 @@
         return bean
     }
 
+
     fun fail(code: Int, msg: String): Map<String, Any> {
         if (code == 0) {
             throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "错误码未正确定义")
diff --git a/payapi/src/main/resources/data.sql b/payapi/src/main/resources/data.sql
index 32cfd2f..b50b1cd 100644
--- a/payapi/src/main/resources/data.sql
+++ b/payapi/src/main/resources/data.sql
@@ -501,6 +501,10 @@
 INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
 VALUES (26, '602103', 2, 'n', 1, '6021', 20190430, 2, '银联充值手续费', 6, '{tenantid}');
 INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
+VALUES (32, '602104', 2, 'n', 1, '6021', 20190430, 2, '收手续费', 6, '{tenantid}');
+INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
+VALUES (31, '6025', 2, 'y', 0, NULL, 20190430, 1, '卡成本费收入', 6, '{tenantid}');
+INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
 VALUES (27, '6601', 2, 'y', 0, NULL, 20190430, 1, '销售费用', 6, '{tenantid}');
 INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
 VALUES (28, '660101', 2, 'y', 1, '6601', 20190430, 2, '折扣优惠款', 6, '{tenantid}');
@@ -667,6 +671,8 @@
 VALUES (29, 'canteen', 'dtltypeList', '食堂就餐', '流水类型', '{tenantid}');
 INSERT INTO "tb_dictionary" ("id", "dictval", "dicttype", "dictcaption", "dicttypename", "tenantid")
 VALUES (30, 'shopmarket', 'dtltypeList', '商超消费', '流水类型', '{tenantid}');
+INSERT INTO "tb_dictionary" ("id", "dictval", "dicttype", "dictcaption", "dicttypename", "tenantid")
+VALUES (31, 'cardservice', 'dtltypeList', '卡务流水', '流水类型', '{tenantid}');