转账分布式锁bug解锁

pull/520/head
dorion 2024-04-25 22:03:06 +08:00
parent f8e8cfe12a
commit 29a6c0f389
10 changed files with 137 additions and 37 deletions

View File

@ -147,7 +147,7 @@
</plugin> --> </plugin> -->
</plugins> </plugins>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
<resources> <!-- <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<excludes> <excludes>
@ -155,7 +155,7 @@
<exclude>*.xml</exclude> <exclude>*.xml</exclude>
</excludes> </excludes>
</resource> </resource>
</resources> </resources>-->
</build> </build>

View File

@ -106,15 +106,18 @@
}, },
{ {
field: 'fcu', field: 'fcu',
title: '创建用户' title: '创建用户',
visible: false
}, },
{ {
field: 'lcd', field: 'lcd',
title: '更新时间' title: '更新时间',
visible: false
}, },
{ {
field: 'lcu', field: 'lcu',
title: '更新用户' title: '更新用户',
visible: false
}, },
{ {

View File

@ -134,19 +134,23 @@
}, },
{ {
field: 'fcd', field: 'fcd',
title: '创建时间' title: '创建时间',
visible: false
}, },
{ {
field: 'fcu', field: 'fcu',
title: '创建用户' title: '创建用户',
visible: false
}, },
{ {
field: 'lcd', field: 'lcd',
title: '更新时间' title: '更新时间',
visible: false
}, },
{ {
field: 'lcu', field: 'lcu',
title: '更新用户' title: '更新用户',
visible: false
}, },
{ {

View File

@ -121,7 +121,8 @@
}, },
{ {
field: 'trxTxId', field: 'trxTxId',
title: 'TRX订单' title: 'TRX订单',
visible: false
}, },
{ {
field: 'tranferCount', field: 'tranferCount',
@ -147,7 +148,8 @@
}, },
{ {
field: 'delegateTxId', field: 'delegateTxId',
title: '能量交易订单' title: '能量交易订单',
visible: false
}, },
{ {
field: 'lockPeriod', field: 'lockPeriod',
@ -165,11 +167,13 @@
}, },
{ {
field: 'unDelegateTxId', field: 'unDelegateTxId',
title: '回收资源交易' title: '回收资源交易',
visible: false
}, },
{ {
field: 'fcd', field: 'fcd',
title: '创建时间' title: '创建时间',
visible: false
}, },
/* { /* {
field: 'fcu', field: 'fcu',
@ -177,7 +181,8 @@
},*/ },*/
{ {
field: 'lcd', field: 'lcd',
title: '更新时间' title: '更新时间',
visible: false
}, },
/*{ /*{
field: 'lcu', field: 'lcu',

View File

@ -112,19 +112,23 @@
}, },
{ {
field: 'fcd', field: 'fcd',
title: '创建时间' title: '创建时间',
visible: false
}, },
{ {
field: 'fcu', field: 'fcu',
title: '创建用户' title: '创建用户',
visible: false
}, },
{ {
field: 'lcd', field: 'lcd',
title: '更新时间' title: '更新时间',
visible: false
}, },
{ {
field: 'lcu', field: 'lcu',
title: '更新用户' title: '更新用户',
visible: false
}, },
{ {
title: '操作', title: '操作',

View File

@ -1,5 +1,8 @@
package com.ruoyi.system.api.impl; package com.ruoyi.system.api.impl;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.ruoyi.common.utils.http.RestTemplateUtils; import com.ruoyi.common.utils.http.RestTemplateUtils;
import com.ruoyi.system.api.ITronApi; import com.ruoyi.system.api.ITronApi;
@ -13,6 +16,8 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import java.util.Date;
@Component @Component
@Slf4j @Slf4j
public class TronApiImpl implements ITronApi { public class TronApiImpl implements ITronApi {
@ -29,10 +34,10 @@ public class TronApiImpl implements ITronApi {
// builder.queryParam("only_confirmed", true); // builder.queryParam("only_confirmed", true);
builder.queryParam("only_to", true); builder.queryParam("only_to", true);
builder.queryParam("limit", 200); builder.queryParam("limit", 200);
// String sysTransferBetween = configService.selectConfigByKey("sys.transfer.between"); String sysTransferBetween = configService.selectConfigByKey("sys.transfer.between");
// //
// DateTime min_timestamp = DateUtil.offset(new Date(), DateField.MINUTE, Integer.valueOf(sysTransferBetween)); DateTime min_timestamp = DateUtil.offset(new Date(), DateField.MINUTE, Integer.valueOf(sysTransferBetween));
// builder.queryParam("min_timestamp", min_timestamp.getTime()); builder.queryParam("min_timestamp", min_timestamp.getTime());
String uriString = builder.toUriString(); String uriString = builder.toUriString();
ResponseEntity responseEntity = RestTemplateUtils.get(uriString, headers, String.class); ResponseEntity responseEntity = RestTemplateUtils.get(uriString, headers, String.class);

View File

@ -1,5 +1,7 @@
package com.ruoyi.system.bot; package com.ruoyi.system.bot;
import com.ruoyi.system.bot.handleService.NewMemberIntoGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.Update;
@ -8,20 +10,37 @@ import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.Keyboard
import org.telegram.telegrambots.meta.bots.AbsSender; import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Component @Component
public class CustomBotFunction { public class CustomBotFunction {
@Autowired
private NewMemberIntoGroup newMemberIntoGroup;
/** /**
* *
*
* @param sender * @param sender
* @param update * @param update
*/ */
public void mainFunc(AbsSender sender, Update update) throws TelegramApiException { public void mainFunc(AbsSender sender, Update update) throws TelegramApiException, IOException, NoSuchAlgorithmException, InvalidKeyException {
if (update.getChatMember() != null && "left".equals(update.getChatMember().getOldChatMember().getStatus())
&& "member".equals(update.getChatMember().getNewChatMember().getStatus()) &&
(update.getChatMember().getChat().isGroupChat() || update.getChatMember().getChat().isSuperGroupChat())) {
newMemberIntoGroup.handleMessage(sender, update);
return;
}
if ("/start".equals(update.getMessage().getText())) { if ("/start".equals(update.getMessage().getText())) {
SendMessage message = new SendMessage(); SendMessage message = new SendMessage();

View File

@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
@ -57,10 +56,10 @@ public class TgLongPollingBot extends TelegramLongPollingBot {
@SneakyThrows @SneakyThrows
public void onUpdateReceived(Update update) { public void onUpdateReceived(Update update) {
// log.info("消息:{}",update.getMessage().getText()); // log.info("消息:{}",update.getMessage().getText());
SendMessage sendMessage = SendMessage.builder().chatId(update.getMessage().getChatId().toString()).text("收到消息:"+update.getMessage().getChatId().toString()).build(); // SendMessage sendMessage = SendMessage.builder().chatId(update.getMessage().getChatId().toString()).text("收到消息:"+update.getMessage().getChatId().toString()).build();
try { try {
customBotFunction.mainFunc(this,update); customBotFunction.mainFunc(this,update);
execute(sendMessage); // execute(sendMessage);
} catch (TelegramApiException e) { } catch (TelegramApiException e) {
log.error("ex:{}",e); log.error("ex:{}",e);

View File

@ -0,0 +1,67 @@
package com.ruoyi.system.bot.handleService;
import com.ruoyi.system.bot.utils.SendContent;
import com.ruoyi.system.handler.UsdtTransferHandler;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.methods.send.SendPhoto;
import org.telegram.telegrambots.meta.api.objects.InputFile;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
@Component
@Slf4j
public class NewMemberIntoGroup {
@Autowired
private SendContent sendContent;
@Autowired
private ISysConfigService configService;
@Autowired
private UsdtTransferHandler usdtTransferHandlerl;
public void handleMessage(AbsSender sender, Update update) throws TelegramApiException, IOException, NoSuchAlgorithmException, InvalidKeyException {
InputStream inputStream =
new ClassPathResource("pbottleRPA_1681804582722.png").getInputStream();
Long chatId = update.getChatMember().getChat().getId();
String sysUsdtGroupWelcomTopic = configService.selectConfigByKey("sys.usdt.group.welcom.topic");
String sysTgGroupChatId = configService.selectConfigByKey("sys.tg.group.chat.id");
if (StringUtils.isNotEmpty(sysUsdtGroupWelcomTopic) && StringUtils.isNotEmpty(sysTgGroupChatId)){
BigDecimal oneUsdtToTrx = usdtTransferHandlerl.getOneUsdtToTrx();
BigDecimal tenUsdtToTrx = oneUsdtToTrx.multiply(BigDecimal.TEN);
Map<String, Object> arguments = new HashMap<>();
arguments.put("tenUsdtToTrx", tenUsdtToTrx);
StrSubstitutor substitutor = new StrSubstitutor(arguments, "{", "}");
String message = substitutor.replace(sysUsdtGroupWelcomTopic);
SendPhoto sendPhoto = SendPhoto.builder()
.chatId(chatId.toString())
.photo(new InputFile(inputStream, "aaa.png"))
.caption(message).build();
sender.execute(sendPhoto);
}else {
log.info("sysUsdtGroupWelcomTopic or sysTgGroupChatId is empty");
}
}
}

View File

@ -110,6 +110,11 @@ public class UsdtTransferHandler {
String dataTo = data.getTo(); String dataTo = data.getTo();
String transactionId = data.getTransaction_id(); String transactionId = data.getTransaction_id();
Boolean hasKey = redisTemplate.hasKey("transfer_USDT_" + transactionId);
if (hasKey) {
return;
}
RLock lock = redissonClient.getLock("lock_" + transactionId); RLock lock = redissonClient.getLock("lock_" + transactionId);
try { try {
boolean res = lock.tryLock(3, 50, TimeUnit.SECONDS); boolean res = lock.tryLock(3, 50, TimeUnit.SECONDS);
@ -139,7 +144,7 @@ public class UsdtTransferHandler {
ApiWrapper apiWrapper = ApiWrapper.ofMainnet(decryptPrivateKey, apiKey); ApiWrapper apiWrapper = ApiWrapper.ofMainnet(decryptPrivateKey, apiKey);
//转账 //转账
Response.TransactionExtention transfer = apiWrapper.transfer(accountAddress, from, trxValue.movePointRight(6).longValue()); Response.TransactionExtention transfer = apiWrapper.transfer(accountAddress, from, trxValue.movePointRight(6).longValue());
//签名 //签名
Chain.Transaction transaction = apiWrapper.signTransaction(transfer); Chain.Transaction transaction = apiWrapper.signTransaction(transfer);
@ -283,16 +288,5 @@ public class UsdtTransferHandler {
} }
} }
/* public static void main(String[] args) {
String res ="{\"code\":\"0\",\"msg\":\"\",\"data\":[{\"instType\":\"SPOT\",\"instId\":\"TRX-USDT\",\"last\":\"0.11108\",\"lastSz\":\"534.839755\",\"askPx\":\"0.11108\",\"askSz\":\"12244.867483\",\"bidPx\":\"0.11107\",\"bidSz\":\"2776.220524\",\"open24h\":\"0.11093\",\"high24h\":\"0.11199\",\"low24h\":\"0.11018\",\"volCcy24h\":\"3721341.18131714737\",\"vol24h\":\"33527411.881202\",\"ts\":\"1713782792103\",\"sodUtc0\":\"0.11134\",\"sodUtc8\":\"0.11081\"}]}";
OkxResponse okxResponse = JSONUtil.toBean(res, OkxResponse.class);
List<com.ruoyi.system.api.entity.okx.Data> oksResponseDataList = okxResponse.getData();
String last = oksResponseDataList.get(0).getLast();
double v = 1 / new Double(last);
BigDecimal bigDecimal = BigDecimal.valueOf(v).setScale(6, BigDecimal.ROUND_HALF_DOWN);
System.out.println(bigDecimal);
}*/
} }