Administrator
2026-06-13 befbb28b2810ed108d2744bceee2bb9b3edaa9bc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
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 TRC20_TRANSFER_API = "https://apilist.tronscanapi.com/api/token_trc20/transfers";
 
    public final static String TRC20_CONTRACT_ADDRESS = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
 
    private final static String TRON_API_KEY = "32c9841d-19ae-48cf-a535-cf56d9d25f1c";
 
    private static Map<String, String> REQUEST_HEADER = new HashMap<>();
    static {
        REQUEST_HEADER.put("TRON-PRO-API-KEY", TRON_API_KEY);
    }
 
    @Scheduled(cron = "0 0/5 * * * ? ")
    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;
        }
        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<String, String> 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("FyTrc20RechargeTask查询链上数据返回为空,传参:{}",param);
            return;
        }
 
        String s = new String(bytes, StandardCharsets.UTF_8);
        log.info("查询到的充值记录:{}", s);
        Trc20TokenviewModel trc20TransfersModel = JSONObject.parseObject(s, Trc20TokenviewModel.class);
        List<Trc20TokenviewContentModel> 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<MallOrderInfo> 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<String, String> 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);
    }
}