zainali5120
2020-07-16 1c043f5cda42801c0dcc830df5b95c6916dc5ec2
XRP同步提交
4 files modified
582 ■■■■ changed files
src/main/java/com/xcong/excoin/modules/blackchain/model/XrpTx.java 69 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/blackchain/service/XrpService.java 424 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java 87 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/blackchain/model/XrpTx.java
@@ -1,63 +1,18 @@
package com.xcong.excoin.modules.blackchain.model;
public class XrpTx {
    private String TransactionType;
    private Integer Flags;
    private Integer Sequence;
    private Integer DestinationTag; // 对应的用户标签
    private Integer Amount; // 金额 除以1000000 一百万
    private Integer Fee;  // 手续费
    private String Account; // 转账人
    private String Destination; // 收款人(收款人是系统账户 说明是转入)
import lombok.Data;
    
    public String getTransactionType() {
        return TransactionType;
    }
    public void setTransactionType(String transactionType) {
        TransactionType = transactionType;
    }
    public Integer getFlags() {
        return Flags;
    }
    public void setFlags(Integer flags) {
        Flags = flags;
    }
    public Integer getSequence() {
        return Sequence;
    }
    public void setSequence(Integer sequence) {
        Sequence = sequence;
    }
    public Integer getDestinationTag() {
        return DestinationTag;
    }
    public void setDestinationTag(Integer destinationTag) {
        DestinationTag = destinationTag;
    }
    public Integer getAmount() {
        return Amount;
    }
    public void setAmount(Integer amount) {
        Amount = amount;
    }
    public Integer getFee() {
        return Fee;
    }
    public void setFee(Integer fee) {
        Fee = fee;
    }
    public String getAccount() {
        return Account;
    }
    public void setAccount(String account) {
        Account = account;
    }
    public String getDestination() {
        return Destination;
    }
    public void setDestination(String destination) {
        Destination = destination;
    }
@Data
public class XrpTx {
    private String transactionType;
    private Integer flags;
    private Integer sequence;
    private Integer destinationTag; // 对应的用户标签
    private Integer amount; // 金额 除以1000000 一百万
    private Integer fee;  // 手续费
    private String account; // 转账人
    private String destination; // 收款人(收款人是系统账户 说明是转入)
    
}
src/main/java/com/xcong/excoin/modules/blackchain/service/XrpService.java
@@ -24,7 +24,10 @@
public class XrpService {
    // private //logger //logger = //logger.get//logger(getClass());
    /**
     *  平台钱包地址
     */
    public final static String ACCOUNT="rKMGEyjXErL2dx9ck5QXFJVH8onSfHF5gn";
    /**
     * 官方接口地址
     */
@@ -32,65 +35,13 @@
    private String postUrl = "https://s1.ripple.com:51234";
    /**
     * 本地nodejs创建钱包地址
     * 结果类型
     */
    private static String localUrl = "http://121.40.86.163:1886";
    private String address;
    private String password;
    private static final String gasFee = "100";
    private static final String COIN_XRP = "XRP";
    private final static String RESULT = "result";
    private final static String SUCCESS = "success";
    private final static String TES_SUCCESS = "tesSUCCESS";
    private final static String METHOD_GET_TRANSACTION = "/v2/accounts/{0}/transactions";
    private final static String METHOD_GET_BALANCE = "/v2/accounts/{0}/balances";
    private final static String METHOD_POST_SIGN = "sign";
    private final static String METHOD_POST_INDEX = "ledger_current";
    private final static String METHOD_POST_ACCOUNT_INFO = "account_info";
    private final static String METHOD_POST_SUBMIT = "submit";
    public XrpService(String address, String password) {
        try {
            this.address = address;
            this.password = password;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public String getAddress() {
        return address;
    }
    public static void main(String[] args) {
        // 十分钟查一次 每次100条
        String result =  HttpUtil.get("https://data.ripple.com/v2/accounts/rBEXvZL66VvaMzX5R2W5g5xC9Z3D81wkzb/transactions?start=2019-09-01T10:10:00Z");
         JSONObject json = JSONObject.parseObject(result);
         XrpTransResult res = json.toJavaObject(XrpTransResult.class);
    }
    /**
     * 创建钱包 { "xAddress":"X7bpbHDKxS3Mr417RPtgS3TFFHwAHqULXJUVZntHWAKnccw",
     * "secret":"snYpXT4wrhi8ve2miSUHUdn9wgzz7",
     * "classicAddress":"rsJftGoh49zju51k2LdvUYrzLzJ44XJpXh",
     * "address":"rsJftGoh49zju51k2LdvUYrzLzJ44XJpXh" }
     *
     * @return
     */
    public static JSONObject createWallet() {
        String res = HttpUtil.get(localUrl);
        JSONObject obj = JSONObject.parseObject(res);
        return obj;
    }
    /**
     * 查询交易记录 用于更新用户的余额 本系统的地址:X75MxY8sjcebBasymUXDYcYHWj6v8wqWLGmg9N3x65SXUJw
     * https://data.ripple.com/v2/accounts/rBEXvZL66VvaMzX5R2W5g5xC9Z3D81wkzb/transactions
     * https://data.ripple.com/v2/accounts/rBEXvZL66VvaMzX5R2W5g5xC9Z3D81wkzb/transactions?start=2019-09-01T10:10:00Z&limit=1
     */
    /**
     * start YYYY-MM-DDThh:mm:ssZ String - Timestamp Start time of query range. The default is the
@@ -109,13 +60,12 @@
     * returned response.
     * 
     * https://github.com/ripple/rippled-historical-database
     *  接口文档:https://xrpl.org/data-api.html#get-account
     */
    public static XrpTransResult getTransactions(Date start) {
        // SimpleDateFormat dateFormat = new SimpleDateFormat("YYYY-MM-DDThh:mm:ssZ");
         SimpleDateFormat formatDay = new SimpleDateFormat("YYYY-MM-dd");
         SimpleDateFormat formatHour = new SimpleDateFormat("hh:mm:ss");
         String startTime = formatDay.format(start)+"T"+formatHour.format(start)+"Z";
         String url ="https://data.ripple.com/v2/accounts/X75MxY8sjcebBasymUXDYcYHWj6v8wqWLGmg9N3x65SXUJw/transactions?start="+startTime+"&limit=1000";
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        String startTime = dateFormat.format(start);
        String url ="https://data.ripple.com/v2/accounts/"+ACCOUNT+"/transactions?type=Payment&result=tesSUCCESS&limit=20&start="+startTime;
         // 十分钟查一次 每次100条
         String result =  HttpUtil.get(url);
         try {
@@ -126,362 +76,6 @@
             e.printStackTrace();
         }
        return null;
    }
    /**
     * XRP查询余额
     *
     * @return
     */
    public static double getBalance(String address) {
        try {
            HashMap<String, String> params = new HashMap<String, String>();
            params.put("currency", COIN_XRP);
            String re = HttpUtil.jsonGet(getUrl + MessageFormat.format(METHOD_GET_BALANCE, address), params);
            if (!StringUtils.isEmpty(re)) {
                JSONObject json = JSON.parseObject(re);
                if (SUCCESS.equals(json.getString(RESULT))) {
                    JSONArray array = json.getJSONArray("balances");
                    if (array != null && array.size() > 0) {
                        // 总余额
                        double balance = array.getJSONObject(0).getDoubleValue("value");
                        if (balance >= 20) {
                            // 可用余额 xrp会冻结20个币
                            return BigDecimalUtil.sub(balance, 20);
                        }
                    }
                }
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币getBalance失败!");
            e.printStackTrace();
        }
        return 0.00;
    }
    /**
     * 发送交易
     *
     * @param address
     * @param value
     * @return
     */
    public synchronized String send(String toAddress, double value, String tag) {
        try {
            String txBlob = this.sign(toAddress, value, tag);
            if (StringUtils.isEmpty(txBlob)) {
                // logger.error("签名失败:{" + toAddress + "}");
                return null;
            }
            HashMap<String, Object> params = new HashMap<String, Object>();
            params.put("tx_blob", txBlob);
            // 签名
            JSONObject json = doRequest(METHOD_POST_SUBMIT, params);
            if (!isError(json)) {
                // logger.error("============瑞波币XRP转账返回!json="+json);
                JSONObject result = json.getJSONObject(RESULT);
                if (result != null) {
                    if (TES_SUCCESS.equals(result.getString("engine_result"))) {
                        String hash = result.getJSONObject("tx_json").getString("hash");
                        if (!StringUtils.isEmpty(hash)) {
                            // logger.error("转账成功:toAddress:{" + toAddress + "},value:{" + value +
                            // "},hash:{" + hash + "}");
                            return hash;
                        } else {
                            // logger.error(
                            // "转账失败:toAddress:{" + toAddress + "},value:{" + value + "},hash:{" + hash +
                            // "}");
                        }
                    }
                }
            } else {
                // logger.error("============瑞波币XRP转账失败!json="+json);
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币send失败!");
            e.printStackTrace();
        }
        return null;
    }
    public synchronized String sendOnLine(String toAddress, double value, String tag) {
        try {
            String txBlob = this.signOnLine(toAddress, value, tag);
            if (StringUtils.isEmpty(txBlob)) {
                // logger.error("签名失败:{" + toAddress + "}");
                return null;
            }
            HashMap<String, Object> params = new HashMap<String, Object>();
            params.put("tx_blob", txBlob);
            // 签名
            JSONObject json = doRequest(METHOD_POST_SUBMIT, params);
            if (!isError(json)) {
                // logger.error("============瑞波币XRP转账返回!json="+json);
                JSONObject result = json.getJSONObject(RESULT);
                if (result != null) {
                    if (TES_SUCCESS.equals(result.getString("engine_result"))) {
                        String hash = result.getJSONObject("tx_json").getString("hash");
                        if (!StringUtils.isEmpty(hash)) {
                            // logger.error("转账成功:toAddress:{" + toAddress + "},value:{" + value +
                            // "},hash:{" + hash + "}");
                            return hash;
                        } else {
                            // logger.error(
                            // "转账失败:toAddress:{" + toAddress + "},value:{" + value + "},hash:{" + hash +
                            // "}");
                        }
                    }
                }
            } else {
                // logger.error("==============瑞波币XRP转账失败!json="+json);
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币send失败!");
            e.printStackTrace();
        }
        return null;
    }
    @Deprecated
    public String signOnLine(String toAddress, Double value, String tag) {
        try {
            // 瑞波币余额存储加六位长度
            value = BigDecimalUtil.mul(value, 1000000);
            Integer vInteger = BigDecimal.valueOf(value).intValue();
            JSONObject txJson = new JSONObject();
            txJson.put("Account", address);
            txJson.put("Amount", vInteger.toString());
            txJson.put("Destination", toAddress);// 标签
            txJson.put("TransactionType", "Payment");
            txJson.put("DestinationTag", tag);
            HashMap<String, Object> params = new HashMap<String, Object>();
            params.put("secret", password);
            params.put("tx_json", txJson);
            params.put("offline", false);
            // 签名
            JSONObject json = doRequest(METHOD_POST_SIGN, params);
            if (!isError(json)) {
                // logger.error("==============XRP签名返回:"+json);
                JSONObject result = json.getJSONObject(RESULT);
                if (result != null) {
                    if (SUCCESS.equals(result.getString("status"))) {
                        return result.getString("tx_blob");
                    }
                }
            } else {
                // logger.error("瑞波币XRP签名失败!json="+json);
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币signOnLine失败!");
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 签名
     *
     * @param address
     * @param value
     * @return tx_blob
     */
    public String sign(String toAddress, Double value, String tag) {
        try {
            value = BigDecimalUtil.mul(value, 1000000);
            Integer vInteger = BigDecimal.valueOf(value).intValue();
            Map<String, String> map = getAccountSequenceAndLedgerCurrentIndex();
            Payment payment = new Payment();
            payment.as(AccountID.Account, address);
            payment.as(AccountID.Destination, toAddress);
            payment.as(UInt32.DestinationTag, tag);
            payment.as(Amount.Amount, vInteger.toString());
            payment.as(UInt32.Sequence, map.get("accountSequence"));
            payment.as(UInt32.LastLedgerSequence, map.get("ledgerCurrentIndex") + 4);
            payment.as(Amount.Fee, gasFee);
            SignedTransaction signed = payment.sign(password);
            if (signed != null) {
                return signed.tx_blob;
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币sign失败!");
            e.printStackTrace();
        }
        return null;
    }
    public Map<String, String> getAccountSequenceAndLedgerCurrentIndex() {
        try {
            HashMap<String, String> params = new HashMap<String, String>();
            params.put("account", address);
            params.put("strict", "true");
            params.put("ledger_index", "current");
            params.put("queue", "true");
            JSONObject re = doRequest(METHOD_POST_ACCOUNT_INFO, params);
            if (re != null) {
                JSONObject result = re.getJSONObject("result");
                if (SUCCESS.equals(result.getString("status"))) {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("accountSequence", result.getJSONObject("account_data").getString("Sequence"));
                    map.put("ledgerCurrentIndex", result.getString("ledger_current_index"));
                    return map;
                }
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币getAccountSequenceAndLedgerCurrentIndex失败!");
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取用户交易序列号
     *
     * @return
     */
    public long getAccountSequence() {
        try {
            HashMap<String, String> params = new HashMap<String, String>();
            params.put("account", address);
            params.put("strict", "true");
            params.put("ledger_index", "current");
            params.put("queue", "true");
            JSONObject re = doRequest(METHOD_POST_ACCOUNT_INFO, params);
            if (re != null) {
                JSONObject result = re.getJSONObject("result");
                if (SUCCESS.equals(result.getString("status"))) {
                    return result.getJSONObject("account_data").getLongValue("Sequence");
                }
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币getAccountSequence失败!");
            e.printStackTrace();
        }
        return 0L;
    }
    /**
     * 获取最新序列
     *
     * @return
     */
    public long getLedgerIndex() {
        try {
            JSONObject re = doRequest(METHOD_POST_INDEX);
            if (re != null) {
                JSONObject result = re.getJSONObject("result");
                if (SUCCESS.equals(result.getString("status"))) {
                    return result.getLongValue("ledger_current_index");
                }
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币getLedgerIndex失败!");
            e.printStackTrace();
        }
        return 0L;
    }
    public String getTransaction(Date dateGMT, String limit) throws ParseException {
        try {
            HashMap<String, String> params = new HashMap<String, String>();
            params.put("start", DateUtil.formatDate(dateGMT, "yyyy-MM-dd'T'HH:mm:ss"));
            params.put("result", "tesSUCCESS");
            params.put("type", "Payment");
            params.put("limit", limit);
            return HttpUtil.jsonGet(getUrl + MessageFormat.format(METHOD_GET_TRANSACTION, address), params);
            // {"result":"success","count":1,"transactions":[{"hash":"86859CBEFB870C941727E291BB13312BC3D6042D8DA08BF1DEDE6BB55F21B8EC","ledger_index":42268358,"date":"2018-10-16T06:49:30+00:00","tx":{"TransactionType":"Payment","Flags":2147483648,"Sequence":37996,"Amount":"29840000","Fee":"1000","SigningPubKey":"0279154FA62D1F28B6CB1F0264663F19EF3A1718D15363CAC1B47A9C6987231F94","TxnSignature":"304502210089F6526134F335C01C65D3E82284C06E22598A4EAD912604BF4FEAA42D5ACCE402203C044F32D399CEA6F4A16DD6DCBB339A7D0CF76E52C1AB090330A67EDFBABBE4","Account":"rH8yTBLm2SYgcL5HQGDznuNxMiy5ayYcmK","Destination":"raHb1tR1BcNB92nEqxiTuKsDap46szkJG2"},"meta":{"TransactionIndex":1,"AffectedNodes":[{"CreatedNode":{"LedgerEntryType":"AccountRoot","LedgerIndex":"56419B3209DA988033F6F0BD921806B4821A73EDF8C338FB5F06C785E527E967","NewFields":{"Sequence":1,"Balance":"29840000","Account":"raHb1tR1BcNB92nEqxiTuKsDap46szkJG2"}}},{"ModifiedNode":{"LedgerEntryType":"AccountRoot","PreviousTxnLgrSeq":42268355,"PreviousTxnID":"63D5A3121F2706099835D9A3A9E5DA574070A4E08FC70956DB1CC196DE6CDEFC","LedgerIndex":"7D2FC14FA2B344F41BB8A6E10B319301EA1C11705AE159B3E2FA82D9F3079E4C","PreviousFields":{"Sequence":37996,"Balance":"2051629511468"},"FinalFields":{"Flags":131072,"Sequence":37997,"OwnerCount":0,"Balance":"2051599670468","Account":"rH8yTBLm2SYgcL5HQGDznuNxMiy5ayYcmK"}}}],"TransactionResult":"tesSUCCESS","delivered_amount":"29840000"}}]}
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币getBalance失败!");
            e.printStackTrace();
        }
        return null;
    }
    public Long parseTransaction(String startTm) throws ParseException {
        try {
            HashMap<String, String> params = new HashMap<String, String>();
            if (!StringUtils.isEmpty(startTm)) {
                Date d = new Date(BigDecimalUtil.longAdd(Long.parseLong(startTm), 1000L));
                params.put("start", DateUtil.formatDate(d, "yyyy-MM-dd'T'HH:mm:ss"));
            }
            params.put("result", "tesSUCCESS");
            params.put("type", "Payment");
            params.put("limit", "1");
            String re = HttpUtil.jsonGet(getUrl + MessageFormat.format(METHOD_GET_TRANSACTION, address), params);
            if (!StringUtils.isEmpty(re)) {
                JSONObject json = JSON.parseObject(re);
                if (SUCCESS.equals(json.getString(RESULT))) {
                    // marker = json.getString("marker");
                    JSONArray transactions = json.getJSONArray("transactions");
                    if (transactions != null && transactions.size() > 0) {
                        for (Object object : transactions) {
                            JSONObject transaction = (JSONObject) object;
                            String hash = transaction.getString("hash");
                            String dateString = transaction.getString("date");
                            Date date = DateUtil.parseDate(dateString, "yyyy-MM-dd'T'HH:mm:ss");
                            JSONObject tx = transaction.getJSONObject("tx");
                            String destinationTag = tx.getString("DestinationTag");
                            if (StringUtils.isEmpty(destinationTag)) {
                                // logger.info("非用户充值记录");
                                return date.getTime();
                            }
                            String to = tx.getString("Destination");
                            if (!address.equals(to)) {
                                // logger.info("非用户充值记录,地址不一致");
                                return date.getTime();
                            }
                            // 校验用户是否存在
                            /*
                             * UserEntity user = userService.getUserById(Integer.parseInt( destinationTag));
                             * if (user == null) { //logger.info("用户不存在:{}",destinationTag); return
                             * date.getTime(); }
                             */
                            double amount = tx.getDoubleValue("Amount");
                            if (amount > 0) {
                                amount = BigDecimalUtil.div(amount, 1000000, 6);
                            } else {
                                // logger.error("交易金额异常:{" + amount + "}");
                                return date.getTime();
                            }
                            // 添加充值记录
                        }
                    }
                }
            }
        } catch (Exception e) {
            // logger.error("==============虚拟币-瑞波币parseTransaction失败!");
            e.printStackTrace();
        }
        return null;
    }
    private boolean isError(JSONObject json) {
        if (json == null || (!StringUtils.isEmpty(json.getString("error")) && json.get("error") != "null")) {
            return true;
        }
        return false;
    }
    private JSONObject doRequest(String method, Object... params) {
        JSONObject param = new JSONObject();
        param.put("id", System.currentTimeMillis() + "");
        param.put("jsonrpc", "2.0");
        param.put("method", method);
        if (params != null) {
            param.put("params", params);
        }
        String creb = Base64.encodeBase64String((address + ":" + password).getBytes());
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Authorization", "Basic " + creb);
        String resp = "";
        try {
            resp = HttpUtil.jsonPost(postUrl, headers, param.toJSONString());
        } catch (Exception e) {
            // logger.info(e.getMessage());
            if (e instanceof IOException) {
                resp = "{}";
            }
        }
        return JSON.parseObject(resp);
    }
}
src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java
@@ -12,4 +12,6 @@
    public void updateEos();
    public void updateXrp();
}
src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java
@@ -6,10 +6,10 @@
import cn.hutool.core.util.StrUtil;
import com.xcong.excoin.common.enumerates.CoinTypeEnum;
import com.xcong.excoin.modules.blackchain.model.EosResult;
import com.xcong.excoin.modules.blackchain.service.BtcService;
import com.xcong.excoin.modules.blackchain.service.EosService;
import com.xcong.excoin.modules.blackchain.service.EthService;
import com.xcong.excoin.modules.blackchain.service.UsdtService;
import com.xcong.excoin.modules.blackchain.model.XrpTransResult;
import com.xcong.excoin.modules.blackchain.model.XrpTransactions;
import com.xcong.excoin.modules.blackchain.model.XrpTx;
import com.xcong.excoin.modules.blackchain.service.*;
import com.xcong.excoin.modules.coin.service.BlockCoinService;
import com.xcong.excoin.modules.member.dao.MemberCoinAddressDao;
import com.xcong.excoin.modules.member.dao.MemberCoinChargeDao;
@@ -26,6 +26,7 @@
import com.xcong.excoin.utils.mail.Sms106Send;
import com.xcong.excoin.utils.mail.SubMailSend;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@@ -34,6 +35,8 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@@ -58,6 +61,8 @@
    private RedisUtils redisUtils;
    private final static String EOS_SEQ_KEY="eos_seq_key";
    private final static String xrp_update_key = "xrp_update_key";
    @Transactional(rollbackFor = Exception.class)
    @Override
@@ -327,6 +332,80 @@
        }
    }
    public void updateXrp() {
        // 首先去查redis上的上次同步时间
        Object lastUpdateTime = redisUtils.get(xrp_update_key);
        SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd hh:mm:ss");
        Date start =null;
        if(lastUpdateTime==null) {
            // 没有 说明是第一次同步 此时从第一天开始同步2020 0716开始
            try {
                start = format.parse("2020-07-16 12:00:00");
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }else {
            // 有上次时间
            try {
                start = format.parse(lastUpdateTime.toString());
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        // 去查询上次同步时间后的所有记录
        XrpTransResult result = XrpService.getTransactions(start);
        // 写入本次更新时间
        String updateTime = format.format(new Date());
        redisUtils.set(xrp_update_key, updateTime);
        // 判断有无
        List<XrpTransactions> list = result.getTransactions();
        if(CollectionUtils.isNotEmpty(list)) {
            // 不为空 说明有转入记录
            for(XrpTransactions item:list) {
                XrpTx data = item.getTx();
                Integer amountOld = data.getAmount();
                // 除以1000000
                BigDecimal amount = new BigDecimal(amountOld).divide(new BigDecimal(1000000));
                Integer memoInt = data.getDestinationTag();
                // 没有标签直接返回
                if(memoInt==null){
                    continue;
                }
                String memo = memoInt.toString();
                String destination = data.getDestination();
                // 判断收款人是不是系统账号
                if(!XrpService.ACCOUNT.equals(destination)){
                    continue;
                }
                List<MemberCoinAddressEntity> memberCoinAddress = memberCoinAddressDao.selectAllBlockAddressBySymbolAndTag(CoinTypeEnum.XRP.name(), memo);
                if(CollectionUtils.isNotEmpty(memberCoinAddress)){
                    MemberCoinAddressEntity memberCoinAddressEntity = memberCoinAddress.get(0);
                    // 用户ID
                    Long memberId = memberCoinAddressEntity.getMemberId();
                    MemberWalletCoinEntity memberWalletCoinEntity = memberWalletCoinDao.selectWalletCoinBymIdAndCode(memberId, CoinTypeEnum.XRP.name());
                    if(memberCoinAddressEntity!=null){
                        memberWalletCoinDao.updateBlockBalance(memberWalletCoinEntity.getId(),amount,BigDecimal.ZERO,0);
                        // 添加冲币记录
                        String orderNo = insertCoinCharge(XrpService.ACCOUNT,memberId,amount,CoinTypeEnum.XRP.name(),memo,BigDecimal.ZERO);
                        LogRecordUtils.insertMemberAccountMoneyChange(memberId, "转入", amount, CoinTypeEnum.XRP.name(), 1, 1);
                        ThreadPoolUtils.sendDingTalk(5);
                        MemberEntity member = memberDao.selectById(memberId);
                        if (StrUtil.isNotBlank(member.getPhone())) {
                            //String amountEos = amount + "XRP";
                            Sms106Send.sendRechargeMsg(member.getPhone(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo);
                        } else {
                            SubMailSend.sendRechargeMail(member.getEmail(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo);
                        }
                    }
                }
            }
        }
    }
    private String generateNo() {
        // 生成订单号
        Long timestamp = System.currentTimeMillis();