package cc.mrbird.febs.mall.chain.trcCoin.quartz; import cc.mrbird.febs.common.enumerates.RunVipDataDictionaryEnum; import cc.mrbird.febs.common.enumerates.YesOrNoEnum; import cc.mrbird.febs.mall.chain.trcCoin.OkHttpUtil2; import cc.mrbird.febs.mall.chain.trcCoin.OklinkDataPageDetailModel; import cc.mrbird.febs.mall.chain.trcCoin.OklinkModel; import cc.mrbird.febs.mall.entity.MallCharge; import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper; import cc.mrbird.febs.mall.mapper.MallChargeMapper; import cc.mrbird.febs.rabbit.producter.AgentProducer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j @Component @ConditionalOnProperty(prefix = "chain", name = "trc", havingValue = "true") public class ChainTrcListenerJob { @Resource private DataDictionaryCustomMapper dataDictionaryCustomMapper; @Resource private MallChargeMapper mallChargeMapper; @Resource private AgentProducer agentProducer; /** * 五分钟 毫秒 */ private final static long TIME_INTERVAL_1HOUR = 300000*12; private final static String TRC20_TRANSFER_API = "https://www.oklink.com/api/v5/explorer/address/token-transaction-list"; public final static String TRC20_CONTRACT_ADDRESS = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"; public final static String TRC20_NAME = "TRON"; public final static String TOKEN_20 = "token_20"; /** * todo 替换成自己的API-KEY */ private final static String TRON_API_KEY = "21fc662e-03f1-4f60-9124-7b63c0d6c813"; private static Map REQUEST_HEADER = new HashMap<>(); static { REQUEST_HEADER.put("Ok-Access-Key", TRON_API_KEY); } @Scheduled(cron = "0 0/2 * * * ? ") public void chainBlockUpdate() { log.info("TRC20同步"); String sysAddress = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( RunVipDataDictionaryEnum.CHARGE_SYS_ADDRESS_TRC.getType(), RunVipDataDictionaryEnum.CHARGE_SYS_ADDRESS_TRC.getCode() ).getValue(); String type = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( RunVipDataDictionaryEnum.CHARGE_TYPE_TRC.getType(), RunVipDataDictionaryEnum.CHARGE_TYPE_TRC.getCode() ).getValue(); if(StrUtil.isBlank(sysAddress)){ log.info("系统未设置充值地址"); return; } // 定时任务的执行时间和转账时间区间间隔5分钟 // 查询过去5分钟的记录 Map param = new HashMap<>(); param.put("chainShortName", TRC20_NAME); param.put("protocolType", TOKEN_20); param.put("tokenContractAddress", TRC20_CONTRACT_ADDRESS); param.put("address", sysAddress); param.put("limit", "100"); long l = System.currentTimeMillis(); byte[] bytes = OkHttpUtil2.doGetSingle(TRC20_TRANSFER_API, REQUEST_HEADER, param, "application/json"); if (bytes == null) { log.error("fyTrc20RechargeOklinkTask查询链上数据返回为空,传参:{}",param); return; } String s = new String(bytes, StandardCharsets.UTF_8); OklinkModel trc20TransfersModel = JSONObject.parseObject(s, OklinkModel.class); List tokenTransfers = trc20TransfersModel.getData().get(0).getTransactionList(); if (CollUtil.isEmpty(tokenTransfers)) { return; } long l1 = System.currentTimeMillis(); log.info("查询trc耗时:{}", (l1 - l)); // 有记录 for (OklinkDataPageDetailModel tokenTransfer : tokenTransfers) { String transactionTime = tokenTransfer.getTransactionTime(); Long transTime = Long.valueOf(transactionTime); if ((transTime + TIME_INTERVAL_1HOUR) < l1) { continue; } // 把1个小时前的数据过滤 log.info("链上时间:{}", transactionTime); // 判断收款地址是否是设置的平台地址 if (sysAddress.equals(tokenTransfer.getTo())) { String transactionId = tokenTransfer.getTxId(); LambdaQueryWrapper mallChargeLambdaQueryWrapper = new LambdaQueryWrapper<>(); mallChargeLambdaQueryWrapper.eq(MallCharge::getTransHash, transactionId); List list = mallChargeMapper.selectList(mallChargeLambdaQueryWrapper); if(CollUtil.isNotEmpty(list)){ log.info("扫描到HASH已使用:{}",transactionId); return; } String fromAddress = tokenTransfer.getFrom(); if (fromAddress.equals(sysAddress)) { log.info("系统地址转出:{}", transactionId); continue; } BigDecimal amount = new BigDecimal(tokenTransfer.getAmount()); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(MallCharge::getAddress, fromAddress); queryWrapper.eq(MallCharge::getSysAddress, sysAddress); queryWrapper.eq(MallCharge::getAmount, amount); queryWrapper.eq(MallCharge::getType, type); queryWrapper.eq(MallCharge::getState, YesOrNoEnum.ING.getValue()); List mallCharges = mallChargeMapper.selectList(queryWrapper); if(CollUtil.isEmpty(mallCharges)){ log.info("未查询到匹配充值记录,充值地址:{},HASH:{}",fromAddress,transactionId); continue; } MallCharge mallCharge = mallCharges.get(0); mallCharge.setState(YesOrNoEnum.YES.getValue()); mallChargeMapper.updateById(mallCharge); if(StrUtil.isNotEmpty(mallCharge.getVipCode())){ agentProducer.sendBuyVipSuccessMsg(mallCharge.getId()); }else{ agentProducer.sendChargeSuccessMsg(mallCharge.getId()); } log.info("扫描到用户ID:{},地址:{},充值金额:{}", mallCharge.getMemberId(), fromAddress, amount); } } } }