Search in sources :

Example 6 with Currency

use of com.whoiszxl.entity.Currency in project shopzz by whoiszxl.

the class EthScanTask method scanOrder.

/**
 * 扫描链上的交易是否和数据库中的支付单是否匹配,如果匹配则修改对应状态。
 * 在最近的300个区块的出块时间一般平均为15秒。
 * 定时任务使用10秒间隔(10 * 1000)。
 * https://txstreet.com/
 */
@Scheduled(fixedDelay = 60 * 1000)
public void scanOrder() {
    // 1. 获取当前货币的配置信息
    Currency ethInfo = currencyService.getCurrencyByName(currencyName);
    AssertUtils.isNotNull(ethInfo, "数据库未配置货币信息:" + currencyName);
    // 2. 获取到当前与网络区块高度
    Long networkBlockHeight = ethereumService.getBlockchainHeight();
    Height heightObj = heightService.getHeightByCurrencyName(currencyName);
    if (heightObj == null) {
        Height height = new Height();
        height.setCurrencyId(ethInfo.getId());
        height.setCurrencyName(ethInfo.getCurrencyName());
        height.setCurrentHeight(networkBlockHeight);
        heightService.save(height);
        return;
    }
    Long currentHeight = heightObj.getCurrentHeight();
    // 3. 相隔1个区块不进行扫描
    if (networkBlockHeight - currentHeight <= 1) {
        return;
    }
    // 4. 遍历扫描区块中的交易
    for (Long i = currentHeight + 1; i <= networkBlockHeight; i++) {
        // 5. 通过区块高度拿到区块,再从区块中拿到交易集合
        EthBlock.Block block = ethereumService.getBlockByNumber(i.longValue());
        List<EthBlock.TransactionResult> transactions = block.getTransactions();
        // 6. 遍历交易集合
        for (EthBlock.TransactionResult transactionResult : transactions) {
            // 7. 拿到交易集合中的Transaction对象
            EthBlock.TransactionObject transactionObject = (EthBlock.TransactionObject) transactionResult;
            Transaction transaction = transactionObject.get();
            // 8. 校验交易有效性
            if (StringUtils.isEmpty(transaction.getTo())) {
                log.info("交易{}不存在toAddress", transaction.getHash());
                continue;
            }
            // 9. 判断支付单是否存在,判断链上充值金额是否足够支付订单
            BigDecimal amount = Convert.fromWei(transaction.getValue().toString(), Convert.Unit.ETHER);
            PayInfoDc payInfoDc = dcPayInfoService.getRechargeByAddressAndCurrencyNameAndUpchainStatus(transaction.getTo(), currencyName, UpchainStatusEnum.NOT_UPCHAIN.getCode());
            if (payInfoDc == null) {
                // log.info("{} 地址不在库中:{}", currencyName, transaction.getTo());
                continue;
            }
            if (amount.compareTo(payInfoDc.getTotalAmount()) < 0) {
                log.info("链上充值金额小于订单金额, 订单金额为:{}, 链上充值金额为:{}", payInfoDc.getTotalAmount().toPlainString(), amount.toPlainString());
                continue;
            }
            // 10. 填充基础信息
            payInfoDc.setFromAddress(transaction.getFrom());
            payInfoDc.setTxHash(transaction.getHash());
            payInfoDc.setCurrentConfirm(transaction.getBlockNumber().subtract(BigInteger.valueOf(i)).longValue());
            payInfoDc.setHeight(transaction.getBlockNumber().longValue());
            payInfoDc.setUpchainAt(new Date(block.getTimestamp().longValue()));
            // 11. 判断是否上链确认成功
            if (i - block.getNumber().intValue() >= ethInfo.getConfirms()) {
                payInfoDc.setUpchainStatus(UpchainStatusEnum.SUCCESS.getCode());
                payInfoDc.setUpchainSuccessAt(new Date(block.getTimestamp().longValue()));
            } else {
                payInfoDc.setUpchainStatus(UpchainStatusEnum.WAITING_CONFIRM.getCode());
            }
            dcPayInfoService.updateById(payInfoDc);
        }
    }
    // 12. 更新区块高度
    heightObj.setCurrentHeight(networkBlockHeight);
    heightService.updateById(heightObj);
}
Also used : PayInfoDc(com.whoiszxl.entity.PayInfoDc) EthBlock(org.web3j.protocol.core.methods.response.EthBlock) BigDecimal(java.math.BigDecimal) Date(java.util.Date) Transaction(org.web3j.protocol.core.methods.response.Transaction) Currency(com.whoiszxl.entity.Currency) Height(com.whoiszxl.entity.Height) Scheduled(org.springframework.scheduling.annotation.Scheduled)

Example 7 with Currency

use of com.whoiszxl.entity.Currency in project shopzz by whoiszxl.

