From 217eb2876711d1f3feed6210e722aebeee15b563 Mon Sep 17 00:00:00 2001 From: Tang Cheng Date: Wed, 10 Jul 2019 13:08:48 +0800 Subject: [PATCH] =?utf8?q?=E6=9B=B4=E6=96=B0=E8=B4=A6=E6=88=B7=E6=A0=A1?= =?utf8?q?=E9=AA=8C=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../supwisdom/dlpay/api/util/HMACUtil.java | 29 +++++++++++++++ .../dlpay/paysdk/ApiLoginHelper.java | 4 +-- .../supwisdom/dlpay/paysdk/utils/Utils.java | 24 ------------- .../supwisdom/dlpay/api/domain/TAccount.java | 22 +++++++----- .../dlpay/framework/domain/TShopacc.java | 25 +++++++++++++ .../dlpay/framework/util/Signature.java | 8 ++++- .../api/service/impl/pay_service_impl.kt | 35 ++++++++++++++----- .../service/impl/transaction_service_impl.kt | 21 +++-------- .../dlpay/api/service/pay_service.kt | 3 +- 9 files changed, 110 insertions(+), 61 deletions(-) create mode 100644 payapi-common/src/main/java/com/supwisdom/dlpay/api/util/HMACUtil.java diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/util/HMACUtil.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/util/HMACUtil.java new file mode 100644 index 00000000..f268646b --- /dev/null +++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/util/HMACUtil.java @@ -0,0 +1,29 @@ +package com.supwisdom.dlpay.api.util; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class HMACUtil { + public static String sha256HMAC(String message, String secret) { + String hash = ""; + try { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); + sha256_HMAC.init(secret_key); + byte[] bytes = sha256_HMAC.doFinal(message.getBytes()); + hash = byteArrayToHexString(bytes); + System.out.println(hash); + } catch (Exception e) { + System.out.println("Error HmacSHA256 ===========" + e.getMessage()); + } + return hash; + } + + private static String byteArrayToHexString(byte[] bytes) { + StringBuilder builder = new StringBuilder(); + for (byte b : bytes) { + builder.append(String.format("%02x", ((int) b) & 0xFF)); + } + return builder.toString(); + } +} diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/ApiLoginHelper.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/ApiLoginHelper.java index ccd2a062..378bf1ba 100644 --- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/ApiLoginHelper.java +++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/ApiLoginHelper.java @@ -2,9 +2,9 @@ package com.supwisdom.dlpay.paysdk; import com.supwisdom.dlpay.api.bean.ApiLoginInitResponse; import com.supwisdom.dlpay.api.bean.ApiLoginResponse; +import com.supwisdom.dlpay.api.util.HMACUtil; import com.supwisdom.dlpay.paysdk.proxy.ApiLoginProxy; import com.supwisdom.dlpay.paysdk.utils.JwtContext; -import com.supwisdom.dlpay.paysdk.utils.Utils; public class ApiLoginHelper { private ApiLoginProxy apiLoginProxy; @@ -27,7 +27,7 @@ public class ApiLoginHelper { if (loginInit.getRetcode() != 0) { throw new RuntimeException("登录初始化错误: " + loginInit.getRetcode() + ", " + loginInit.getException()); } - String token = Utils.sha256HMAC(loginInit.getToken(), secret); + String token = HMACUtil.sha256HMAC(loginInit.getToken(), secret); ApiLoginResponse login; if (clientId != null) { login = apiLoginProxy.loginWithClientId(appid, token, clientId); diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/utils/Utils.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/utils/Utils.java index 791850d8..27b15a05 100644 --- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/utils/Utils.java +++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/utils/Utils.java @@ -1,29 +1,5 @@ package com.supwisdom.dlpay.paysdk.utils; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - public class Utils { - public static String sha256HMAC(String message, String secret) { - String hash = ""; - try { - Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); - SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); - sha256_HMAC.init(secret_key); - byte[] bytes = sha256_HMAC.doFinal(message.getBytes()); - hash = byteArrayToHexString(bytes); - System.out.println(hash); - } catch (Exception e) { - System.out.println("Error HmacSHA256 ===========" + e.getMessage()); - } - return hash; - } - private static String byteArrayToHexString(byte[] bytes) { - StringBuilder builder = new StringBuilder(); - for (byte b : bytes) { - builder.append(String.format("%02x", ((int) b) & 0xFF)); - } - return builder.toString(); - } } diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TAccount.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TAccount.java index c019cee5..ccbb872d 100644 --- a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TAccount.java +++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TAccount.java @@ -1,7 +1,7 @@ package com.supwisdom.dlpay.api.domain; -import com.supwisdom.dlpay.framework.util.MD5; import com.supwisdom.dlpay.framework.util.MoneyUtil; +import com.supwisdom.dlpay.framework.util.Signature; import com.supwisdom.dlpay.framework.util.TradeDict; import org.hibernate.annotations.GenericGenerator; @@ -257,22 +257,28 @@ public class TAccount implements Serializable { } public String generateTac() { - String data = this.accno + MoneyUtil.YuanToFen(this.availbal) + MoneyUtil.YuanToFen(this.balance) + MoneyUtil.YuanToFen(this.frozebal); - return MD5.generatePassword(data, this.accno); + String data = this.accno + + this.opendate + + this.transStatus + + this.userid + + MoneyUtil.YuanToFen(this.availbal) + + MoneyUtil.YuanToFen(this.balance) + + MoneyUtil.YuanToFen(this.frozebal); + return Signature.generateTac(this.accno, data); } public boolean tacCheck() { String tac_c = generateTac(); - if (tac_c.equalsIgnoreCase(this.tac) || this.tac == null) { + if (tac_c.equalsIgnoreCase(this.tac) || Signature.SPY_TAC.equals(this.tac)) { return true; } return false; } - public void addAmount(double amount) { - this.balance = this.balance + amount; - this.availbal = this.availbal + amount; - this.tac = this.generateTac(); + @PrePersist + @PreUpdate + public void updateTac() { + this.tac = generateTac(); } public boolean checkOverflow() { diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java index fe9c1d10..943b4e5a 100644 --- a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java +++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TShopacc.java @@ -1,5 +1,9 @@ package com.supwisdom.dlpay.framework.domain; +import com.supwisdom.dlpay.framework.util.MoneyUtil; +import com.supwisdom.dlpay.framework.util.Sign; +import com.supwisdom.dlpay.framework.util.Signature; + import javax.persistence.*; import javax.validation.constraints.NotNull; import java.sql.Timestamp; @@ -124,6 +128,27 @@ public class TShopacc { this.lastUpdate = new Timestamp(System.currentTimeMillis()); } + public String genMAC() { + String data = this.shopaccno + this.status + + this.shopid + + this.opendate + MoneyUtil.YuanToFen(this.balance); + return Signature.generateTac(this.shopaccno, data); + } + + public boolean checkMAC() { + String mac = genMAC(); + if (mac.equalsIgnoreCase(this.mac) || Signature.SPY_TAC.equals(this.mac)) { + return true; + } + return false; + } + + @PrePersist + @PreUpdate + public void updateMAC() { + this.mac = genMAC(); + } + public Timestamp getLastUpdate() { return lastUpdate; } diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Signature.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Signature.java index 0f06200d..849d2759 100644 --- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Signature.java +++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/Signature.java @@ -1,15 +1,21 @@ package com.supwisdom.dlpay.framework.util; +import com.supwisdom.dlpay.api.util.HMACUtil; import com.supwisdom.dlpay.framework.tenant.TenantContext; public class Signature { + public static final String SPY_TAC = "DLzJi044R7QHhJCDhpjZId8d"; private static final String ROOT_STATIC_KEY = "WfFTw42/2JnHP1Qjs4hnMstgANbhRvbXL84rNg=="; + private static String deliveryKey(String tenantId, String factor) { + return HMACUtil.sha256HMAC(tenantId + factor, ROOT_STATIC_KEY); + } + public static String generateTac(String factor, String data) { String tenant = TenantContext.getTenantSchema(); if (tenant == null) { throw new IllegalArgumentException("TenantID 未定义"); } - return ""; + return HMACUtil.sha256HMAC(deliveryKey(tenant, factor), data).substring(0, 24); } } diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/pay_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/pay_service_impl.kt index e54f063f..1ab0d377 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/pay_service_impl.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/pay_service_impl.kt @@ -9,6 +9,7 @@ import com.supwisdom.dlpay.framework.dao.FeetypeConfigDao import com.supwisdom.dlpay.framework.dao.ShopaccDao import com.supwisdom.dlpay.framework.dao.SubjectDao import com.supwisdom.dlpay.framework.domain.TFeetypeConfig +import com.supwisdom.dlpay.framework.domain.TShop import com.supwisdom.dlpay.framework.domain.TShopacc import com.supwisdom.dlpay.framework.domain.TSubject import com.supwisdom.dlpay.framework.util.TradeErrorCode @@ -33,10 +34,18 @@ class AccountUtilServcieImpl : AccountUtilServcie { @Autowired lateinit var feetypeConfigDao: FeetypeConfigDao + private fun accountCheck(account: TAccount) { + if (!account.tacCheck()) { + throw TransactionProcessException(TradeErrorCode.ACCOUNT_TAC_ERROR, + "个人账户<${account.userid}>验证错误") + } + } + override fun readAccountForUpdateNowait(userid: String): TAccount { return try { - accountDao.getByUseridForUpdateNowait(userid) - ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "账户<$userid>不存在") + accountDao.getByUseridForUpdateNowait(userid)?.also { + accountCheck(it) + } ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "账户<$userid>不存在") } catch (ex: Exception) { when (ex) { is CannotAcquireLockException, is LockTimeoutException -> throw TransactionException(TradeErrorCode.ACCOUNT_TRADE_BUSY, "账户<$userid>交易繁忙,请稍后再试") @@ -46,18 +55,28 @@ class AccountUtilServcieImpl : AccountUtilServcie { } override fun readAccount(userid: String): TAccount { - return accountDao.findByUserid(userid) - ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "账户<$userid>不存在") + return accountDao.findByUserid(userid)?.also { + accountCheck(it) + } ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, "账户<$userid>不存在") + } + + private fun shopAccCheck(shopacc: TShopacc) { + if (!shopacc.checkMAC()) { + throw TransactionProcessException(TradeErrorCode.ACCOUNT_TAC_ERROR, + "商户账户<${shopacc.shopid}>验证错误") + } } override fun readShopAcc(shopId: Int): TShopacc { - return shopaccDao.findByShopid(shopId) - ?: throw TransactionProcessException(TradeErrorCode.SHOP_NOT_EXISTS, "商户<$shopId>不存在") + return shopaccDao.findByShopid(shopId)?.also { + shopAccCheck(it) + } ?: throw TransactionProcessException(TradeErrorCode.SHOP_NOT_EXISTS, "商户<$shopId>不存在") } override fun readShopbyShopaccno(shopaccno: String): TShopacc { - return shopaccDao.findByShopaccno(shopaccno) - ?: throw TransactionProcessException(TradeErrorCode.SHOP_NOT_EXISTS, "商户<$shopaccno>不存在") + return shopaccDao.findByShopaccno(shopaccno)?.also { + shopAccCheck(it) + } ?: throw TransactionProcessException(TradeErrorCode.SHOP_NOT_EXISTS, "商户<$shopaccno>不存在") } override fun readSubject(subjno: String): TSubject { diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt index 44598d14..15869a6c 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt @@ -5,6 +5,7 @@ import com.supwisdom.dlpay.api.dao.AccountDao import com.supwisdom.dlpay.api.dao.TransactionMainDao import com.supwisdom.dlpay.api.domain.* import com.supwisdom.dlpay.api.repositories.AccountService +import com.supwisdom.dlpay.api.service.AccountUtilServcie import com.supwisdom.dlpay.api.service.SourceTypeService import com.supwisdom.dlpay.api.service.TransactionService import com.supwisdom.dlpay.exception.TransactionCheckException @@ -31,13 +32,7 @@ class TransactionServiceImpl : TransactionService { private lateinit var accountService: AccountService @Autowired - private lateinit var accountDao: AccountDao - - @Autowired - private lateinit var shopaccDao: ShopaccDao - - @Autowired - private lateinit var subjectDao: SubjectDao + private lateinit var accountUtilService: AccountUtilServcie @Autowired private lateinit var systemUtilService: SystemUtilService @@ -458,18 +453,14 @@ class TransactionServiceImpl : TransactionService { private fun doReversePrepareAndCheck(originTrans: TTransactionMain, builder: TransactionBuilder) { if (originTrans.person) { - val account = accountDao.findByUserid(originTrans.personDtl.userid) - ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, - "账户不存在") + val account = accountUtilService.readAccount(originTrans.personDtl.userid) builder.person(account).apply { setAmount(-originTrans.personDtl.amount, getOppositeTradeFlag(originTrans.personDtl.tradeflag)) } } if (originTrans.shop) { - val shopacc = shopaccDao.findByShopaccno(originTrans.shopDtl.shopaccno) - ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, - "商户不存在") + val shopacc = accountUtilService.readShopbyShopaccno(originTrans.shopDtl.shopaccno) builder.shop(shopacc).apply { setAmount(-originTrans.shopDtl.amount, getOppositeTradeFlag(originTrans.shopDtl.tradeflag)) @@ -477,9 +468,7 @@ class TransactionServiceImpl : TransactionService { } if (originTrans.subject) { - val subject = subjectDao.findBySubjno(originTrans.subjectDtl.subjectno) - ?: throw TransactionProcessException(TradeErrorCode.ACCOUNT_NOT_EXISTS, - "科目不存在") + val subject = accountUtilService.readSubject(originTrans.subjectDtl.subjectno) builder.subject(subject) } } diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/pay_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/pay_service.kt index f10c1a34..443acd0e 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/pay_service.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/pay_service.kt @@ -9,10 +9,9 @@ import org.springframework.transaction.annotation.Transactional interface AccountUtilServcie { - @Transactional(propagation = Propagation.REQUIRED, rollbackFor = arrayOf(Exception::class)) + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class]) fun readAccountForUpdateNowait(userid: String): TAccount - fun readAccount(userid: String): TAccount fun readShopAcc(shopId: Int): TShopacc -- 2.17.1