wallet tron transactions
This commit is contained in:
228
app/Service/Coin/Tron/UsdtTrx20Service.php
Normal file
228
app/Service/Coin/Tron/UsdtTrx20Service.php
Normal file
@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\Coin\Tron;
|
||||
|
||||
use App\Bean\Model\Wallet\Wallet\WalletAddressTransactionBean;
|
||||
use App\Bean\Queue\Wallet\QueueEventBean;
|
||||
use App\Bean\Queue\Wallet\QueueWalletBlockBean;
|
||||
use App\Bean\Queue\Wallet\QueueWalletBlockTransactionBean;
|
||||
use App\Bean\Queue\Wallet\QueueWalletPlatformTransactionBean;
|
||||
use App\Bean\Sdk\Wallet\Tron\EventBean;
|
||||
use App\Cache\Key\TronKeyCache;
|
||||
use App\Cache\Set\TronWalletAddressSetCache;
|
||||
use App\Exceptions\QueueException;
|
||||
use App\Jobs\Wallet\WalletAddressTransactionQueue;
|
||||
use App\Jobs\Wallet\WalletBlockQueue;
|
||||
use App\Jobs\Wallet\WalletBlockTransactionQueue;
|
||||
use App\Jobs\Wallet\WalletPlatformTransactionQueue;
|
||||
use App\Models\Wallet\Tron\WalletTronBlockModel;
|
||||
use App\Models\Wallet\Wallet\WalletAddressModel;
|
||||
use App\Models\Wallet\Wallet\WalletAddressTransactionModel;
|
||||
use App\Models\Wallet\Wallet\WalletCurrencyModel;
|
||||
use App\Tools\Logs;
|
||||
use Sdk\Wallet\UsdtTrc20;
|
||||
|
||||
class UsdtTrx20Service
|
||||
{
|
||||
protected UsdtTrc20 $usdtTrc20Sdk;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->usdtTrc20Sdk = new UsdtTrc20();
|
||||
}
|
||||
|
||||
function getHandle(): \Sdk\Wallet\Trc20Sdk
|
||||
{
|
||||
return $this->usdtTrc20Sdk->getHandler();
|
||||
}
|
||||
|
||||
//定时请求当前区块比对redis中当前区块,差值存入队列
|
||||
function checkNowBlock(): void
|
||||
{
|
||||
$oNowBlockBean = $this->getHandle()->getNowBlockNumber();
|
||||
//查询redis中当前区块
|
||||
$oTronKeyCache = new TronKeyCache();
|
||||
$sLocalNowBlock = $oTronKeyCache->getNowBlock();
|
||||
if (empty($sLocalNowBlock)) { //不存在就从数据库中取
|
||||
$oWalletTronBlockModel = new WalletTronBlockModel();
|
||||
$sLocalNowBlock = $oWalletTronBlockModel->getLastBlockNumber();
|
||||
if (!empty($sLocalNowBlock)) $oTronKeyCache->setNowBlock($sLocalNowBlock);
|
||||
}
|
||||
|
||||
$oWalletTronBlockModel = new WalletTronBlockModel();
|
||||
//如果都不存在,就直接投递到队列
|
||||
if (empty($sLocalNowBlock)) {
|
||||
$res = $oWalletTronBlockModel->insertByBlockNum($oNowBlockBean->getBlockNumber());
|
||||
if (!$res) return;
|
||||
$oQueueWalletBlockBean = new QueueWalletBlockBean();
|
||||
$oQueueWalletBlockBean->setId($res->id);
|
||||
$oQueueWalletBlockBean->setBlockNumber($oNowBlockBean->getBlockNumber());
|
||||
WalletBlockQueue::putToQueue($oQueueWalletBlockBean);
|
||||
return;
|
||||
}
|
||||
|
||||
//如果相等获取大于,就不处理
|
||||
if ($sLocalNowBlock >= $oNowBlockBean->getBlockNumber()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//如果不相等,获取差值一个个投递到队列
|
||||
for ($i = $sLocalNowBlock + 1; $i <= $oNowBlockBean->getBlockNumber(); $i++) {
|
||||
$res = $oWalletTronBlockModel->insertByBlockNum($i);
|
||||
if (!$res) continue;
|
||||
$oQueueWalletBlockBean = new QueueWalletBlockBean();
|
||||
$oQueueWalletBlockBean->setId($res->id);
|
||||
$oQueueWalletBlockBean->setBlockNumber($i);
|
||||
WalletBlockQueue::putToQueue($oQueueWalletBlockBean);
|
||||
}
|
||||
}
|
||||
|
||||
//监听处理区块
|
||||
public function tronBlockConsumer(QueueWalletBlockBean $oQueueWalletBlockBean): void
|
||||
{
|
||||
$oWalletTronBlockModel = new WalletTronBlockModel();
|
||||
$oResModel = $oWalletTronBlockModel->findItem($oQueueWalletBlockBean->getId());
|
||||
if (!$oResModel) throw new QueueException('区块不存在');
|
||||
if ($oResModel->status != WalletTronBlockModel::STATUS_WAIT) return;
|
||||
$oResModel->status = WalletTronBlockModel::STATUS_PROCESS;
|
||||
$oResModel->save();
|
||||
|
||||
$blockNumber = $oQueueWalletBlockBean->getBlockNumber();
|
||||
$fingerprint = null;
|
||||
|
||||
try {
|
||||
//循环获取区块所有转账信息
|
||||
while (true) {
|
||||
$oResponseBean = $this->getHandle()->getTrc20BlockEventsTransferByBlockNumber($blockNumber, $fingerprint);
|
||||
if ($oResponseBean === false) throw new QueueException('获取区块信息失败');
|
||||
if (empty($oResponseBean)) break;
|
||||
if ($oResponseBean->getSuccess() === false) break;
|
||||
$fingerprint = $oResponseBean->getMeta()->getFingerprint();
|
||||
if (empty($oResponseBean->getData())) break;
|
||||
//投递到区块账变队列
|
||||
$oQueueWalletBlockTransactionBean = new QueueWalletBlockTransactionBean();
|
||||
$oQueueWalletBlockTransactionBean->setData($oResponseBean->getData());
|
||||
WalletBlockTransactionQueue::putToQueue($oQueueWalletBlockTransactionBean);
|
||||
|
||||
if (empty($fingerprint)) break;
|
||||
}
|
||||
$updateItem = [
|
||||
'id' => $oResModel->id,
|
||||
'status' => WalletTronBlockModel::STATUS_FINISH,
|
||||
];
|
||||
$oWalletTronBlockModel->updateItem($updateItem);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Logs::ErrLog(__FUNCTION__, $e, $oQueueWalletBlockBean->toArray());
|
||||
$oQueueWalletBlockBean->IncrTryTimes();
|
||||
if (!$oQueueWalletBlockBean->checkTryTimes()) { //超出重试次数
|
||||
$updateItem = [
|
||||
'id' => $oResModel->id,
|
||||
'status' => WalletTronBlockModel::STATUS_FAIL,
|
||||
];
|
||||
$oWalletTronBlockModel->updateItem($updateItem);
|
||||
return;
|
||||
}
|
||||
WalletBlockQueue::putToQueue($oQueueWalletBlockBean, 30);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//监听处理区块每笔合约交易
|
||||
public function tronBlockTransactionConsumer(QueueWalletBlockTransactionBean $oQueueWalletBlockTransactionBean): void
|
||||
{
|
||||
$aBlockEvents = $oQueueWalletBlockTransactionBean->getData();
|
||||
foreach ($aBlockEvents as $item) {
|
||||
$oEventBean = new EventBean($item);
|
||||
try {
|
||||
$this->tronBlockTransaction($oEventBean);
|
||||
} catch (\Exception $e) {
|
||||
Logs::ErrLog(__FUNCTION__, $e, $oEventBean->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//监听处理单个合约交易
|
||||
function tronBlockTransaction(EventBean $oEventBean): void
|
||||
{
|
||||
//检查合约
|
||||
if ($oEventBean->getContractAddress() != UsdtTrc20::CONTRACT_ADDRESS) return;
|
||||
|
||||
$from_addr = $oEventBean->getResult()->getFrom();
|
||||
$to_addr = $oEventBean->getResult()->getTo();
|
||||
$value = $oEventBean->getResult()->getValue();
|
||||
|
||||
//检查交易双方是否是平台地址
|
||||
$oTronWalletAddressSetCache = new TronWalletAddressSetCache();
|
||||
$is_from = $oTronWalletAddressSetCache->checkKey($from_addr);
|
||||
$is_to = $oTronWalletAddressSetCache->checkKey($to_addr);
|
||||
if (!$is_from && !$is_to) return;
|
||||
//投递到钱包地址账变处理队列
|
||||
$oQueueEventBean = new QueueEventBean($oEventBean->toArray());
|
||||
WalletAddressTransactionQueue::putToQueue($oQueueEventBean);
|
||||
return;
|
||||
}
|
||||
|
||||
//用户钱包地址交易账变处理
|
||||
function walletAddressTransactionConsumer(QueueEventBean $bean): void
|
||||
{
|
||||
try {
|
||||
$from_addr = $bean->getResult()->getFrom();
|
||||
$to_addr = $bean->getResult()->getTo();
|
||||
$value = $bean->getResult()->getValue();
|
||||
|
||||
//查询地址是否存在
|
||||
$oWalletAddressModel = new WalletAddressModel();
|
||||
$resFromModel = $oWalletAddressModel->findByAddressHex($from_addr, WalletCurrencyModel::CODE_USDT_TRC20);
|
||||
$resToModel = $oWalletAddressModel->findByAddressHex($to_addr, WalletCurrencyModel::CODE_USDT_TRC20);
|
||||
if (!$resFromModel && !$resToModel) return;
|
||||
|
||||
//先落地到数据库
|
||||
$oWalletAddressTransactionModel = new WalletAddressTransactionModel();
|
||||
$oWalletAddressTransactionBean = new WalletAddressTransactionBean();
|
||||
$oWalletAddressTransactionBean->setCurrencyCode(WalletCurrencyModel::CODE_USDT_TRC20);
|
||||
$oWalletAddressTransactionBean->setBlockTransactionId($bean->getTransactionId());
|
||||
$oWalletAddressTransactionBean->setBlockNumber($bean->getBlockNumber());
|
||||
$oWalletAddressTransactionBean->setBlockEventName($bean->getEventName());
|
||||
$oWalletAddressTransactionBean->setBlockFromAddress($bean->getResult()->getFrom());
|
||||
$oWalletAddressTransactionBean->setBlockToAddress($bean->getResult()->getTo());
|
||||
$oWalletAddressTransactionBean->setBlockValue($bean->getResult()->getValue());
|
||||
$oWalletAddressTransactionBean->setIsNotify(WalletAddressTransactionModel::IS_NOTIFY_WAIT);
|
||||
|
||||
if ($resToModel) { //充值
|
||||
$oWalletAddressTransactionBean->setType(WalletAddressTransactionModel::TYPE_RECHARGE);
|
||||
$oWalletAddressTransactionBean->setWalletAddressId($resToModel->id);
|
||||
$resRecharge = $oWalletAddressTransactionModel->typeRecharge($oWalletAddressTransactionBean);
|
||||
if (!$resRecharge) throw new QueueException('WalletAddressTransactionModel addTransaction recharge error');
|
||||
//投递到处理平台用户账变队列
|
||||
$this->addToQueue($oWalletAddressTransactionBean);
|
||||
}
|
||||
if ($resFromModel) { //提现
|
||||
$oWalletAddressTransactionBean->setType(WalletAddressTransactionModel::TYPE_WITHDRAW);
|
||||
$oWalletAddressTransactionBean->setWalletAddressId($resFromModel->id);
|
||||
$resWithdraw = $oWalletAddressTransactionModel->typeWithdraw($oWalletAddressTransactionBean);
|
||||
if (!$resWithdraw) throw new QueueException('WalletAddressTransactionModel addTransaction withdraw error');
|
||||
//投递到处理平台用户账变队列
|
||||
$this->addToQueue($oWalletAddressTransactionBean);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Logs::ErrLog(__FUNCTION__, $e, $bean->toArrayNotNull());
|
||||
$bean->IncrTryTimes();
|
||||
if($bean->checkTryTimes()) return;
|
||||
WalletAddressTransactionQueue::putToQueue($bean, 30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function addToQueue(WalletAddressTransactionBean $bean): void
|
||||
{
|
||||
$oQueueWalletPlatformTransactionBean = new QueueWalletPlatformTransactionBean();
|
||||
$oQueueWalletPlatformTransactionBean->setWalletId($bean->getWalletAddressId());
|
||||
$oQueueWalletPlatformTransactionBean->setWalletTransactionId($bean->getId());
|
||||
$oQueueWalletPlatformTransactionBean->setBlockTransactionId($bean->getBlockTransactionId());
|
||||
$oQueueWalletPlatformTransactionBean->setAmount($bean->getAmount());
|
||||
$oQueueWalletPlatformTransactionBean->setType($bean->getType());
|
||||
WalletPlatformTransactionQueue::putToQueue($oQueueWalletPlatformTransactionBean);
|
||||
}
|
||||
}
|
||||
31
app/Service/PlatformRechargeService.php
Normal file
31
app/Service/PlatformRechargeService.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Bean\Queue\Wallet\QueueWalletPlatformTransactionBean;
|
||||
use App\Exceptions\QueueException;
|
||||
use App\Models\Wallet\Platform\WalletPlatformBalanceTransactionModel;
|
||||
use App\Models\Wallet\Platform\WalletPlatformBindModel;
|
||||
|
||||
class PlatformRechargeService
|
||||
{
|
||||
function walletPlatformTransactionConsumer(QueueWalletPlatformTransactionBean $bean): void
|
||||
{
|
||||
//根据钱包id查找平台和用户
|
||||
$oWalletPlatformBindModel = new WalletPlatformBindModel();
|
||||
$resBindModel = $oWalletPlatformBindModel->findItem($bean->getWalletId());
|
||||
if (!$resBindModel) throw new QueueException('钱包不存在');
|
||||
$oWalletPlatformBalanceTransactionModel = new WalletPlatformBalanceTransactionModel();
|
||||
$res = $oWalletPlatformBalanceTransactionModel->typeRecharge(
|
||||
$resBindModel->platform_id,
|
||||
$resBindModel->uid,
|
||||
$resBindModel->currency_code,
|
||||
$bean->getAmount(),
|
||||
$bean->getWalletId(),
|
||||
$bean->getBlockTransactionId(),
|
||||
$bean->getWalletTransactionId()
|
||||
);
|
||||
if (!$res) throw new QueueException('typeRecharge fail');
|
||||
}
|
||||
|
||||
}
|
||||
130
app/Service/PlatformWithdrawService.php
Normal file
130
app/Service/PlatformWithdrawService.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
namespace App\Service;
|
||||
|
||||
use App\Bean\Queue\Wallet\QueueWalletPlatformTransactionBean;
|
||||
use App\Bean\Queue\Wallet\QueueWalletPlatformWithdrawTransferBean;
|
||||
use App\Exceptions\QueueException;
|
||||
use App\Models\Wallet\Platform\WalletPlatformBalanceTransactionModel;
|
||||
use App\Models\Wallet\Platform\WalletPlatformBindModel;
|
||||
use App\Models\Wallet\Wallet\WalletAddressModel;
|
||||
use App\Models\Wallet\Wallet\WalletCurrencyModel;
|
||||
use App\Tools\Logs;
|
||||
use App\Tools\Times;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Sdk\Wallet\TokenAddress;
|
||||
use Sdk\Wallet\UsdtTrc20;
|
||||
|
||||
class PlatformWithdrawService
|
||||
{
|
||||
function withdrawTransferConsumer(QueueWalletPlatformWithdrawTransferBean $bean): void
|
||||
{
|
||||
//获取账变
|
||||
$oWalletPlatformBalanceTransactionModel = new WalletPlatformBalanceTransactionModel();
|
||||
$resModel = $oWalletPlatformBalanceTransactionModel->findItem($bean->getTransactionId());
|
||||
if (!$resModel) throw new QueueException('账变不存在');
|
||||
if($resModel->status != WalletPlatformBalanceTransactionModel::STATUS_WAIT) throw new QueueException('账变状态不正确');
|
||||
|
||||
//更新账变状态
|
||||
$updateItem = [
|
||||
'id' => $bean->getTransactionId(),
|
||||
'status' => WalletPlatformBalanceTransactionModel::STATUS_PROCESSING,
|
||||
'updated_at' => Times::getNowDateTime(),
|
||||
];
|
||||
$res = $oWalletPlatformBalanceTransactionModel->updateItem($updateItem);
|
||||
if (!$res) throw new QueueException('更新账变状态失败');
|
||||
$currency_code = $resModel->currency_code;
|
||||
//提现
|
||||
try {
|
||||
//根据币种调用不同的提现方法
|
||||
switch ($currency_code) {
|
||||
case WalletCurrencyModel::CODE_USDT_TRC20: //提现USDT
|
||||
|
||||
$txId = $this->withdrawUsdtTrc20($resModel);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new QueueException('不支持的币种');
|
||||
}
|
||||
|
||||
|
||||
Logs::SuccLog(__FUNCTION__, $bean->toArrayNotNull());
|
||||
}catch (\Exception $e){
|
||||
//更新账变状态
|
||||
$updateItem = [
|
||||
'id' => $bean->getTransactionId(),
|
||||
'status' => WalletPlatformBalanceTransactionModel::STATUS_FAIL,
|
||||
'updated_at' => Times::getNowDateTime(),
|
||||
];
|
||||
$oWalletPlatformBalanceTransactionModel->updateItem($updateItem);
|
||||
Logs::ErrLog(__FUNCTION__ . ' ' . 'rollBack', $e, $bean->toArrayNotNull());
|
||||
throw new QueueException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function withdrawUsdtTrc20($model): string
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$oWalletAddressModel = new WalletAddressModel();
|
||||
//获取出金地址
|
||||
$resFromModel = $oWalletAddressModel->findWithdrawWallet($model->currency_code, $model->amount);
|
||||
if(!$resFromModel) throw new QueueException('提现地址不足');
|
||||
$from_wallet_address_id = $resFromModel->id;
|
||||
$from_wallet_address = $resFromModel->address_base58;
|
||||
|
||||
//获取入金地址
|
||||
$to_wallet_address = $model->to_wallet_address;
|
||||
if(!empty($to_wallet_address)) throw new QueueException('平台钱包id错误');
|
||||
|
||||
$fromAddress = new TokenAddress($resFromModel->address_base58, $oWalletAddressModel->decodePrivateKey($resFromModel->private_key));
|
||||
$toAddress = new TokenAddress($to_wallet_address);
|
||||
$amount = abs($model->amount);
|
||||
|
||||
//调用sdk发起提现
|
||||
$sdk = new UsdtTrc20();
|
||||
$oTransferTransactionBean = $sdk->getHandler()->trc20Transfer($fromAddress,$toAddress, $amount);
|
||||
if(!$oTransferTransactionBean) throw new QueueException('提现sdk发起失败');
|
||||
if(empty($oTransferTransactionBean->getTxID())) throw new QueueException('提现sdk发起失败');
|
||||
|
||||
//存储交易id
|
||||
$updateItem = [
|
||||
'id' => $model->id,
|
||||
'block_transaction_id' => $oTransferTransactionBean->getTxID(),
|
||||
'from_wallet_address_id' => $from_wallet_address_id,
|
||||
'from_wallet_address' => $from_wallet_address,
|
||||
'updated_at' => Times::getNowDateTime(),
|
||||
];
|
||||
$oWalletPlatformBalanceTransactionModel = new WalletPlatformBalanceTransactionModel();
|
||||
$res = $oWalletPlatformBalanceTransactionModel->updateItem($updateItem);
|
||||
if(!$res) throw new QueueException('更新账变失败');
|
||||
|
||||
DB::commit();
|
||||
return $oTransferTransactionBean->getTxID();
|
||||
}catch (\Exception $e){
|
||||
DB::rollBack();
|
||||
throw new QueueException($e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function walletPlatformTransactionConsumer(QueueWalletPlatformTransactionBean $bean): void
|
||||
{
|
||||
//根据txid查找平台和用户
|
||||
$oWalletPlatformBindModel = new WalletPlatformBindModel();
|
||||
$resBindModel = $oWalletPlatformBindModel->findItem($bean->getWalletId());
|
||||
if (!$resBindModel) throw new QueueException('钱包不存在');
|
||||
$oWalletPlatformBalanceTransactionModel = new WalletPlatformBalanceTransactionModel();
|
||||
$resModel = $oWalletPlatformBalanceTransactionModel->findByBlockTransactionId($bean->getBlockTransactionId(), WalletPlatformBalanceTransactionModel::TYPE_WITHDRAW_DEC);
|
||||
if (!$resModel) throw new QueueException('账变不存在');
|
||||
if($resModel->status != WalletPlatformBalanceTransactionModel::STATUS_PROCESSING) throw new QueueException('账变状态不正确');
|
||||
|
||||
$res = $oWalletPlatformBalanceTransactionModel->typeWithdrawSecondCallback(
|
||||
$resModel->id,
|
||||
WalletPlatformBalanceTransactionModel::STATUS_SUCCESS,
|
||||
null,
|
||||
$bean->getWalletTransactionId(),
|
||||
);
|
||||
if (!$res) throw new QueueException('typeWithdrawSecondCallback fail');
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user