the class EthScanTask method confirmTx.

/**
 * 确认交易,将数据库中状态为待确认的支付单再次去链上查询是否确认数超过了配置确认数。
 * 在最近的300个区块的出块时间一般平均为15秒。
 * 定时任务使用15秒间隔(15 * 1000)。
 * https://txstreet.com/
 */
@Scheduled(fixedDelay = 10 * 1000)
public void confirmTx() {
    // 0. 获取当前货币的配置信息
    Currency ethInfo = currencyService.getCurrencyByName(currencyName);
    AssertUtils.isNotNull(ethInfo, "数据库未配置货币信息:" + currencyName);
    // 1. 获取当前网络的区块高度
    Long currentHeight = ethereumService.getBlockchainHeight();
    // 2. 查询到所有待确认的支付单
    List<PayInfoDc> waitConfirmRecharge = dcPayInfoService.getWaitConfirmPayInfo(currencyName);
    if (ObjectUtils.isEmpty(waitConfirmRecharge)) {
        log.info("不存在待确认的支付单");
        return;
    }
    // 3. 遍历库中交易进行判断是否成功
    List<Long> paySuccessOrderIds = new ArrayList<>();
    for (PayInfoDc payInfoDc : waitConfirmRecharge) {
        Transaction transaction = ethereumService.getTransactionByHash(payInfoDc.getTxHash());
        // 如果链上交易确认数大于等于配置的确认数,则更新支付单为成功并更新上链成功时间,否则只更新当前确认数。
        if (currentHeight - transaction.getBlockNumber().longValue() >= ethInfo.getConfirms()) {
            payInfoDc.setUpchainStatus(UpchainStatusEnum.SUCCESS.getCode());
            payInfoDc.setUpchainSuccessAt(new Date());
        }
        payInfoDc.setCurrentConfirm(currentHeight - transaction.getBlockNumber().longValue());
        dcPayInfoService.updateById(payInfoDc);
        paySuccessOrderIds.add(payInfoDc.getOrderId());
    }
    if (ObjectUtils.isNotEmpty(paySuccessOrderIds)) {
        // 成功了发送消息去更新oms_order记录为支付成功
        ResponseResult<Boolean> responseResult = orderFeignClient.notifyDcPaySuccess(paySuccessOrderIds);
        if (!responseResult.isOk()) {
            log.error("支付成功了,但是更新订单未成功", responseResult.getMessage());
        }
    }
}
Also used : PayInfoDc(com.whoiszxl.entity.PayInfoDc) Transaction(org.web3j.protocol.core.methods.response.Transaction) Currency(com.whoiszxl.entity.Currency) ArrayList(java.util.ArrayList) Date(java.util.Date) Scheduled(org.springframework.scheduling.annotation.Scheduled)

Example 8 with Currency

use of com.whoiszxl.entity.Currency in project shopzz by whoiszxl.

the class BtcFeignClientImpl method giveAddress.

@Override
@Transactional
@PostMapping("/createRecharge/{orderId}/{amount}")
public ResponseResult<RechargeResponse> giveAddress(String orderId, String amount) {
    // 1. 获取货币信息
    Currency btcInfo = currencyService.getCurrencyByName(currencyName);
    AssertUtils.isNotNull(btcInfo, "数据库未配置货币信息:" + currencyName);
    // 2. 生成bitcoin地址
    String newAddress = bitcoinClient.getNewAddress(orderId);
    return ResponseResult.buildSuccess(new RechargeResponse(btcInfo.getId(), newAddress, amount));
}
Also used : RechargeResponse(com.whoiszxl.entity.response.RechargeResponse) Currency(com.whoiszxl.entity.Currency) PostMapping(org.springframework.web.bind.annotation.PostMapping) Transactional(org.springframework.transaction.annotation.Transactional)

Example 9 with Currency

use of com.whoiszxl.entity.Currency in project shopzz by whoiszxl.

the class BtcScanTask method confirmTx.

/**
 * 确认交易,将数据库中状态为待确认的充值单再次去链上查询是否确认数超过了配置确认数。
 * 在最近的250个区块的出块时间一般平均为10分钟,所以定时任务运行的时间可以稍微拉长一些,降低服务器与节点的压力。
 * 测试链使用5秒间隔,主网则使用10分钟间隔(600 * 1000)。
 * https://txstreet.com/
 */
