更新账户校验机制
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