VaultodyServiceImpl.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. package com.crm.manager.service.impl;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.crm.manager.dao.mapper.TransactionItemMapper;
  4. import com.crm.manager.repository.TransactionItemRepository;
  5. import com.crm.manager.service.SysConfigService;
  6. import com.crm.manager.service.SysVaultodyConfigService;
  7. import com.crm.manager.service.VaultodyService;
  8. import com.crm.rely.backend.core.constant.Constants;
  9. import com.crm.rely.backend.core.dto.base.BaseResultDto;
  10. import com.crm.rely.backend.core.dto.base.PageDto;
  11. import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
  12. import com.crm.rely.backend.core.exception.ServiceException;
  13. import com.crm.rely.backend.core.pojo.table.SysConfigTable;
  14. import com.crm.rely.backend.model.config.VaultodyConfig;
  15. import com.crm.rely.backend.model.constant.ConfigConstants;
  16. import com.crm.rely.backend.model.constant.ManagerConstants;
  17. import com.crm.rely.backend.model.dto.vaultody.vaults.TransactionItemDto;
  18. import com.crm.rely.backend.model.dto.vaultody.vaults.VaultTransaction;
  19. import com.crm.rely.backend.model.dto.vaultody.vaults.VaultodyVaultsListDto;
  20. import com.crm.rely.backend.model.dto.vaultody.vaults.response.*;
  21. import com.crm.rely.backend.model.entity.vaultody.vaults.VaultTransactionsEntity;
  22. import com.crm.rely.backend.model.entity.vaultody.vaults.VaultTransactionsSearchEntity;
  23. import com.crm.rely.backend.model.pojo.table.SysVaultodyConfigTable;
  24. import com.crm.rely.backend.model.pojo.table.TransactionItemTable;
  25. import com.crm.rely.backend.util.AESUtil;
  26. import com.crm.rely.backend.util.HttpUtil;
  27. import com.crm.rely.backend.util.UUIDUtil;
  28. import com.google.common.collect.Lists;
  29. import lombok.extern.slf4j.Slf4j;
  30. import org.apache.commons.lang3.StringUtils;
  31. import org.jsoup.Connection;
  32. import org.springframework.beans.BeanUtils;
  33. import org.springframework.beans.factory.annotation.Autowired;
  34. import org.springframework.stereotype.Service;
  35. import org.springframework.util.CollectionUtils;
  36. import org.springframework.util.ObjectUtils;
  37. import javax.crypto.Mac;
  38. import javax.crypto.spec.SecretKeySpec;
  39. import java.io.IOException;
  40. import java.nio.charset.StandardCharsets;
  41. import java.util.*;
  42. import java.util.stream.Collectors;
  43. @Slf4j
  44. @Service
  45. public class VaultodyServiceImpl implements VaultodyService {
  46. @Autowired
  47. private SysVaultodyConfigService vaultodyConfigService;
  48. @Autowired
  49. private SysConfigService sysConfigService;
  50. @Autowired
  51. private TransactionItemRepository transactionItemRepository;
  52. @Autowired
  53. private TransactionItemMapper transactionItemMapper;
  54. public static String getSignature(String message, String apiSecret) {
  55. try {
  56. byte[] decodedSecret = Base64.getDecoder().decode(apiSecret);
  57. Mac mac = Mac.getInstance("HmacSHA256");
  58. SecretKeySpec secretKeySpec = new SecretKeySpec(decodedSecret, "HmacSHA256");
  59. mac.init(secretKeySpec);
  60. byte[] hash = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
  61. return Base64.getEncoder().encodeToString(hash);
  62. } catch (Exception e) {
  63. e.printStackTrace();
  64. }
  65. return null;
  66. }
  67. public static void main2(String[] args) {
  68. String s = "{\n" +
  69. " \"apiKey\": \"6f3cc6caf513a5cde2df5d3ed805e3703d4d43b2\",\n" +
  70. " \"apiSecret\": \"MLjTUAYgxSM2dg==\",\n" +
  71. " \"passphrase\": \"7UGMi2*t0h\",\n" +
  72. " \"vaultId\": \"\",\n" +
  73. " \"baseUrl\": \"https://rest.vaultody.com\",\n" +
  74. " \"vaultsListUrl\": \"/vaults/test\",\n" +
  75. " \"network\": \"\",\n" +
  76. " \"vaultsTransactionsPathTemplate\": \"/vaults/%s/transactions\",\n" +
  77. " \"webhooksPassphrase\": \"\"\n" +
  78. "}";
  79. System.out.println(AESUtil.encrypt(s, "bfa5559109f94c78af615bcf00d52060"));
  80. System.out.println(AESUtil.decrypt(AESUtil.encrypt(s, "bfa5559109f94c78af615bcf00d52060"), "bfa5559109f94c78af615bcf00d52060"));
  81. }
  82. public static void main(String[] args) {
  83. String s = "{\n" +
  84. " \"apiKey\": \"6f3cc6caf513a5cde2df5d3ed805e3703d4d43b2\",\n" +
  85. " \"apiSecret\": \"MLjTUAYgxSM2dg==\",\n" +
  86. " \"passphrase\": \"7UGMi2*t0h\",\n" +
  87. " \"vaultId\": \"\",\n" +
  88. " \"baseUrl\": \"https://rest.vaultody.com\",\n" +
  89. " \"vaultsListUrl\": \"/vaults/test\",\n" +
  90. " \"network\": \"\",\n" +
  91. " \"vaultsTransactionsPathTemplate\": \"/vaults/%s/transactions\",\n" +
  92. " \"webhooksPassphrase\": \"\",\n" +
  93. " \"vaultodyList\": [\n" +
  94. " {\n" +
  95. " \"apiKey\": \"6f3cc6caf513a5cde2df5d3ed805e3703d4d43b2\",\n" +
  96. " \"apiSecret\": \"MLjTUAYgxSM2dg==\",\n" +
  97. " \"passphrase\": \"7UGMi2*t0h\",\n" +
  98. " \"vaultId\": \"69cb34038d64830006453c0c\",\n" +
  99. " \"baseUrl\": \"https://rest.vaultody.com\",\n" +
  100. " \"vaultsListUrl\": \"/vaults/test\",\n" +
  101. " \"network\": \"\",\n" +
  102. " \"vaultsTransactionsPathTemplate\": \"/vaults/%s/transactions\",\n" +
  103. " \"webhooksPassphrase\": \"\"\n" +
  104. " },\n" +
  105. " {\n" +
  106. " \"apiKey\": \"002key\",\n" +
  107. " \"apiSecret\": \"002pwd\",\n" +
  108. " \"passphrase\": \"7UGMi2*t0h\",\n" +
  109. " \"vaultId\": \"002\",\n" +
  110. " \"baseUrl\": \"https://rest.vaultody.com\",\n" +
  111. " \"vaultsListUrl\": \"/vaults/test\",\n" +
  112. " \"network\": \"\",\n" +
  113. " \"vaultsTransactionsPathTemplate\": \"/vaults/%s/transactions\",\n" +
  114. " \"webhooksPassphrase\": \"\"\n" +
  115. " }\n" +
  116. " ]\n" +
  117. "}";
  118. System.out.println(AESUtil.encrypt(s, "bfa5559109f94c78af615bcf00d52060"));
  119. System.out.println(AESUtil.decrypt(AESUtil.encrypt(s, "bfa5559109f94c78af615bcf00d52060"), "bfa5559109f94c78af615bcf00d52060"));
  120. }
  121. /**
  122. * Coin
  123. */
  124. public static void main1(String[] args) {
  125. try {
  126. List<VaultodyVaultsListDto> dtos = new ArrayList<>();
  127. // ------------------ 配置 ------------------
  128. String apiKey = "6f3cc6caf513a5cde2df5d3ed805e3703d4d43b2";
  129. String apiSecret = "MLjTUAYgxSM2dg=="; // Base64编码的secret
  130. String passphrase = "7UGMi2*t0h";
  131. String method = "GET";
  132. String requestPath = "/vaults/test";
  133. String baseUrl = "https://rest.vaultody.com";
  134. String query = "{}"; // POST 时 query 通常为空,否则按接口要求填写
  135. String body = "{}"; // POST 时 query 通常为空,否则按接口要求填写
  136. // ------------------ 时间戳(秒) ------------------
  137. String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
  138. // ------------------ 构建消息用于签名 ------------------
  139. String message = timestamp + method + requestPath + body + query;
  140. System.out.println("Message: " + message);
  141. String signature = getSignature(message, apiSecret);
  142. System.out.println("Signature: " + signature);
  143. Map<String, String> headers = new HashMap<>();
  144. headers.put("x-api-key", apiKey);
  145. headers.put("x-api-sign", signature);
  146. headers.put("x-api-timestamp", timestamp);
  147. headers.put("x-api-passphrase", passphrase);
  148. headers.put("Content-Type", "application/json");
  149. try {
  150. Connection.Response response = HttpUtil.get(baseUrl + requestPath, headers);
  151. if (response.statusCode() != 200){
  152. System.out.println("Error: " + response.statusMessage());
  153. }
  154. VaultsListResponseDto responseDto = JSON.parseObject(response.body(), VaultsListResponseDto.class);
  155. List<VaultsListResponseDto.Item> items = responseDto.getData().getItems();
  156. for (VaultsListResponseDto.Item item : items){
  157. VaultodyVaultsListDto dto = new VaultodyVaultsListDto();
  158. BeanUtils.copyProperties(item, dto);
  159. dtos.add(dto);
  160. }
  161. System.out.println(JSON.toJSONString(dtos));
  162. } catch (IOException e) {
  163. throw new RuntimeException(e);
  164. }
  165. } catch (Exception e) {
  166. e.printStackTrace();
  167. }
  168. }
  169. /**
  170. * 交易记录接口拼接url
  171. */
  172. public String getPath(String pathTemplate, String vaultId) {
  173. // String pathTemplate = "/vaults/%s/transactions";
  174. String actualPath = String.format(pathTemplate, vaultId);
  175. return actualPath;
  176. }
  177. public VaultodyConfig getVaultodyConfig() {
  178. SysVaultodyConfigTable configTable = vaultodyConfigService.getByCode(ConfigConstants.VAULTODY_MANAGER_CONFIG);
  179. if (configTable == null) {
  180. throw ServiceException.exception(Constants.SYSTEM_ERROR);
  181. }
  182. String aesKey = getPropertyKey();
  183. String property = AESUtil.decrypt(configTable.getValue(), aesKey);
  184. VaultodyConfig vaultodyConfig = JSON.parseObject(property, VaultodyConfig.class);
  185. return vaultodyConfig;
  186. }
  187. public VaultodyConfig getVaultodyConfig(String vaultId) {
  188. SysVaultodyConfigTable configTable = vaultodyConfigService.getByCode(ConfigConstants.VAULTODY_MANAGER_CONFIG);
  189. if (configTable == null) {
  190. throw ServiceException.exception(Constants.SYSTEM_ERROR);
  191. }
  192. String aesKey = getPropertyKey();
  193. String property = AESUtil.decrypt(configTable.getValue(), aesKey);
  194. VaultodyConfig vaultodyConfig = JSON.parseObject(property, VaultodyConfig.class);
  195. List<VaultodyConfig> vaultodyList = vaultodyConfig.getVaultodyList();
  196. if(CollectionUtils.isEmpty(vaultodyList)){
  197. throw ServiceException.exception(ManagerConstants.NOT_PERMIT);
  198. }
  199. Map<String, VaultodyConfig> list = vaultodyList.stream().collect(Collectors.toMap(VaultodyConfig::getVaultId, v -> v));
  200. VaultodyConfig config = new VaultodyConfig();
  201. if(!list.containsKey(vaultId)){
  202. throw ServiceException.exception(ManagerConstants.NOT_PERMIT);
  203. }
  204. config = list.get(vaultId);
  205. return config;
  206. }
  207. private String getPropertyKey() throws ServiceException {
  208. SysConfigTable table = sysConfigService.getByCode(ConfigConstants.VAULTODY_FINANCE_PROPERTY_KEY);
  209. if (table == null) {
  210. throw ServiceException.exception(Constants.SYSTEM_ERROR);
  211. }
  212. return table.getValue();
  213. }
  214. @Override
  215. public BaseResultDto vaultsList() throws Exception {
  216. List<VaultodyVaultsListDto> dtos = new ArrayList<>();
  217. VaultodyConfig config = getVaultodyConfig();
  218. String apiKey = config.getApiKey();
  219. String apiSecret = config.getApiSecret();
  220. String passphrase = config.getPassphrase();
  221. String method = "GET";
  222. String requestPath = config.getVaultsListUrl();
  223. String baseUrl = config.getBaseUrl();
  224. String query = "{}"; // POST 时 query 通常为空,否则按接口要求填写
  225. String body = "{}";
  226. // ------------------ 时间戳(秒) ------------------
  227. String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
  228. // ------------------ 构建消息用于签名 ------------------
  229. String message = timestamp + method + requestPath + body + query;
  230. String signature = getSignature(message, apiSecret);
  231. System.out.println("Signature: " + signature);
  232. Map<String, String> headers = new HashMap<>();
  233. headers.put("x-api-key", apiKey);
  234. headers.put("x-api-sign", signature);
  235. headers.put("x-api-timestamp", timestamp);
  236. headers.put("x-api-passphrase", passphrase);
  237. headers.put("Content-Type", "application/json");
  238. Connection.Response response = HttpUtil.get(baseUrl + requestPath, headers);
  239. if (response.statusCode() != 200){
  240. return BaseResultDto.error(response.statusMessage());
  241. }
  242. VaultsListResponseDto responseDto = JSON.parseObject(response.body(), VaultsListResponseDto.class);
  243. List<VaultsListResponseDto.Item> items = responseDto.getData().getItems();
  244. for (VaultsListResponseDto.Item item : items){
  245. VaultodyVaultsListDto dto = new VaultodyVaultsListDto();
  246. BeanUtils.copyProperties(item, dto);
  247. dtos.add(dto);
  248. }
  249. return BaseResultDto.success(dtos);
  250. }
  251. public VaultTransaction query3Items(VaultTransactionsEntity entity) throws Exception{
  252. VaultodyConfig config = getVaultodyConfig(entity.getVaultId());
  253. String apiKey = config.getApiKey();
  254. String apiSecret = config.getApiSecret(); // Base64编码的secret
  255. String passphrase = config.getPassphrase();
  256. String method = "GET";
  257. // String requestPath = "/vaults/"+entity.getVaultId()+"/transactions";
  258. String requestPath = getPath(config.getVaultsTransactionsPathTemplate(), entity.getVaultId());
  259. String baseUrl = config.getBaseUrl();
  260. String query = "{}";
  261. Map<String, String> params = new HashMap();
  262. if(!ObjectUtils.isEmpty(entity.getLimit())){
  263. params.put("limit", String.valueOf(entity.getLimit()));
  264. }
  265. if(StringUtils.isNotBlank(entity.getStartingAfter())){
  266. params.put("startingAfter", entity.getStartingAfter());
  267. }
  268. if (StringUtils.isNotBlank(entity.getContext())){
  269. params.put("context", entity.getContext());
  270. }
  271. // ------------------ 时间戳(秒) ------------------
  272. String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
  273. // ------------------ 构建消息用于签名 ------------------
  274. String message = timestamp + method + requestPath + query + JSON.toJSONString(params);
  275. String signature = getSignature(message, apiSecret);
  276. log.info("Signature: {}",signature);
  277. Map<String, String> headers = new HashMap<>();
  278. headers.put("x-api-key", apiKey);
  279. headers.put("x-api-sign", signature);
  280. headers.put("x-api-timestamp", timestamp);
  281. headers.put("x-api-passphrase", passphrase);
  282. headers.put("Content-Type", "application/json");
  283. Connection.Response response = HttpUtil.get(baseUrl + requestPath, headers, params);
  284. log.info("response.statusCode: {} , response.body: {}",response.statusCode() , response.body());
  285. if (response.statusCode() != 200) {
  286. log.error("response.statusCode() != 200,{}","3Item Error!");
  287. throw ServiceException.exception(Constants.SYSTEM_ERROR);
  288. }
  289. TransactionResponse responseDto = JSON.parseObject(response.body(), TransactionResponse.class);
  290. ResponseData data = responseDto.getData();
  291. List<TransactionItem> items;
  292. if(CollectionUtils.isEmpty(data.getItems())){
  293. items = new ArrayList<>();
  294. TransactionItem item = new TransactionItem();
  295. item.setBlockchain("ethereum");
  296. item.setCreatedTimestamp(System.currentTimeMillis() / 1000);
  297. item.setDirection("direction");
  298. item.setHasTokenTransfer("false");
  299. item.setId("654ba3af9e8dd80901f17347");
  300. item.setIsInternal("false");
  301. item.setMinedInBlockHeight("1234324");
  302. item.setNetwork("mainnet");
  303. List<TransactionParticipant> recipients = new LinkedList<>();
  304. TransactionParticipant recipient = new TransactionParticipant();
  305. recipient.setAddress("0xd2070342a1a5ce24930ec6582b3db846458525a0");
  306. recipient.setAddressType("deposit");
  307. recipient.setAmount("0.0003");
  308. recipient.setAmountUnit("ETH");
  309. recipient.setIsVaultAddress("false");
  310. recipient.setLabel("收款钱包名称");
  311. recipients.add(recipient);
  312. List<TransactionParticipant> senders = new LinkedList<>();
  313. TransactionParticipant sender = new TransactionParticipant();
  314. sender.setAddress("0xa94b8eca8703ad2804cb204976ac023b612c407e");
  315. sender.setAddressType("deposit");
  316. sender.setAmount("0.0003");
  317. sender.setAmountUnit("ETH");
  318. sender.setIsVaultAddress("true");
  319. sender.setLabel("付款钱包名称");
  320. senders.add(sender);
  321. item.setRecipients(recipients);
  322. item.setSenders(senders);
  323. item.setStatus("completed");
  324. TransactionFee transactionFee = new TransactionFee();
  325. transactionFee.setAmount("0.0024");
  326. transactionFee.setAmountUnit("ETH");
  327. item.setTransactionFee(transactionFee);
  328. item.setTransactionId("281a63d28ddf6d0d5d78090b7cdf3a8c0be95bbb296544943ef45d9dec44405d");
  329. items.add(item);
  330. data.setItems(items);
  331. }
  332. VaultTransaction vaultTransaction = getVaultTransaction(data);
  333. return vaultTransaction;
  334. }
  335. private VaultTransaction getVaultTransaction(ResponseData data) {
  336. VaultTransaction vaultTransaction = new VaultTransaction();
  337. vaultTransaction.setHasMore(data.getHasMore());
  338. vaultTransaction.setLimit(data.getLimit());
  339. vaultTransaction.setStartingAfter(data.getStartingAfter());
  340. List<TransactionItemDto> list = Lists.newArrayList();
  341. for (TransactionItem item : data.getItems()) {
  342. TransactionItemDto dto = new TransactionItemDto();
  343. dto.setRequestId(UUIDUtil.getUUID());
  344. dto.setId(item.getId());
  345. dto.setTransactionId(item.getTransactionId());
  346. dto.setStatus(item.getStatus());
  347. dto.setCreatedTimestamp(item.getCreatedTimestamp());
  348. dto.setSenderAddress(item.getSenders().get(0).getAddress());
  349. dto.setSenderIsVaultAddress(item.getSenders().get(0).getIsVaultAddress());
  350. dto.setSenderAmountUnit(item.getSenders().get(0).getAmountUnit());
  351. dto.setSenderAmount(item.getSenders().get(0).getAmount());
  352. dto.setRecipientAddress(item.getRecipients().get(0).getAddress());
  353. dto.setRecipientIsVaultAddress(item.getRecipients().get(0).getIsVaultAddress());
  354. dto.setRecipientAmountUnit(item.getRecipients().get(0).getAmountUnit());
  355. dto.setRecipientAmount(item.getRecipients().get(0).getAmount());
  356. dto.setBlockchain(item.getBlockchain());
  357. dto.setMinedInBlockHeight(item.getMinedInBlockHeight());
  358. dto.setFeeAmount(item.getTransactionFee().getAmount());
  359. dto.setFeeAmountUnit(item.getTransactionFee().getAmountUnit());
  360. dto.setSenderLabel(item.getSenders().get(0).getLabel());
  361. dto.setRecipientLabel(item.getRecipients().get(0).getLabel());
  362. list.add(dto);
  363. }
  364. vaultTransaction.setList(list);
  365. return vaultTransaction;
  366. }
  367. @Override
  368. public List<TransactionItemTable> queryExportItems (VaultTransactionsEntity entity) throws Exception{
  369. return finAllByVaultId(entity.getVaultId());
  370. }
  371. @Override
  372. public void batchSave(List<TransactionItemTable> tables) {
  373. transactionItemRepository.saveAll(tables);
  374. }
  375. @Override
  376. public List<TransactionItemTable> finAllByVaultId(String vaultId) {
  377. return transactionItemRepository.findAllByVaultId(vaultId);
  378. }
  379. @Override
  380. public BaseResultDto searchList(VaultTransactionsSearchEntity entity) throws Exception {
  381. List<TransactionItemTable> tables = new LinkedList<>();
  382. List<TransactionItemDto> list = queryWithFilter(entity.getVaultId());
  383. if(!CollectionUtils.isEmpty(list)){
  384. for (TransactionItemDto transactionItemDto : list) {
  385. TransactionItemTable table = new TransactionItemTable() ;
  386. BeanUtils.copyProperties(transactionItemDto, table);
  387. table.setVaultId(entity.getVaultId());
  388. table.setItemId(transactionItemDto.getId());
  389. tables.add(table);
  390. }
  391. batchSave(tables);
  392. }
  393. Integer count = transactionItemMapper.countList(entity);
  394. if (count == null || count <= 0) {
  395. return ResultWithPagerDto.success(new PageDto(), new ArrayList<>());
  396. }
  397. PageDto pageDto = PageDto.format(entity, count);
  398. List<TransactionItemTable> dtos = transactionItemMapper.pageList(entity);
  399. if (dtos == null || dtos.size() <= 0) {
  400. throw new ServiceException(Constants.SYSTEM_ERROR);
  401. }
  402. return ResultWithPagerDto.success(pageDto, dtos);
  403. }
  404. public List<TransactionItemDto> queryWithFilter(String vaultId) throws Exception {
  405. VaultTransactionsEntity entity = new VaultTransactionsEntity();
  406. entity.setVaultId(vaultId);
  407. List<TransactionItemDto> result = new ArrayList<>();
  408. // 先获取数据库中已存在的item ID列表
  409. List<String> existingItemIds = recordByVaultId(vaultId);
  410. Set<String> existingIdSet = new HashSet<>(existingItemIds);
  411. VaultTransaction vaultTransaction = query3Items(entity);
  412. // 处理第一页数据
  413. if (vaultTransaction.getList() != null && !vaultTransaction.getList().isEmpty()) {
  414. List<TransactionItemDto> filteredList = filterExistingItems(vaultTransaction.getList(), existingIdSet);
  415. result.addAll(filteredList);
  416. }
  417. // 分页查询剩余数据
  418. while (Boolean.TRUE.equals(vaultTransaction.getHasMore())
  419. && vaultTransaction.getList() != null
  420. && !vaultTransaction.getList().isEmpty()) {
  421. String lastId = vaultTransaction.getList().get(vaultTransaction.getList().size() - 1).getId();
  422. entity.setStartingAfter(lastId);
  423. vaultTransaction = query3Items(entity);
  424. if (vaultTransaction.getList() != null && !vaultTransaction.getList().isEmpty()) {
  425. List<TransactionItemDto> filteredList = filterExistingItems(vaultTransaction.getList(), existingIdSet);
  426. result.addAll(filteredList);
  427. } else {
  428. break;
  429. }
  430. }
  431. return result;
  432. }
  433. private List<TransactionItemDto> filterExistingItems(List<TransactionItemDto> items, Set<String> existingIdSet) {
  434. if (items == null || items.isEmpty()) {
  435. return Collections.emptyList();
  436. }
  437. return items.stream()
  438. .filter(item -> item != null && item.getId() != null)
  439. .filter(item -> !existingIdSet.contains(item.getId()))
  440. .collect(Collectors.toList());
  441. }
  442. private List<String> recordByVaultId(String vaultId){
  443. List<TransactionItemTable> list = finAllByVaultId(vaultId);
  444. if(CollectionUtils.isEmpty(list)){
  445. return new ArrayList<>();
  446. }
  447. return list.stream().map(TransactionItemTable::getItemId).toList();
  448. }
  449. }