编写新交易流程测试代码
diff --git a/build.gradle b/build.gradle
index 350290f..5af099d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -38,6 +38,9 @@
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
+ implementation 'com.github.chenhaiyangs:rpc-tcc-transaction-spring:1.2.0'
+ implementation 'com.github.chenhaiyangs:rpc-tcc-transaction-api:1.1.0'
+ implementation 'com.github.chenhaiyangs:rpc-tcc-transaction-core:1.2.0'
implementation 'org.postgresql:postgresql:42.2.5'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'com.jcabi:jcabi-manifests:1.1'
diff --git a/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java b/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java
index 8d3130d..733a6c2 100644
--- a/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java
+++ b/src/main/java/com/supwisdom/dlpay/api/dao/AccountDao.java
@@ -34,9 +34,5 @@
@Query("select a from TAccount a where a.userid = ?1 and a.subjno=?2")
TAccount findByUseridAndSubjno(String userid, String subjno);
- @Modifying
- @Query("update TAccount t set t.availbal=t.availbal-?3 , t.balance=t.balance-?3 where t.accno=?1 and t.availbal=?2")
- int updateAccountBalance(String accno, Double availbal, Double amount);
-
Page<TAccount> findAllByAccnameContaining(String accname, Pageable pageable);
}
diff --git a/src/main/java/com/supwisdom/dlpay/api/repositories/TAccountRepository.java b/src/main/java/com/supwisdom/dlpay/api/repositories/TAccountRepository.java
index d999a27..222391f 100644
--- a/src/main/java/com/supwisdom/dlpay/api/repositories/TAccountRepository.java
+++ b/src/main/java/com/supwisdom/dlpay/api/repositories/TAccountRepository.java
@@ -1,5 +1,12 @@
package com.supwisdom.dlpay.api.repositories;
+import com.supwisdom.dlpay.api.domain.TAccount;
+import com.supwisdom.dlpay.api.domain.TPersondtl;
+
public interface TAccountRepository {
- int updateAccountBalance(String accno, Double avaibal, Double amount);
+ int recalcAccountBalance(String accno, Double avaibal, Double amount, boolean overdraft);
+
+ int recalcAccountBalance(TAccount account, Double amount, boolean overdraft);
+
+ int recalcAccountBalance(TPersondtl dtl, Double amount, boolean overdraft);
}
diff --git a/src/main/java/com/supwisdom/dlpay/api/repositories/TShopaccRepository.java b/src/main/java/com/supwisdom/dlpay/api/repositories/TShopaccRepository.java
new file mode 100644
index 0000000..291bd1c
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/api/repositories/TShopaccRepository.java
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.api.repositories;
+
+import com.supwisdom.dlpay.api.domain.TShopdtl;
+
+public interface TShopaccRepository {
+ int recalcShopBalance(TShopdtl dtl, Double amount, boolean overdraft);
+}
diff --git a/src/main/java/com/supwisdom/dlpay/api/repositories/impl/TAccountRepositoryImpl.java b/src/main/java/com/supwisdom/dlpay/api/repositories/impl/TAccountRepositoryImpl.java
deleted file mode 100644
index 029e85f..0000000
--- a/src/main/java/com/supwisdom/dlpay/api/repositories/impl/TAccountRepositoryImpl.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.supwisdom.dlpay.api.repositories.impl;
-
-import com.supwisdom.dlpay.api.domain.TAccount;
-import com.supwisdom.dlpay.api.repositories.TAccountRepository;
-import org.springframework.stereotype.Repository;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-
-@Repository
-@Transactional
-public class TAccountRepositoryImpl implements TAccountRepository {
-
- @PersistenceContext
- private EntityManager em;
-
- @Override
- public int updateAccountBalance(String accno, Double avaibal, Double amount) {
-
- TAccount account = em.find(TAccount.class, accno);
- if (account == null) {
- return 0;
- }
-
-
-
- return 0;
- }
-}
diff --git a/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index 580ee13..941e6b1 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -1,5 +1,6 @@
package com.supwisdom.dlpay
+import com.fasterxml.jackson.databind.ser.std.StringSerializer
import io.lettuce.core.ReadFrom
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.SpringBootApplication
@@ -61,6 +62,13 @@
template.setConnectionFactory(connectionFactory)
return template
}
+
+ @Bean
+ fun longValueRedisTemplate(connectionFactory: RedisConnectionFactory): RedisTemplate<String, Long> {
+ val template = RedisTemplate<String, Long>()
+ template.keySerializer = StringRedisSerializer()
+ return template
+ }
}
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
new file mode 100644
index 0000000..5c557d3
--- /dev/null
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/repositories/repository_impl.kt
@@ -0,0 +1,72 @@
+package com.supwisdom.dlpay.api.repositories
+
+import com.supwisdom.dlpay.api.domain.TAccount
+import com.supwisdom.dlpay.api.domain.TPersondtl
+import com.supwisdom.dlpay.api.domain.TShopdtl
+import com.supwisdom.dlpay.exception.TransactionProcessException
+import com.supwisdom.dlpay.framework.domain.TShopacc
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import org.springframework.stereotype.Repository
+import org.springframework.transaction.annotation.Transactional
+import javax.persistence.EntityManager
+import javax.persistence.PersistenceContext
+
+@Repository
+@Transactional
+class TAccountRepositoryImpl : TAccountRepository {
+
+ @PersistenceContext
+ private lateinit var entityManager: EntityManager
+
+ override fun recalcAccountBalance(accno: String, avaibal: Double, amount: Double, overdraft: Boolean): Int {
+ val account = entityManager.find(TAccount::class.java, accno) ?: return 0
+ if (avaibal.compareTo(account.availbal!!) != 0) {
+ throw TransactionProcessException(TradeErrorCode.ACCOUNT_TRADE_BUSY,
+ "账户余额已被更新")
+ }
+
+ //1. 从 redis 读取账户余额
+ //2. 没有记录时,读取数据库余额并存入 redis ,如果返回已存在,读取redis 余额
+ //3. 扣除 redis 中余额
+ val query = entityManager.createQuery("update TAccount a set a.availbal=a.availbal+?1, a.balance=a.balance+?1 " +
+ "where a.accno=?2 and a.availbal=?3")
+ ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR, "更新个人账户余额错误")
+
+ query.setParameter(1, amount)
+ .setParameter(2, accno)
+ .setParameter(3, avaibal)
+ return query.executeUpdate()
+ }
+
+ override fun recalcAccountBalance(account: TAccount, amount: Double, overdraft: Boolean): Int {
+ return recalcAccountBalance(account.accno, account.availbal, amount, overdraft)
+ }
+
+ override fun recalcAccountBalance(dtl: TPersondtl, amount: Double, overdraft: Boolean): Int {
+ return entityManager.find(TAccount::class.java, dtl.accountNo)?.let {
+ recalcAccountBalance(it, amount, overdraft)
+ } ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
+ "交易流水<${dtl.refno}>未找到指定个人账户")
+ }
+}
+
+@Repository
+@Transactional
+class ShopaccRepositoryImpl : TShopaccRepository {
+
+ @PersistenceContext
+ private lateinit var entityManager: EntityManager
+
+ override fun recalcShopBalance(dtl: TShopdtl, amount: Double, overdraft: Boolean): Int {
+ val shopacc = entityManager.find(TShopacc::class.java, dtl.shopaccno)
+ ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS,
+ "交易流水<${dtl.refno}>商户账户不存在")
+
+ 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)
+ .setParameter(3, shopacc.balance)
+ return query.executeUpdate()
+ }
+}
\ No newline at end of file
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 4359f7f..ebf7118 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
@@ -4,15 +4,26 @@
import com.supwisdom.dlpay.api.TransactionResult
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.TransactionProcessException
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.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import java.sql.SQLException
+import javax.transaction.Transactional
+
+
+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 {
@@ -39,6 +50,12 @@
@Autowired
lateinit var debitCreditDtlDao: DebitCreditDtlDao
+ @Autowired
+ lateinit var accountRepository: TAccountRepositoryImpl
+
+ @Autowired
+ lateinit var shopaccRepository: ShopaccRepositoryImpl
+
private fun builderRecords(builder: TransactionBuilder, status: String): TransactionResult {
// 记录三方的交易流水(个人,商户,科目)
try {
@@ -250,9 +267,6 @@
transactionMainDao.save(transaction)
}
- private fun decreseAccountBalance(account: TAccount, amount: Double) {
-
- }
override fun success(refno: String) {
val transaction = transactionMainDao.findByRefnoForUpdate(refno)
@@ -266,12 +280,16 @@
if (transaction.person) {
// update account balance
transaction.personDtl?.let {
- accoutDao.updateAccountBalance("", 0.0, transaction.personDtl.amount)
+ accountRepository.recalcAccountBalance(it, it.amount, false)
} ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
- "个人<${transaction.personDtl.userid}>不存在")
+ "个人流水<${transaction.refno}>不存在")
}
if (transaction.shop) {
// update shop balance
+ transaction.shopDtl?.let {
+ shopaccRepository.recalcShopBalance(it, it.amount, false)
+ } ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS,
+ "商户流水<${transaction.refno}>不存在")
}
if (transaction.subject) {
diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt b/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
index b4407c1..8872f33 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
@@ -2,6 +2,7 @@
import com.supwisdom.dlpay.api.TransactionBuilder
import com.supwisdom.dlpay.api.TransactionResult
+import com.supwisdom.dlpay.api.domain.TAccount
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
@@ -20,4 +21,8 @@
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
fun success(refno: String)
+}
+
+interface PersonAccountService {
+ fun recalcBalance(account: TAccount, amount: Double)
}
\ No newline at end of file