package cc.mrbird.febs.mall.quartz; import cc.mrbird.febs.common.enumerates.OrderStatusEnum; import cc.mrbird.febs.common.utils.RedisUtils; import cc.mrbird.febs.mall.controller.dependentStation.constant.OrderConstants; import cc.mrbird.febs.mall.controller.dependentStation.enums.SalesServiceEnums; import cc.mrbird.febs.mall.controller.dependentStation.utils.OkHttpUtil2; import cc.mrbird.febs.mall.controller.dependentStation.utils.Trc20TokenviewContentModel; import cc.mrbird.febs.mall.controller.dependentStation.utils.Trc20TokenviewModel; import cc.mrbird.febs.mall.entity.DataDictionaryCustom; import cc.mrbird.febs.mall.entity.MallOrderInfo; import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper; import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j @Component @ConditionalOnProperty(prefix = "system", name = "job", havingValue = "true") public class ChatTrc20ChargeOkLinkTask { @Resource private RedisUtils redisUtils; @Resource private MallOrderInfoMapper mallOrderInfoMapper; @Resource private DataDictionaryCustomMapper dataDictionaryCustomMapper; /** * 五分钟 毫秒 */ private final static long TIME_INTERVAL = 300000*6; private final static String TRON_API_KEY = "fq6S2XK5zfNccu6QfGCi"; private static Map REQUEST_HEADER = new HashMap<>(); static { REQUEST_HEADER.put("TRON-PRO-API-KEY", TRON_API_KEY); } @Scheduled(cron = "0 0/1 * * * ? ") public void recharge() { // 查询过去5分钟的记录 DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( SalesServiceEnums.TRC_ADDRESS.getType(), SalesServiceEnums.TRC_ADDRESS.getCode() ); String receiveAddress = dataDictionaryCustom.getValue(); if (receiveAddress == null) { log.error("请先配置系统地址"); return; } //https://services.tokenview.io/vipapi/trx/token/TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t String url = "https://services.tokenview.io/vipapi/trx/address/tokentrans/"+receiveAddress+"/TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t/1/10"; // 定时任务的执行时间和转账时间区间间隔5分钟 // 每次将上次的时间存入redis,第一次使用默认的时间 long endTime = System.currentTimeMillis(); long startTime = endTime-TIME_INTERVAL; System.out.println(new Date()+" 自动充值定时任务 "+startTime+" "+endTime); // 当前的充值地址 TRC20USDT_ADDRESS Map param = new HashMap<>(); param.put("timestampStart", startTime + ""); param.put("timestampEnd", endTime + ""); param.put("toAddress", receiveAddress); param.put("apikey", TRON_API_KEY); long l = System.currentTimeMillis(); byte[] bytes = OkHttpUtil2.doGetSingle(url, REQUEST_HEADER, param, "application/json"); if (ObjectUtil.isEmpty( bytes )) { log.error("查询链上数据返回为空,传参:{}",param); return; } String s = new String(bytes, StandardCharsets.UTF_8); log.info("查询到的充值记录:{}", s); Trc20TokenviewModel trc20TransfersModel = JSONObject.parseObject(s, Trc20TokenviewModel.class); List tokenTransfers = trc20TransfersModel.getData(); if (CollUtil.isEmpty(tokenTransfers)) { //logger.error("FyTrc20RechargeTask查询链上数据返回没有token转账,返回结果:{}",s); return; } long l1 = System.currentTimeMillis(); log.info("查询trc耗时:{}", (l1 - l)); log.info("查询到的充值记录:{}", JSONObject.toJSONString(trc20TransfersModel)); log.info("时间区间,start:{},end:{}", startTime, endTime); // 有记录 for (Trc20TokenviewContentModel tokenTransfer : tokenTransfers) { log.info("链上时间:{}", tokenTransfer.getTime()); // 从数据库 String transactionId = tokenTransfer.getTxid(); List chatOrders = mallOrderInfoMapper.selectList( Wrappers.lambdaQuery(MallOrderInfo.class) .eq(MallOrderInfo::getTradeHash, transactionId) ); if(CollUtil.isNotEmpty(chatOrders)){ log.info("扫描到HASH已使用:{}",transactionId); continue; } // 金额 String quant = tokenTransfer.getValue(); BigDecimal amount = new BigDecimal(quant).divide(new BigDecimal("1000000")).setScale(2, RoundingMode.DOWN); String amountKey = OrderConstants.TRC20_ORDER_KEY + amount; String orderCode = redisUtils.getString(amountKey); if (StrUtil.isBlank(orderCode)) { log.info("Redis未扫描到充值金额:{}",transactionId); continue; } MallOrderInfo chatOrder = mallOrderInfoMapper.selectOne( Wrappers.lambdaQuery(MallOrderInfo.class) .eq(MallOrderInfo::getOrderNo, orderCode) ); if(chatOrder==null){ log.error("未找到订单:{}",orderCode); continue; } if(OrderStatusEnum.WAIT_PAY.getValue() != chatOrder.getStatus()){ log.error("订单不是待充值状态: {},订单编号:{}",transactionId,orderCode); continue; } mallOrderInfoMapper.update( null, Wrappers.lambdaUpdate(MallOrderInfo.class) .set(MallOrderInfo::getStatus, OrderStatusEnum.WAIT_SHIPPING.getValue()) .set(MallOrderInfo::getTradeHash, transactionId) .set(MallOrderInfo::getPayTime, new Date()) .set(MallOrderInfo::getPayResult, "1") .eq(MallOrderInfo::getId, chatOrder.getId()) ); redisUtils.del(amountKey); log.info("Redis扫描到充值记录:{},订单编号:{}",transactionId,orderCode); } } public static void main(String[] args) { String receiveAddress = "TExto1UjtFcXKw5QdJDRqtx7wTQ15D37GD"; String url = "https://services.tokenview.io/vipapi/trx/address/tokentrans/"+receiveAddress+"/TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t/1/10"; // 定时任务的执行时间和转账时间区间间隔5分钟 // 每次将上次的时间存入redis,第一次使用默认的时间 long endTime = System.currentTimeMillis(); long startTime = endTime-TIME_INTERVAL; System.out.println(new Date()+" 自动充值定时任务fyTrc20RechargeTokenviewTask "+startTime+" "+endTime); // 当前的充值地址 TRC20USDT_ADDRESS Map param = new HashMap<>(); param.put("timestampStart", startTime + ""); param.put("timestampEnd", endTime + ""); param.put("toAddress", receiveAddress); param.put("apikey", TRON_API_KEY); long l = System.currentTimeMillis(); byte[] bytes = OkHttpUtil2.doGetSingle(url, REQUEST_HEADER, param, "application/json"); if (bytes == null) { log.error("FyTrc20RechargeTask查询链上数据返回为空,传参:{}",param); return; } String s = new String(bytes, StandardCharsets.UTF_8); System.out.println(s); System.exit(0); } }