以太坊合约
//根据txId查询交易记录是否存在 存在:提现 不存在:充值 /* 提现逻辑 * 1、判断区块交易中为状态 * 2、成功 更新交易状态 * 3、不成功 (1)更新交易状态 (2)返还账号金额 */ /* 充值逻辑 * 1、更具coinid和to查询 判断 是系统用户充值的 && 交易状态成功 * 2、添加充值记录 * 3、给用户金额充值 返回金额 更新钱包 * 4、首次充值奖励 */ @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void listBlock(Web3j web3j) throws IOException, Exception, BCException { Long tokenBlockHeight = jobUtils.getETHBlockHeight(); Long latestBlockNumber = web3j.ethBlockNumber().send().getBlockNumber().longValue(); logger.info("最新区块高度:{},扫描区块高度:{}",latestBlockNumber, tokenBlockHeight); if(latestBlockNumber<tokenBlockHeight) { tokenBlockHeight = latestBlockNumber; try { logger.warn("扫描区块高度大于当前最新区块高度"); Thread.sleep(10000L); } catch (InterruptedException e) { e.printStackTrace(); } } logger.info("当前扫描区块高度:{}", tokenBlockHeight); EthBlock block = null; if(tokenBlockHeight>0) { block = web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(BigInteger.valueOf(tokenBlockHeight)), true).send(); } if(block!=null){ List<TransactionResult> list=block.getBlock().getTransactions(); for(TransactionResult result : list){ TransactionObject object=(TransactionObject) result; if(object==null) { logger.warn("当前扫描区块object为空 休眠3秒"); Thread.sleep(3000); return; } List<FVirtualCapitalOperationDTO> fvirtualcaptualoperations = this.fVirtualCapitalOperationMapper.selectByTxid(object.getHash()); if (fvirtualcaptualoperations.size() > 0) { //交易记录列表中有该笔交易,说明是提现 //logger.info(object.getHash() +" 是否存在该笔交易: " + (fvirtualcaptualoperations.size() > 0)); FVirtualCapitalOperationDTO opDto = fvirtualcaptualoperations.get(0); //logger.info("交易类型是否为提现:" +(opDto.getFtype()==VirtualCapitalOperationTypeEnum.COIN_OUT.getCode()?"提现":"充值")); if(opDto.getFtype()==VirtualCapitalOperationTypeEnum.COIN_OUT.getCode()) { //交易类型为 提现 //查询该笔交易状态 boolean txStatus = false; EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(object.getHash()).send(); if(receipt.getTransactionReceipt().isPresent()){ TransactionReceipt re=receipt.getTransactionReceipt().get(); txStatus = HexToBoolean(re.getStatus()); } //txStatus = true; //logger.info("区块交易中为状态成功:" +txStatus); //区块交易中为状态成功 if(txStatus) { //更新交易状态 opDto.setFstatus(VirtualCapitalOperationOutStatusEnum.OperationSuccess); opDto.setFupdatetime(Utils.getTimestamp()); opDto.setFconfirmations(1); opDto.setFblocknumber(block.getBlock().getNumber().intValue()); if (this.fVirtualCapitalOperationMapper.updateByPrimaryKey(opDto) <= 0) { logger.warn("提现交易更新为(成功状态)异常 hash:{}", object.getHash()); throw new Exception(); } //logger.info("完成更新交易状态为成功"); } else { //区块交易中为状态失败 //1、更新交易状态 opDto.setFstatus(VirtualCapitalOperationOutStatusEnum.OperationFailed); opDto.setFupdatetime(Utils.getTimestamp()); opDto.setFconfirmations(1); opDto.setFblocknumber(block.getBlock().getNumber().intValue()); if (this.fVirtualCapitalOperationMapper.updateByPrimaryKey(opDto) <= 0) { logger.warn("提现交易更新为(失败状态)异常 hash:{}", object.getHash()); throw new Exception(); } //2、返还金额 更新钱包 /*UserCoinWallet userCoinWallet = userCoinWalletMapper.selectLock(opDto.getFuid(), opDto.getFcoinid()); if (userCoinWallet == null) { continue; } userCoinWallet.setTotal(MathUtils.add(userCoinWallet.getTotal(), opDto.getFamount())); if(this.userCoinWalletMapper.update(userCoinWallet)<=0) { throw new Exception(); } logger.info("完成返还金额");*/ } } else { continue; } } else {//交易记录列表中有该笔交易,说明是充值 //================================= List<SystemCoinType> coinTypes = jobUtils.getCoinTypeList(); if (coinTypes != null && coinTypes.size()>0) { for (SystemCoinType coinType : coinTypes) { if (coinType.getCoinType().equals(SystemCoinSortEnum.ETH.getCode()) || coinType.getCoinType().equals(SystemCoinSortEnum.ETC.getCode())) { //---------------------------- if(object.getTo()==null) { //如果to为空的话,说明该条交易是建合约交易 continue; } BigDecimal tranAmount = new BigDecimal(this.ETHBalanceHexToStr(object.getValue(), 18)); String to = object.getTo().trim(); String input = object.get().getInput(); //判断如果是代币,那么金额在input数据中 if(tranAmount.compareTo(BigDecimal.ZERO)==0) { //是合约代币交易, 判断当前合约代币名称是否与当前币种名称一致, 不一致则continue if(!coinType.getContractAccount().equals(object.getTo().trim())) { continue; } if(input!=null && input.length()>136){ String tranMethodId=input.substring(0,10); if("0xa9059cbb".equals(tranMethodId)){ // transfer param: to - balance 事件ID,固定的,该事件为转账ID List<Type> values=FunctionReturnDecoder.decode(input.substring(input.length()-64,input.length()), org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}))); if(!values.isEmpty()){ String value=values.get(0).getValue().toString(); tranAmount = new BigDecimal(ETHBalanceToStr(value, coinType.getContractWei())); } String toAddress=input.substring(10,74); List<Type> addressType = FunctionReturnDecoder.decode(toAddress, org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}))); if(!addressType.isEmpty()){ to = addressType.get(0).getValue().toString(); } }else if("0x23b872dd".equals(tranMethodId)) { //transferFrom param:from - to - balance List<Type> values=FunctionReturnDecoder.decode(input.substring(input.length()-64,input.length()), org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}))); if(!values.isEmpty()){ String value=values.get(0).getValue().toString(); tranAmount = new BigDecimal(ETHBalanceToStr(value, coinType.getContractWei())); } String toAddress=input.substring(74,138); List<Type> addressType = FunctionReturnDecoder.decode(toAddress, org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}))); if(!addressType.isEmpty()){ to = addressType.get(0).getValue().toString(); } } else { logger.info("非转账交易 hash:{}", object.getHash()); break; } } } //交易记录列表中有该笔交易,说明是充值 int coinid = coinType.getId(); FUserVirtualAddressDTO vaDto = fUserVirtualAddressMapper.selectByCoinAndAddress(16, to); if(vaDto!=null) { //判断 是系统用户充值的 && 交易状态成功 //logger.info(coinid +" : " + object.getTo() + "用户地址中是存在:" +(vaDto!=null)); //查询该笔交易状态 boolean txStatus = false; EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(object.getHash()).send(); if(receipt.getTransactionReceipt().isPresent()){ TransactionReceipt re=receipt.getTransactionReceipt().get(); txStatus = HexToBoolean(re.getStatus()); } //logger.info("区块交易中为状态成功:" +txStatus); //txStatus = true; if(txStatus) { //1、添加充值记录 FVirtualCapitalOperationDTO fvirtualcaptualoperation = new FVirtualCapitalOperationDTO(); fvirtualcaptualoperation.setFuid(vaDto.getFuid()); fvirtualcaptualoperation.setFamount(tranAmount); fvirtualcaptualoperation.setFfees(BigDecimal.ZERO); fvirtualcaptualoperation.setFcoinid(coinid); fvirtualcaptualoperation.setFtype(VirtualCapitalOperationTypeEnum.COIN_IN.getCode()); fvirtualcaptualoperation.setFstatus(VirtualCapitalOperationInStatusEnum.SUCCESS); fvirtualcaptualoperation.setFhasowner(true); fvirtualcaptualoperation.setFbtcfees(BigDecimal.ZERO); fvirtualcaptualoperation.setFblocknumber(block.getBlock().getNumber().intValue()); fvirtualcaptualoperation.setFconfirmations(1); fvirtualcaptualoperation.setFrechargeaddress(to); fvirtualcaptualoperation.setFcreatetime(Utils.getTimestamp()); fvirtualcaptualoperation.setFupdatetime(Utils.getTimestamp()); fvirtualcaptualoperation.setVersion(0); fvirtualcaptualoperation.setFsource(DataSourceEnum.WEB.getCode()); fvirtualcaptualoperation.setFuniquenumber(object.getHash()); if(this.fVirtualCapitalOperationMapper.insert(fvirtualcaptualoperation)<=0) { logger.warn("充值交易插入异常 hash:{}", object.getHash()); throw new Exception(); } //2、给用户金额充值 返回金额 更新钱包 UserCoinWallet userCoinWallet = userCoinWalletMapper.selectLock(fvirtualcaptualoperation.getFuid(), fvirtualcaptualoperation.getFcoinid()); if (userCoinWallet == null) { logger.warn("获取用户钱包对象失败,hash:{}, uid:{}, coinid:{}", object.getHash(), fvirtualcaptualoperation.getFuid(), fvirtualcaptualoperation.getFcoinid()); continue; } userCoinWallet.setTotal(MathUtils.add(userCoinWallet.getTotal(), fvirtualcaptualoperation.getFamount())); if(this.userCoinWalletMapper.update(userCoinWallet)<=0) { logger.warn("更新资产数据失败,hash:{}, uid:{}, coinid:{}, amount:{}", object.getHash(), fvirtualcaptualoperation.getFuid(), fvirtualcaptualoperation.getFcoinid(), fvirtualcaptualoperation.getFamount()); throw new Exception(); } BigDecimal last = jobUtils.getLastPrice(fvirtualcaptualoperation.getFcoinid()); BigDecimal amount = MathUtils.mul(fvirtualcaptualoperation.getFamount(), last); scoreHelper.SendUserScore(fvirtualcaptualoperation.getFuid(), amount, ScoreTypeEnum.RECHARGE.getCode() , "充值" + coinType.getShortName() + ":" + fvirtualcaptualoperation.getFamount()); //首次充值奖励 boolean isFirstRecharge = isFirstCharge(fvirtualcaptualoperation.getFuid()); if(isFirstRecharge) { scoreHelper.SendUserScore(fvirtualcaptualoperation.getFuid(), BigDecimal.ZERO, ScoreTypeEnum.FIRSTCHARGE.getCode(), ScoreTypeEnum.FIRSTCHARGE.getValue().toString()); } mqSend.SendUserAction(fvirtualcaptualoperation.getFagentid(), fvirtualcaptualoperation.getFuid(), LogUserActionEnum.COIN_RECHARGE, fvirtualcaptualoperation.getFcoinid(), 0, fvirtualcaptualoperation.getFamount()); // 风控短信 if (fvirtualcaptualoperation.getFamount().compareTo(coinType.getRiskNum()) >= 0) { String riskphone = jobUtils.getSystemArgs(ArgsConstant.RISKPHONE); String[] riskphones = riskphone.split("#"); if (riskphones.length > 0) { FUser fuser = userMapper.selectByPrimaryKey(fvirtualcaptualoperation.getFuid()); for (String string : riskphones) { try { validateHelper.smsRiskManage(fuser.getFloginname(), string, PlatformEnum.BC.getCode(), BusinessTypeEnum.SMS_RISKMANAGE.getCode(), "充值", fvirtualcaptualoperation.getFamount(), coinType.getName()); } catch (Exception e) { logger.error("updateCoinCome riskphones err"); e.printStackTrace(); } } } } logger.info("完成添加充值记录 hash:{}", object.getHash()); } break; } //---------------------------- } } } //================================= } } tokenBlockHeight = tokenBlockHeight + 1; } else { logger.info("block is null"); } //System.out.println("===============tokenBlockHeight: " + tokenBlockHeight); jobUtils.setETHBlockHeight(tokenBlockHeight); try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } }