From bb55ebad1b27ee0977eeaf06d56e3a4a930be45f Mon Sep 17 00:00:00 2001 From: Tang Cheng Date: Wed, 22 May 2019 16:54:56 +0800 Subject: [PATCH] =?utf8?q?=E5=88=9D=E6=AD=A5=E6=B5=8B=E8=AF=95=E4=BA=A4?= =?utf8?q?=E6=98=93=E8=AE=B0=E8=B4=A6=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../dlpay/api/domain/TPersondtl.java | 22 -- .../supwisdom/dlpay/api/domain/TShopdtl.java | 11 + .../dlpay/api/domain/TTransactionMain.java | 31 ++- .../dlpay/framework/util/TradeDict.java | 16 +- .../com/supwisdom/dlpay/api/ThirdPayCall.kt | 1 + .../kotlin/com/supwisdom/dlpay/api/advices.kt | 16 ++ .../api/controller/consume_api_controller.kt | 6 +- .../dlpay/api/repositories/repository_impl.kt | 2 +- .../service/impl/transaction_service_impl.kt | 241 +++++++++++++----- .../dlpay/api/transaction_builder.kt | 101 ++------ .../dlpay/framework/framework_util.kt | 6 + 11 files changed, 279 insertions(+), 174 deletions(-) diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java b/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java index 3713fe49..376b528a 100644 --- a/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java +++ b/src/main/java/com/supwisdom/dlpay/api/domain/TPersondtl.java @@ -77,12 +77,6 @@ public class TPersondtl { @Column(name = "REMARK", length = 240) private String remark; - @Column(name = "CREATETIME", length = 14) - private String createtime; //创建时间 - - @Column(name = "ENDTIME", length = 14) - private String endtime; //支付结束时间 - public String getRefno() { return refno; } @@ -235,22 +229,6 @@ public class TPersondtl { this.remark = remark; } - public String getCreatetime() { - return createtime; - } - - public void setCreatetime(String createtime) { - this.createtime = createtime; - } - - public String getEndtime() { - return endtime; - } - - public void setEndtime(String endtime) { - this.endtime = endtime; - } - public String getUserName() { return userName; } diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java b/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java index 2078c990..14dcb5d4 100644 --- a/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java +++ b/src/main/java/com/supwisdom/dlpay/api/domain/TShopdtl.java @@ -39,6 +39,9 @@ public class TShopdtl { @Column(name = "payinfo", length = 200) private String payInfo; + @Column(name = "tradeflag", length = 6) + private String tradeflag; + @Column(name = "status", length = 20) private String status; @@ -151,4 +154,12 @@ public class TShopdtl { public void setTradeCode(Integer tradeCode) { this.tradeCode = tradeCode; } + + public String getTradeflag() { + return tradeflag; + } + + public void setTradeflag(String tradeflag) { + this.tradeflag = tradeflag; + } } diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java b/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java index c60c6217..6c7507d2 100644 --- a/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java +++ b/src/main/java/com/supwisdom/dlpay/api/domain/TTransactionMain.java @@ -4,6 +4,7 @@ import com.supwisdom.dlpay.framework.domain.TSubject; import javax.persistence.*; +import java.sql.Timestamp; import java.util.List; import static javax.persistence.FetchType.LAZY; @@ -39,22 +40,28 @@ public class TTransactionMain { @Column(name = "outid", length = 60) private String outId; + @Column(name = "create_time") + private Timestamp createTime; + + @Column(name = "end_time") + private Timestamp endTime; + @Column(name = "reverse_flag", nullable = false, length = 10) private String reverseFlag = "none"; - @OneToOne(targetEntity = TPersondtl.class, fetch = LAZY) + @OneToOne(targetEntity = TPersondtl.class, fetch = LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "refno", referencedColumnName = "refno") private TPersondtl personDtl; - @OneToOne(targetEntity = TShopdtl.class, fetch = LAZY) + @OneToOne(targetEntity = TShopdtl.class, fetch = LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "refno", referencedColumnName = "refno") private TShopdtl shopDtl; - @OneToOne(targetEntity = TSubjectdtl.class, fetch = LAZY) + @OneToOne(targetEntity = TSubjectdtl.class, fetch = LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "refno", referencedColumnName = "refno") private TSubjectdtl subjectDtl; - @OneToMany(targetEntity = TDebitCreditDtl.class, fetch = LAZY) + @OneToMany(targetEntity = TDebitCreditDtl.class, fetch = LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "refno", referencedColumnName = "refno") private List details; @@ -162,4 +169,20 @@ public class TTransactionMain { public void setDetails(List details) { this.details = details; } + + public Timestamp getCreateTime() { + return createTime; + } + + public void setCreateTime(Timestamp createTime) { + this.createTime = createTime; + } + + public Timestamp getEndTime() { + return endTime; + } + + public void setEndTime(Timestamp endTime) { + this.endTime = endTime; + } } diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java b/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java index ed6db07b..c786deab 100644 --- a/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java +++ b/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java @@ -1,5 +1,7 @@ package com.supwisdom.dlpay.framework.util; +import org.jetbrains.annotations.Nullable; + public class TradeDict { /** * 状态: @@ -34,8 +36,8 @@ public class TradeDict { public static final String DTL_STATUS_NONE = "none"; - public static final String TRADE_FLAG_DEPOSIT = "deposit"; - public static final String TRADE_FLAG_PAY = "pay"; + public static final String TRADE_FLAG_OUT = "out"; + public static final String TRADE_FLAG_IN = "in"; /** * 交易借方 */ @@ -65,4 +67,14 @@ public class TradeDict { public static final String PAYTYPE_RECHARGE_COUPON = "coupon"; // 充值优惠 public static final String PAYTYPE_RECHARGE_SERVICEFEE = "servicefee"; //收服务费 + + /** + * reverse flag + * - none : 无 + * - cancel : 冲正 + * - reverse : 手工撤销 + */ + public static final String REVERSE_FLAG_NONE = "none"; + public static final String REVERSE_FLAG_CANCEL = "cancel"; + public static final String REVERSE_FLAG_REVERSE = "reverse"; } diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt b/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt index 4f06db87..3a03934a 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/ThirdPayCall.kt @@ -237,6 +237,7 @@ class CallService { fun CallCitizenCardPay(config: Map, paydtl: TShopdtl): CallBackResp { val resp = CallBackResp() + resp.retcode = "0" // TODO: 代扣逻辑 return resp } diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt b/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt index 47eb0435..f96ba95c 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt @@ -1,10 +1,26 @@ package com.supwisdom.dlpay.api +import com.supwisdom.dlpay.framework.ResponseBodyBuilder +import com.supwisdom.dlpay.framework.util.TradeErrorCode import org.aspectj.lang.JoinPoint import org.aspectj.lang.annotation.Aspect import org.aspectj.lang.annotation.Before import org.aspectj.lang.annotation.Pointcut +import org.springframework.http.ResponseEntity import org.springframework.stereotype.Component +import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.bind.annotation.RestControllerAdvice + + +@RestControllerAdvice +class RestControllerAdvice { + + @ExceptionHandler + fun handleException(ex: Exception): ResponseEntity { + return ResponseEntity.ok().body(ResponseBodyBuilder.create() + .exception(TradeErrorCode.BUSINESS_DEAL_ERROR, ex.cause)) + } +} @Component @Aspect diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt index 0d8007a6..bfa6eac7 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt @@ -217,15 +217,19 @@ class ConsumeController { transTime = param.transtime paytype = TradeDict.PAYTYPE_CITIZEN_CARD payinfo = "市民卡代扣消费" + outId = shopacc.shopaccno + outtradeno = param.billno }.person(account).apply { amount = param.amount / 100.0 opposite = AccountProxy(shopacc) - tradeflag = TradeDict.TRADE_FLAG_PAY + description = "市民卡代扣消费" summary = "市民卡代扣消费" + tradeOut() }.and().shop(shopacc).apply { amount = param.amount / 100.0 opposite = AccountProxy(account) summary = "市民卡代扣消费" + tradeIn() }.and().addDebitCreditRecord(AccountProxy(subject), AccountProxy(account), param.amount / 100.0, "市民卡代扣消费") .addDebitCreditRecord(AccountProxy(account), AccountProxy(shopacc), diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/repositories/repository_impl.kt b/src/main/kotlin/com/supwisdom/dlpay/api/repositories/repository_impl.kt index 5c557d3a..21d03249 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/repositories/repository_impl.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/repositories/repository_impl.kt @@ -62,7 +62,7 @@ class ShopaccRepositoryImpl : TShopaccRepository { ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "交易流水<${dtl.refno}>商户账户不存在") - val query = entityManager.createQuery("update TShopacc c set c.balance=c.balance-?1" + + val query = entityManager.createQuery("update TShopacc c set c.balance=c.balance+?1" + " where c.shopaccno=?2 and c.balance=?3") query.setParameter(1, amount) .setParameter(2, dtl.shopaccno) diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt index f8ece693..4e355cf5 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt @@ -5,51 +5,27 @@ import com.supwisdom.dlpay.api.dao.* import com.supwisdom.dlpay.api.domain.* import com.supwisdom.dlpay.api.repositories.ShopaccRepositoryImpl import com.supwisdom.dlpay.api.repositories.TAccountRepositoryImpl -import com.supwisdom.dlpay.api.service.PersonAccountService import com.supwisdom.dlpay.api.service.TransactionService +import com.supwisdom.dlpay.exception.TransactionCheckException import com.supwisdom.dlpay.exception.TransactionProcessException import com.supwisdom.dlpay.framework.service.SystemUtilService -import com.supwisdom.dlpay.framework.util.Subject import com.supwisdom.dlpay.framework.util.TradeDict import com.supwisdom.dlpay.framework.util.TradeErrorCode import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service import java.sql.SQLException -import javax.transaction.Transactional +import java.sql.Timestamp -open class PersonAccountServiceImpl : PersonAccountService { - @Transactional - override fun recalcBalance(account: TAccount, amount: Double) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } -} - @Service class TransactionServiceImpl : TransactionService { - companion object { - val INIT_DTL_STATUS = setOf(TradeDict.DTL_STATUS_INIT, TradeDict.DTL_STATUS_WIP) - } - @Autowired lateinit var transactionMainDao: TransactionMainDao - @Autowired - lateinit var accoutDao: AccountDao - @Autowired lateinit var persondtlDao: PersondtlDao - @Autowired - lateinit var shopdtlDao: ShopdtlDao - - @Autowired - lateinit var subjectdtlDao: SubjectdtlDao - - @Autowired - lateinit var debitCreditDtlDao: DebitCreditDtlDao - @Autowired lateinit var accountRepository: TAccountRepositoryImpl @@ -59,12 +35,91 @@ class TransactionServiceImpl : TransactionService { @Autowired lateinit var systemUtilService: SystemUtilService + private fun preCheck(builder: TransactionBuilder) { + if (builder.outId.isNotEmpty() && builder.outtradeno.isEmpty()) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "第三方账号未指定第三方流水号") + } + + if (builder.transDate.length != 8 || builder.transTime.length != 6) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "交易发生日期错误") + } + + if (builder.transCode <= 0) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "交易码错误") + } + + if (builder.hasPerson()) { + builder.person().also { + if (!it.hasOpposite()) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "个人交易对方账户未设置") + } + if (it.payinfo.isEmpty() || it.paytype.isEmpty()) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "个人交易信息未设置") + } + when (it.tradeFlag()) { + TradeDict.TRADE_FLAG_IN -> { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "不支持的交易") + } + TradeDict.TRADE_FLAG_OUT -> { + if (builder.reverseFlag != TradeDict.REVERSE_FLAG_NONE && it.amount > 0) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "消费冲正交易,余额不能大于0") + } else if (builder.reverseFlag == TradeDict.REVERSE_FLAG_NONE && it.amount < 0) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "消费交易,余额不能小于0") + } + } + else -> { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "个人交易方向未设置") + } + } + + } + } + + if (builder.hasShop()) { + builder.shop().also { + if (!it.hasOpposite()) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "商户交易对方账户未设置") + } + when (it.tradeFlag()) { + TradeDict.TRADE_FLAG_IN -> { + if (it.amount < 0) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "商户收入交易金额不能小于0") + } + } + TradeDict.TRADE_FLAG_OUT -> { + if (it.amount > 0) { + throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "商户支出交易金额不能小于0") + } + } + else -> throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, + "商户交易方向未设置") + } + } + } + } + private fun builderRecords(builder: TransactionBuilder, status: String): TTransactionMain { - // 记录三方的交易流水(个人,商户,科目) try { + preCheck(builder) + // 记录三方的交易流水(个人,商户,科目) val transaction = TTransactionMain().apply { refno = systemUtilService.refno accdate = systemUtilService.accdate + outTradeNo = builder.outtradeno + outId = builder.outId + createTime = Timestamp(systemUtilService.sysdatetime.sysdate.time) } @@ -73,17 +128,25 @@ class TransactionServiceImpl : TransactionService { this.refno = transaction.refno this.accdate = transaction.accdate userid = builder.person().person.userid + accountNo = builder.person().person.accno userName = builder.person().person.accname + outtradeno = builder.outtradeno transdate = builder.transDate transtime = builder.transTime befbal = builder.person().person.availbal - amount = builder.person().amount + amount = if (builder.person().tradeFlag() == TradeDict.TRADE_FLAG_IN) { + builder.person().amount + } else { + -builder.person().amount + } paytype = builder.person().paytype payinfo = builder.person().payinfo transcode = builder.transCode - tradeflag = builder.person().tradeflag + tradeflag = builder.person().tradeFlag() + transdesc = builder.person().description oppositeAccNo = builder.person().opposite.getAccountNo() oppositeAccName = builder.person().opposite.getAccountName() + reverseFlag = builder.reverseFlag this.status = status }.also { // save persondtl @@ -102,6 +165,12 @@ class TransactionServiceImpl : TransactionService { this.transDate = builder.transDate this.transTime = builder.transTime this.tradeCode = builder.transCode + amount = if (builder.shop().tradeFlag() == TradeDict.TRADE_FLAG_IN) { + builder.shop().amount + } else { + -builder.shop().amount + } + this.tradeflag = builder.shop().tradeFlag() this.shopaccno = builder.shop().shopacc.shopaccno this.shopname = builder.shop().shopacc.shopname this.oppositeAccNo = builder.shop().opposite.getAccountNo() @@ -151,8 +220,9 @@ class TransactionServiceImpl : TransactionService { if (builder.hasPerson()) { + val dc = getDebitOrCredit(builder.person().tradeFlag()) sumBalanceFromDetails(transaction.details, builder.person().person.accno, - builder.person().person.subjno, "debit").also { + builder.person().person.subjno, 2, dc).also { if (transaction.personDtl.amount != it) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "输入金额错误,个人余额不符<${transaction.personDtl.amount}>") @@ -161,8 +231,9 @@ class TransactionServiceImpl : TransactionService { } if (builder.hasShop()) { + val dc = getDebitOrCredit(builder.shop().tradeFlag()) sumBalanceFromDetails(transaction.details, builder.shop().shopacc.shopaccno, - builder.shop().shopacc.subjno, "both").also { + builder.shop().shopacc.subjno, 2, dc).also { if (transaction.shopDtl.amount != it) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "输入金额错误,商户余额不符<${transaction.shopDtl.amount}>") @@ -172,7 +243,9 @@ class TransactionServiceImpl : TransactionService { if (builder.hasSubject()) { sumBalanceFromDetails(transaction.details, builder.subject().subject.subjno, - transaction.subjectDtl.subjectno, "both").also { + transaction.subjectDtl.subjectno, + builder.subject().subject.balflag, + "both").also { if (transaction.subjectDtl.amount != it) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "输入金额错误,科目余额不符<${transaction.subjectDtl.amount}>") @@ -180,6 +253,7 @@ class TransactionServiceImpl : TransactionService { } } + transaction.status = status transactionMainDao.save(transaction) return transaction } catch (ex: SQLException) { @@ -187,6 +261,14 @@ class TransactionServiceImpl : TransactionService { } } + private fun getDebitOrCredit(tradeFlag: String): String { + return when (tradeFlag) { + TradeDict.TRADE_FLAG_IN -> "credit" + TradeDict.TRADE_FLAG_OUT -> "debit" + else -> "both" + } + } + override fun init(builder: TransactionBuilder): TTransactionMain { return builderRecords(builder, TradeDict.DTL_STATUS_INIT) } @@ -197,6 +279,7 @@ class TransactionServiceImpl : TransactionService { private fun sumBalanceFromDetails(details: List, accno: String, subjno: String, + balanceFlag: Int, debitOrCredit: String = "debit"): Double { val debitAmount = details.sumByDouble { line -> @@ -214,57 +297,64 @@ class TransactionServiceImpl : TransactionService { } } return when (debitOrCredit) { - "debit" -> debitAmount - "credit" -> creditAmount + "debit" -> { + if (balanceFlag == 2) debitAmount * -1.0 else debitAmount + } + "credit" -> { + if (balanceFlag == 2) creditAmount else creditAmount * -1.0 + } "both" -> creditAmount - debitAmount else -> throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "结算借贷方向余额错误") } } - override fun wip(refno: String): TTransactionMain { - val transaction = transactionMainDao.findById(refno).let { - if (it.isPresent) it.get() else null - } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>参考号错误") - - if (transaction.status != TradeDict.DTL_STATUS_INIT) { - throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误") - } + private fun updateRecordStatus(transaction: TTransactionMain, status: String) { if (transaction.person) { - persondtlDao.findById(refno).let { - if (!it.isPresent) it.get() else null - }?.also { - if (it.status != TradeDict.DTL_STATUS_INIT) { - throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "个人流水<$refno>状态错误") + transaction.personDtl?.also { + if (it.status != transaction.status) { + throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, + "个人流水<${transaction.refno}>状态错误") } - it.status = TradeDict.DTL_STATUS_WIP - persondtlDao.save(it) - } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, "个人流水<$refno>不存在") + it.status = status + } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, + "个人流水<${transaction.refno}>不存在") } if (transaction.shop) { - shopdtlDao.findById(refno).let { - if (it.isPresent) it.get() else null - }?.also { - if (it.status != TradeDict.DTL_STATUS_INIT) { - throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "商户流水<$refno>状态错误") + transaction.shopDtl?.also { + if (it.status != transaction.status) { + throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, + "商户流水<${transaction.refno}>状态错误") } - it.status = TradeDict.DTL_STATUS_WIP - shopdtlDao.save(it) - } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, "商户流水<$refno>不存在") + it.status = status + } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, + "商户流水<${transaction.refno}>不存在") } if (transaction.subject) { - subjectdtlDao.findById(refno).let { - if (it.isPresent) it.get() else null - }?.also { - if (it.status != TradeDict.DTL_STATUS_INIT) { - throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "科目流水<$refno>状态错误") + transaction.subjectDtl?.also { + if (it.status != transaction.status) { + throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, + "科目流水<${transaction.refno}>状态错误") } - it.status = TradeDict.DTL_STATUS_WIP - subjectdtlDao.save(it) - } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, "科目流水<$refno>不存在") + it.status = status + } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, + "科目流水<${transaction.refno}>不存在") + } + transaction.status = status + } + + override fun wip(refno: String): TTransactionMain { + val transaction = transactionMainDao.findByRefnoForUpdate(refno) + ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>参考号错误") + + if (transaction.status != TradeDict.DTL_STATUS_INIT + && transaction.status != TradeDict.DTL_STATUS_WIP) { + throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误") } + + updateRecordStatus(transaction, TradeDict.DTL_STATUS_WIP) transactionMainDao.save(transaction) return transaction } @@ -278,7 +368,8 @@ class TransactionServiceImpl : TransactionService { throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误") } - transaction.status = TradeDict.DTL_STATUS_FAIL + updateRecordStatus(transaction, TradeDict.DTL_STATUS_FAIL) + transaction.endTime = Timestamp(systemUtilService.sysdatetime.sysdate.time) transactionMainDao.save(transaction) return transaction } @@ -292,25 +383,35 @@ class TransactionServiceImpl : TransactionService { if (transaction.status in errorStatus) { throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误") } - transaction.status = TradeDict.DTL_STATUS_FAIL + transaction.status = TradeDict.DTL_STATUS_SUCCESS if (transaction.person) { // update account balance transaction.personDtl?.let { - accountRepository.recalcAccountBalance(it, it.amount, false) + if (accountRepository.recalcAccountBalance(it, it.amount, false) != 1) { + throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY, + "个人账户交易冲突") + } } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, "个人流水<${transaction.refno}>不存在") + transaction.personDtl.status = TradeDict.DTL_STATUS_SUCCESS } if (transaction.shop) { // update shop balance transaction.shopDtl?.let { - shopaccRepository.recalcShopBalance(it, it.amount, false) + if (shopaccRepository.recalcShopBalance(it, it.amount, false) != 1) { + throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY, + "商户账户交易冲突") + } } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, "商户流水<${transaction.refno}>不存在") + transaction.shopDtl.status = TradeDict.DTL_STATUS_SUCCESS } if (transaction.subject) { // update subject balance } + + transaction.endTime = Timestamp(systemUtilService.sysdatetime.sysdate.time) transactionMainDao.save(transaction) return transaction } diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt b/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt index 847aab89..40abd488 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt @@ -22,9 +22,34 @@ open class SubTransactionBuilder(val parent: TransactionBuilder) { return if (field.isEmpty()) parent.payinfo else field } + + lateinit var opposite: AccountProxy<*> + + fun hasOpposite(): Boolean { + return this::opposite.isInitialized + } + fun and(): TransactionBuilder { return parent } + + private var balanceInOut: String = "" + + fun tradeIn(): SubTransactionBuilder { + this.balanceInOut = TradeDict.TRADE_FLAG_IN + return this + } + + fun tradeOut(): SubTransactionBuilder { + this.balanceInOut = TradeDict.TRADE_FLAG_OUT + return this + } + + fun tradeFlag(): String { + return this.balanceInOut + } + + } class PersonTranactionBuilder(parent: TransactionBuilder, val person: TAccount) @@ -32,8 +57,6 @@ class PersonTranactionBuilder(parent: TransactionBuilder, val person: TAccount) var amount: Double = 0.0 var summary: String = "" var description: String = "" - var tradeflag : String = "" - lateinit var opposite: AccountProxy<*> } @@ -41,14 +64,12 @@ class ShopTransactionBuilder(parent: TransactionBuilder, val shopacc: TShopacc) : SubTransactionBuilder(parent) { var amount: Double = 0.0 var summary: String = "" - lateinit var opposite: AccountProxy<*> } class SubjectTransactionBuilder(parent: TransactionBuilder, val subject: TSubject) : SubTransactionBuilder(parent) { var amount: Double = 0.0 var summary: String = "" - lateinit var opposite: AccountProxy<*> } @@ -107,6 +128,8 @@ class TransactionBuilder { var paytype: String = "" var payinfo: String = "" var outtradeno: String = "" //第三方流水号 + var outId: String = "" + var reverseFlag: String = "none" fun person(): PersonTranactionBuilder { return this.personBuilder @@ -181,73 +204,3 @@ class TransactionBuilder { return transactionService.wip(this) } } - -class TransactionExample { - companion object { - fun exampleInit(accountUtilServcie: AccountUtilServcie, - service: TransactionService, - userid: String, shopid: Int, amount: Int, manageFee: Int, - transDate: String, transTime: String, payType: String) { - - val person = accountUtilServcie.readAccount(userid) - val shop = accountUtilServcie.readShopAcc(shopid) - - val builder = TransactionBuilder().apply { - this.transDate = transDate - this.transTime = transTime - this.transCode = 3001 - this.payinfo = "POS消费" - this.paytype = payType - }.person(person).apply { - this.amount = (amount + manageFee) / 100.0 // 金额考虑减和加 - this.summary = "POS消费" - this.opposite = AccountProxy(shop) - this.tradeflag = TradeDict.TRANS_DIRECTION_CREDIT - }.and().shop(shop).apply { - this.amount = amount / 100.0 // 金额考虑减和加 - this.summary = "POS消费" - this.opposite = AccountProxy(person) - }.and() - - if (payType == "balance") { - builder.addDebitCreditRecord(AccountProxy(person), AccountProxy(shop), - amount / 100.0, "POS消费") - if (manageFee > 0) { - val subject = accountUtilServcie.readSubject("2001") - builder.subject(subject).apply { - this.amount = manageFee / 100.0 // 金额考虑减和加 - this.summary = "POS消费搭伙费" - this.opposite = AccountProxy(person) - }.and().addDebitCreditRecord(AccountProxy(person), AccountProxy(subject), manageFee / 100.0, - "POS消费搭伙费") - } - } else if (payType == "wechat") { - accountUtilServcie.readSubject(Subject.SUBJNO_PAY_WECHAT).also { - builder.addDebitCreditRecord(AccountProxy(it), AccountProxy(person), - (amount + manageFee) / 100.0, "微信转账") - .addDebitCreditRecord(AccountProxy(person), AccountProxy(shop), - amount / 100.0, "微信支付消费") - } - - if (manageFee > 0) { - accountUtilServcie.readSubject("2001").also { - builder.subject(it).apply { - this.amount = manageFee / 100.0 // 金额考虑减和加 - this.summary = "微信支付消费搭伙费" - this.opposite = AccountProxy(person) - }.and().addDebitCreditRecord(AccountProxy(person), AccountProxy(it), manageFee / 100.0, - "微信支付消费搭伙费") - } - } - } else { - throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "不支持的支付方式") - } - val result = builder.init(service) - println(result.refno) - } - - fun exampleConfirm(refno: String, transactionService: TransactionService) { - transactionService.success(refno) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt b/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt index 2137335e..b35904bf 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt @@ -50,6 +50,12 @@ class ResponseBodyBuilder private constructor() { return build() } + fun exception(code: Int, cause: Throwable?, msg: String? = null): Map { + data("exception", cause?.message ?: "unkonw excpetion") + result(code, msg) + return build() + } + fun transException(exception: TransactionException, msg: String): Map { data("exception", exception.message!!) result(exception.code(), "$msg - [${exception.message}]") -- 2.17.1