@Scheduled(fixedDelay = 5 * 1000)
public void confirmTx() {
    // 0. 获取当前货币的配置信息
    Currency btcInfo = currencyService.getCurrencyByName(currencyName);
    AssertUtils.isNotNull(btcInfo, "数据库未配置货币信息:" + currencyName);
    // 1. 查询到所有待确认的支付单
    List<PayInfoDc> waitConfirmRecharge = dcPayInfoService.getWaitConfirmPayInfo(currencyName);
    if (ObjectUtils.isEmpty(waitConfirmRecharge)) {
        log.info("不存在待确认的支付单");
        return;
    }
    // 3. 遍历库中交易进行判断是否成功
    List<Long> paySuccessOrderIds = new ArrayList<>();
    for (PayInfoDc payInfoDc : waitConfirmRecharge) {
        BitcoindRpcClient.RawTransaction transaction = bitcoinClient.getRawTransaction(payInfoDc.getTxHash());
        // 如果链上交易确认数大于等于配置的确认数,则更新充值单为成功并更新上链成功时间,否则只更新当前确认数。
        if (transaction.confirmations() >= btcInfo.getConfirms()) {
            payInfoDc.setUpchainStatus(UpchainStatusEnum.SUCCESS.getCode());
            payInfoDc.setUpchainSuccessAt(new Date());
        }
        payInfoDc.setCurrentConfirm(transaction.confirmations().longValue());
        payInfoDc.setUpdatedAt(new Date());
        dcPayInfoService.updateById(payInfoDc);
        paySuccessOrderIds.add(payInfoDc.getOrderId());
    }
    if (ObjectUtils.isNotEmpty(paySuccessOrderIds)) {
        // 成功了发送消息去更新oms_order记录为支付成功
        ResponseResult<Boolean> responseResult = orderFeignClient.notifyDcPaySuccess(paySuccessOrderIds);
        if (!responseResult.isOk()) {
            log.error("支付成功了,但是更新订单未成功", responseResult.getMessage());
        }
    }
}
Also used : PayInfoDc(com.whoiszxl.entity.PayInfoDc) Currency(com.whoiszxl.entity.Currency) ArrayList(java.util.ArrayList) BitcoindRpcClient(wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient) Date(java.util.Date) Scheduled(org.springframework.scheduling.annotation.Scheduled)

Example 10 with Currency

use of com.whoiszxl.entity.Currency in project shopzz by whoiszxl.

the class ZXLFeignClientImpl method giveAddress.

@Override
@Transactional
public ResponseResult<RechargeResponse> giveAddress(String orderId, String amount) {
    // 1. 获取货币信息
    Currency ethInfo = currencyService.getCurrencyByName(currencyName);
    AssertUtils.isNotNull(ethInfo, "数据库未配置货币信息:" + currencyName);
    // 2. 通过keystore的方式生成一个以太坊地址
    EthereumAddress ethereumAddress = ethereumService.createAddressByFile();
    String qrCodeData = getQrCodeData(amount, ethereumAddress.getAddress());
    // 3. 保存keystore文件与地址的对应关系
    CurrencyAccount account = new CurrencyAccount();
    account.setAddress(ethereumAddress.getAddress());
    account.setCurrencyId(ethInfo.getId());
    account.setCurrencyName(ethInfo.getCurrencyName());
    account.setKeystoreName(ethereumAddress.getKeystoreName());
    account.setMnemonic(ethereumAddress.getMnemonic());
    currencyAccountService.save(account);
    return ResponseResult.buildSuccess(new RechargeResponse(ethInfo.getId(), ethereumAddress.getAddress(), qrCodeData));
}
Also used : EthereumAddress(com.whoiszxl.common.EthereumAddress) CurrencyAccount(com.whoiszxl.entity.CurrencyAccount) RechargeResponse(com.whoiszxl.entity.response.RechargeResponse) Currency(com.whoiszxl.entity.Currency) Transactional(org.springframework.transaction.annotation.Transactional)

Aggregations

Currency (com.whoiszxl.entity.Currency)10 PayInfoDc (com.whoiszxl.entity.PayInfoDc)6 Scheduled (org.springframework.scheduling.annotation.Scheduled)6 RechargeResponse (com.whoiszxl.entity.response.RechargeResponse)4 Date (java.util.Date)4 Transactional (org.springframework.transaction.annotation.Transactional)4 Transaction (org.web3j.protocol.core.methods.response.Transaction)4 EthereumAddress (com.whoiszxl.common.EthereumAddress)3 CurrencyAccount (com.whoiszxl.entity.CurrencyAccount)3 Height (com.whoiszxl.entity.Height)3 BigDecimal (java.math.BigDecimal)2 ArrayList (java.util.ArrayList)2 PostMapping (org.springframework.web.bind.annotation.PostMapping)2 EthBlock (org.web3j.protocol.core.methods.response.EthBlock)2 BitcoindRpcClient (wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient)2 TypeReference (org.web3j.abi.TypeReference)1 Function (org.web3j.abi.datatypes.Function)1 Type (org.web3j.abi.datatypes.Type)1 TransactionReceipt (org.web3j.protocol.core.methods.response.TransactionReceipt)1