更新账户校验机制
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 0000000..f268646
--- /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 ccd2a06..378bf1b 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 @@
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 @@
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 791850d..27b15a0 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 c019cee..ccbb872 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 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 fe9c1d1..943b4e5 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 @@
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 0f06200..849d275 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 e54f063..1ab0d37 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.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 @@
@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 @@
}
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 44598d1..15869a6 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.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 @@
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 @@
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 @@
}
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 f10c1a3..443acd0 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 @@
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