src/main/java/com/xcong/excoin/configurations/security/TokenFilter.java
@@ -65,7 +65,7 @@ MemberEntity loginUser = JSONObject.parseObject(loginStr, MemberEntity.class); Authentication authentication = new UsernamePasswordAuthenticationToken(loginUser, token, new ArrayList<>()); SecurityContextHolder.getContext().setAuthentication(authentication); redisUtils.expire(redisKey, 300000); redisUtils.expire(redisKey, 36000); } else { log.info("token无法查询:{}", token); SecurityContextHolder.clearContext(); src/main/java/com/xcong/excoin/modules/blackchain/model/EosResult.java
New file @@ -0,0 +1,28 @@ package com.xcong.excoin.modules.blackchain.model; import lombok.Data; /** * 数据样例 * EosResult(quantity=2.0000 EOS, memo=aa, from=okbtothemoon, to=biueeostoken, accountActionSeq=2) */ @Data public class EosResult { /** * 转账数量 */ private String quantity; /** * 转账标记 */ private String memo; private String from; private String to; /** * 这笔转账对应于这个账户的序号 */ private Integer accountActionSeq; } src/main/java/com/xcong/excoin/modules/blackchain/model/XrpTx.java
@@ -1,63 +1,18 @@ package com.xcong.excoin.modules.blackchain.model; import lombok.Data; @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; // 收款人(收款人是系统账户 说明是转入) 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; // 收款人(收款人是系统账户 说明是转入) 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; } } src/main/java/com/xcong/excoin/modules/blackchain/service/EosService.java
New file @@ -0,0 +1,84 @@ package com.xcong.excoin.modules.blackchain.service; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.blackchain.model.EosResult; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class EosService { // 正式网络 https://api-v2.eosasia.one https://proxy.eosnode.tools // 测试网络 https://api-kylin.eosasia.one // "eosqxyx11111", "5JJB2oiCXwASK9fumjyTgbtHcwDVedVRaZda1kBhFuQcmjnrDWB" //private final static String account = "huobideposit"; public final static String ACCOUNT = "biueeostoken"; // private String account; private final static String EOS_NAME = "EOS"; public static final String K_mnemonic = "mnemonic"; public static final String K_privateKey = "privateKey"; public static final String K_publicKey = "publicKey"; private static final String EOS_TOKEN = "eosio.token"; private static final String ACTION_TRANSFER = "transfer"; public static void main(String[] args) throws Exception { List<EosResult> actions = getActions(0, 3); for(EosResult eosResult:actions){ System.out.println(eosResult.toString()); String quantity = eosResult.getQuantity(); String amountStr = quantity.split("")[0]; System.out.println(quantity); System.out.println(new BigDecimal(amountStr)); } } /** * * @param pos 从第几条开始(包括pos) * @param offset 查询条数 * @return */ public static List<EosResult> getActions(int pos, int offset) { JSONObject param = new JSONObject(); param.put("account_name", ACCOUNT); param.put("pos", pos); param.put("offset", offset); Map<String, String> header = new HashMap<String, String>(); header.put("content-type", "application/json"); String res = HttpUtil.post("https://api.eosflare.io/v1/eosflare/get_actions", null, param.toJSONString(), header); System.out.println(res); List<EosResult> results = new ArrayList<>(); try { JSONObject jsonObject = JSONObject.parseObject(res); JSONArray actions = jsonObject.getJSONArray("actions"); if (actions != null && actions.size() > 0) { int size = actions.size(); EosResult eosResult = null; for (int i = 0; i < size; i++) { JSONObject jsonObject1 = actions.getJSONObject(i); // 当前交易序号 Object account_action_seq = jsonObject1.get("account_action_seq"); JSONObject action_trace = jsonObject1.getJSONObject("action_trace"); JSONObject act = action_trace.getJSONObject("act"); Object account = act.get("account"); if (!EOS_TOKEN.equals(account)) { continue; } eosResult = JSONObject.parseObject(act.getString("data"), EosResult.class); eosResult.setAccountActionSeq((Integer) account_action_seq); results.add(eosResult); } } } catch (Exception e) { e.printStackTrace(); } return results; } } src/main/java/com/xcong/excoin/modules/blackchain/service/Impl/BlockSeriveImpl.java
@@ -105,9 +105,7 @@ map.put("lable", uuid); break; case "XRP": JSONObject jSONObject = XrpService.createWallet(); address = (String) jSONObject.get("xAddress"); key = (String) jSONObject.get("secret"); address = "biyicteos123"; map.put("address", address); map.put("lable", uuid); break; 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,379 +60,22 @@ * 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"; // 十分钟查一次 每次100条 String result = HttpUtil.get(url); try { JSONObject json = JSONObject.parseObject(result); XrpTransResult res = json.toJavaObject(XrpTransResult.class); return res; }catch(Exception e) { e.printStackTrace(); } return null; } /** * XRP查询余额 * * @return */ public static double getBalance(String address) { 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=100&start="+startTime; // 十分钟查一次 每次100条 String result = HttpUtil.get(url); 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失败!"); JSONObject json = JSONObject.parseObject(result); XrpTransResult res = json.toJavaObject(XrpTransResult.class); return res; }catch(Exception e) { 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/controller/CoinController.java
@@ -146,9 +146,9 @@ */ @ApiOperation(value="获取代理资产佣金入账", notes="获取代理资产佣金入账") @ApiResponses({@ApiResponse( code = 200, message = "success", response = MemberAgentIntoInfoVo.class)}) @GetMapping(value="/getWalletAgentIntoRecords") public Result getWalletAgentIntoRecords() { return coinService.getWalletAgentIntoRecords(); @PostMapping(value="/getWalletAgentIntoRecords") public Result getWalletAgentIntoRecords(@RequestBody @Valid RecordsPageDto recordsPageDto) { return coinService.getWalletAgentIntoRecords(recordsPageDto); } /** src/main/java/com/xcong/excoin/modules/coin/dao/MemberAccountMoneyChangeDao.java
@@ -29,4 +29,7 @@ IPage<MemberAccountMoneyChange> selectWalletAgentRecordsInPage(Page<OrderCoinsDealEntity> page, @Param("record") MemberAccountMoneyChange memberAccountMoneyChange); IPage<MemberAccountMoneyChange> selectWalletAgentIntoRecordsByMemIdTypeSymbol(Page<OrderCoinsDealEntity> page, @Param("record")MemberAccountMoneyChange memberAccountMoneyChange); } src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java
@@ -10,4 +10,8 @@ public void updateBtc(); public void updateEos(); public void updateXrp(); } src/main/java/com/xcong/excoin/modules/coin/service/CoinService.java
@@ -29,7 +29,7 @@ public Result getWalletCoinBySymbol(String symbol); public Result getWalletAgentIntoRecords(); public Result getWalletAgentIntoRecords(@Valid RecordsPageDto recordsPageDto); public Result getWalletCoinRecords(@Valid RecordsPageDto recordsPageDto); src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java
@@ -5,9 +5,11 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.xcong.excoin.common.enumerates.CoinTypeEnum; import com.xcong.excoin.modules.blackchain.service.BtcService; import com.xcong.excoin.modules.blackchain.service.EthService; import com.xcong.excoin.modules.blackchain.service.UsdtService; import com.xcong.excoin.modules.blackchain.model.EosResult; 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; @@ -18,17 +20,23 @@ import com.xcong.excoin.modules.member.entity.MemberEntity; import com.xcong.excoin.modules.member.entity.MemberWalletCoinEntity; import com.xcong.excoin.utils.LogRecordUtils; import com.xcong.excoin.utils.RedisUtils; import com.xcong.excoin.utils.ThreadPoolUtils; import com.xcong.excoin.utils.dingtalk.DingTalkUtils; 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; import org.springframework.transaction.annotation.Transactional; 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; @@ -48,6 +56,13 @@ private MemberCoinChargeDao memberCoinChargeDao; @Resource private MemberWalletCoinDao memberWalletCoinDao; @Resource 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 @@ -250,6 +265,147 @@ } } @Override public void updateEos() { // 获取上次读取的序号 int pos= 0; //每次获取的条数 int offset = 10; String eosSeq = redisUtils.getString(EOS_SEQ_KEY); if(StringUtils.isNotBlank(eosSeq)){ pos = Integer.valueOf(eosSeq); } // 记录最大的seq int seq = pos; List<EosResult> actions = EosService.getActions(pos, offset); if(CollectionUtils.isNotEmpty(actions)){ for(EosResult eosResult:actions){ String to = eosResult.getTo(); Integer accountActionSeq = eosResult.getAccountActionSeq(); if(accountActionSeq>seq){ seq = accountActionSeq; } if(!EosService.ACCOUNT.equals(to)){ // 判断是否是收款 continue; } // 处理收款 String quantity = eosResult.getQuantity(); String memo = eosResult.getMemo(); if(StringUtils.isBlank(memo)){ // 没有标记的跳过 continue; } if(StringUtils.isNotBlank(quantity)){ // 转账额 String amountStr = quantity.split("")[0]; BigDecimal amount = new BigDecimal(amountStr); List<MemberCoinAddressEntity> memberCoinAddress = memberCoinAddressDao.selectAllBlockAddressBySymbolAndTag(CoinTypeEnum.EOS.name(), memo); if(CollectionUtils.isNotEmpty(memberCoinAddress)){ MemberCoinAddressEntity memberCoinAddressEntity = memberCoinAddress.get(0); // 用户ID Long memberId = memberCoinAddressEntity.getMemberId(); MemberWalletCoinEntity memberWalletCoinEntity = memberWalletCoinDao.selectWalletCoinBymIdAndCode(memberId, CoinTypeEnum.EOS.name()); if(memberCoinAddressEntity!=null){ memberWalletCoinDao.updateBlockBalance(memberWalletCoinEntity.getId(),amount,BigDecimal.ZERO,0); // 添加冲币记录 String orderNo = insertCoinCharge(EosService.ACCOUNT,memberId,amount,CoinTypeEnum.EOS.name(),memo,BigDecimal.ZERO); LogRecordUtils.insertMemberAccountMoneyChange(memberId, "转入", amount, CoinTypeEnum.EOS.name(), 1, 1); ThreadPoolUtils.sendDingTalk(5); MemberEntity member = memberDao.selectById(memberId); if (StrUtil.isNotBlank(member.getPhone())) { //String amountEos = amountStr + "EOS"; 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); } } } } } } // 最后更新seq 即下次查询的起始位置 在本次最大的基础上加一 if(seq>0 && seq>pos){ redisUtils.set(EOS_SEQ_KEY,seq+1); } } 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(); src/main/java/com/xcong/excoin/modules/coin/service/impl/CoinServiceImpl.java
@@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; import javax.annotation.Resource; import javax.validation.Valid; import com.xcong.excoin.modules.platform.entity.PlatformCnyUsdtExchangeEntity; import org.springframework.stereotype.Service; @@ -479,31 +480,34 @@ } @Override public Result getWalletAgentIntoRecords() { public Result getWalletAgentIntoRecords(RecordsPageDto recordsPageDto) { //获取用户ID Long memberId = LoginUserUtils.getAppLoginUser().getId(); List<MemberAccountMoneyChange> contractRecordList = memberAccountMoneyChangeDao.selectWalletAgentIntoRecordsByMemIdTypeSymbol(memberId); MemberAgentIntoInfoVo memberAgentIntoInfoVo = new MemberAgentIntoInfoVo(); Page<OrderCoinsDealEntity> page = new Page<>(recordsPageDto.getPageNum(), recordsPageDto.getPageSize()); MemberAccountMoneyChange memberAccountMoneyChange = new MemberAccountMoneyChange(); memberAccountMoneyChange.setMemberId(memberId); IPage<MemberAccountMoneyChange> list = memberAccountMoneyChangeDao.selectWalletAgentIntoRecordsByMemIdTypeSymbol(page, memberAccountMoneyChange); List<MemberAccountMoneyChange> contractRecordList = list.getRecords(); List<MemberAccountMoneyChangeInfoVo> arrayList = new ArrayList<>(); if(CollUtil.isNotEmpty(contractRecordList)) { if (ObjectUtil.isNotNull(contractRecordList)) { for (MemberAccountMoneyChange memberAccountMoneyChange : contractRecordList) { for (MemberAccountMoneyChange memberAccountMoneyChanges : contractRecordList) { MemberAccountMoneyChangeInfoVo memberAccountMoneyChangeInfoVo = new MemberAccountMoneyChangeInfoVo(); memberAccountMoneyChangeInfoVo.setAmount(memberAccountMoneyChange.getAmount()); memberAccountMoneyChangeInfoVo.setContent(memberAccountMoneyChange.getContent()); memberAccountMoneyChangeInfoVo.setStatus(memberAccountMoneyChange.getStatus()); memberAccountMoneyChangeInfoVo.setSymbol(memberAccountMoneyChange.getSymbol()); memberAccountMoneyChangeInfoVo.setType(memberAccountMoneyChange.getType()); memberAccountMoneyChangeInfoVo.setUpdateTime(memberAccountMoneyChange.getUpdateTime()); memberAccountMoneyChangeInfoVo.setAmount(memberAccountMoneyChanges.getAmount()); memberAccountMoneyChangeInfoVo.setContent(memberAccountMoneyChanges.getContent()); memberAccountMoneyChangeInfoVo.setStatus(memberAccountMoneyChanges.getStatus()); memberAccountMoneyChangeInfoVo.setSymbol(memberAccountMoneyChanges.getSymbol()); memberAccountMoneyChangeInfoVo.setType(memberAccountMoneyChanges.getType()); memberAccountMoneyChangeInfoVo.setUpdateTime(memberAccountMoneyChanges.getUpdateTime()); arrayList.add(memberAccountMoneyChangeInfoVo); } } } memberAgentIntoInfoVo.setMemberAccountMoneyChangeInfoVo(arrayList); return Result.ok(memberAgentIntoInfoVo); Page<MemberAccountMoneyChangeInfoVo> pageEntityToPageVo = new Page<>(); pageEntityToPageVo.setRecords(arrayList); return Result.ok(pageEntityToPageVo); } } src/main/java/com/xcong/excoin/modules/contract/service/impl/ContractHoldOrderServiceImpl.java
@@ -233,7 +233,7 @@ if (rewardRatio.compareTo(BigDecimal.ZERO) > -1) { rewardRatio = rewardRatio.multiply(BigDecimal.ONE.subtract(tradeSettingEntity.getProfitParam())); } else { rewardRatio = rewardRatio.multiply(BigDecimal.ONE.add(tradeSettingEntity.getProfitParam())); // rewardRatio = rewardRatio.multiply(BigDecimal.ONE.add(tradeSettingEntity.getProfitParam())); } } src/main/java/com/xcong/excoin/modules/contract/service/impl/OrderWebsocketServiceImpl.java
@@ -178,7 +178,7 @@ if (profitLossPrice.compareTo(BigDecimal.ZERO) > 0) { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.subtract(tradeSetting.getProfitParam())); } else { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); // profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); } } //回报率 @@ -268,7 +268,7 @@ if (profitLossPrice.compareTo(BigDecimal.ZERO) > 0) { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.subtract(tradeSetting.getProfitParam())); } else { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); // profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); } } //回报率 @@ -278,7 +278,7 @@ contractOrderEntity.setClosingFeeAmount(order.getOpeningFeeAmount()); contractOrderEntity.setClosingPrice(closePrice); contractOrderEntity.setClosingType(7); contractOrderEntity.setOrderType(ContractOrderEntity.ORDER_TYPE_CLOSE_MORE); contractOrderEntity.setOrderType(ContractOrderEntity.ORDER_TYPE_CLOSE_LESS); BigDecimal totalReturn = BigDecimal.ZERO; contractOrderService.save(contractOrderEntity); @@ -360,7 +360,7 @@ if (profitLossPrice.compareTo(BigDecimal.ZERO) > 0) { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.subtract(tradeSetting.getProfitParam())); } else { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); // profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); } } //回报率 @@ -451,7 +451,7 @@ if (profitLossPrice.compareTo(BigDecimal.ZERO) > 0) { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.subtract(tradeSetting.getProfitParam())); } else { profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); // profitLossPrice = profitLossPrice.multiply(BigDecimal.ONE.add(tradeSetting.getProfitParam())); } } //回报率 src/main/java/com/xcong/excoin/modules/contract/service/impl/RabbitOrderServiceImpl.java
@@ -95,14 +95,14 @@ Integer closingType = null; // 开多 if (ContractHoldOrderEntity.OPENING_TYPE_MORE == holdOrderEntity.getOpeningType()) { newPrice = newPrice.multiply(BigDecimal.ONE.subtract(memberEntity.getSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); newPrice = newPrice.multiply(BigDecimal.ONE.subtract(memberEntity.getClosingSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); // (最新价-开仓价)*规格*张数 profitOrLoss = newPrice.subtract(holdOrderEntity.getOpeningPrice()).multiply(lotNumber).multiply(new BigDecimal(holdOrderEntity.getSymbolCnt())); orderType = ContractOrderEntity.ORDER_TYPE_CLOSE_MORE; closingType = OrderClosingTypeEnum.CLOSE_MORE.getValue(); // 开空 } else { newPrice = newPrice.multiply(BigDecimal.ONE.add(memberEntity.getSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); newPrice = newPrice.multiply(BigDecimal.ONE.add(memberEntity.getClosingSpread().divide(BigDecimal.valueOf(10000), 4, BigDecimal.ROUND_DOWN))); // (开仓价-最新价)*规格*张数 profitOrLoss = holdOrderEntity.getOpeningPrice().subtract(newPrice).multiply(lotNumber).multiply(new BigDecimal(holdOrderEntity.getSymbolCnt())); orderType = ContractOrderEntity.ORDER_TYPE_CLOSE_LESS; src/main/java/com/xcong/excoin/modules/member/entity/MemberEntity.java
@@ -154,4 +154,9 @@ * 滑点 */ private BigDecimal spread; /** * 平仓点数 */ private BigDecimal closingSpread; } src/main/java/com/xcong/excoin/modules/member/service/impl/MemberServiceImpl.java
@@ -152,9 +152,10 @@ member.setAccountType(MemberEntity.ACCOUNT_TYPE_NORMAL); member.setAgentLevel(MemberEntity.ACCOUNT_AGENT_LEVEL); member.setCertifyStatus(MemberEntity.CERTIFY_STATUS_UN_SUBMIT); member.setIsForce(0); member.setIsForce(1); member.setIsProfit(0); member.setSpread(BigDecimal.ZERO); member.setSpread(BigDecimal.ONE); member.setClosingSpread(BigDecimal.ONE); memberDao.insert(member); String inviteId = ShareCodeUtil.toSerialCode(member.getId()); src/main/java/com/xcong/excoin/quartz/job/BlockCoinUpdateJob.java
@@ -50,4 +50,14 @@ blockCoinService.updateBtc(); } @Scheduled(cron = "0 4/20 * * * ? ") public void eosUpdate() { blockCoinService.updateEos(); } @Scheduled(cron = "0 6/20 * * * ? ") public void xrpUpdate() { blockCoinService.updateXrp(); } } src/main/resources/mapper/member/MemberAccountMoneyChangeDao.xml
@@ -14,10 +14,6 @@ select * from member_account_money_change where type = 3 and member_id = #{memberId} order by id desc </select> <select id="selectWalletAgentIntoRecordsByMemIdTypeSymbol" resultType="com.xcong.excoin.modules.coin.entity.MemberAccountMoneyChange"> select * from member_account_money_change where type = 3 and content like '%佣金到账%' and member_id = #{memberId} order by id desc </select> <select id="selectWalletCoinRecordsInPage" resultType="com.xcong.excoin.modules.coin.entity.MemberAccountMoneyChange"> select * from member_account_money_change <if test="record != null"> @@ -54,5 +50,18 @@ </if> order by id desc </select> <select id="selectWalletAgentIntoRecordsByMemIdTypeSymbol" resultType="com.xcong.excoin.modules.coin.entity.MemberAccountMoneyChange"> select * from member_account_money_change <if test="record != null"> <where> type = 3 and content like '%佣金到账%' <if test="record.memberId != null" > and member_id=#{record.memberId} </if> </where> </if> order by id desc </select> </mapper> src/test/java/com/xcong/excoin/RedisTest.java
@@ -1,11 +1,13 @@ package com.xcong.excoin; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.member.dao.MemberDao; import com.xcong.excoin.modules.member.entity.MemberEntity; import com.xcong.excoin.utils.RedisUtils; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import javax.annotation.Resource; @@ -26,7 +28,8 @@ @Test public void redisResetTest() { MemberEntity member = memberDao.selectById(1L); redisUtils.set("app_5b6298754d5b4aac985d9d7d42a2db9d", member); member.setPassword(new BCryptPasswordEncoder().encode(member.getPassword())); redisUtils.set("app_d95747766852410c80ed81ba9e72d15d", JSONObject.toJSONString(member), 36000); } }