Просмотр исходного кода

Weenier 168otc项目部署 0630

wesmiler 3 лет назад
Родитель
Сommit
1d10df2963

+ 0 - 98
app/Services/GoogleCodeService.php

@@ -1,98 +0,0 @@
-<?php
-// +----------------------------------------------------------------------
-// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
-// +----------------------------------------------------------------------
-// | 版权所有 2017~2021 LARAVEL研发中心
-// +----------------------------------------------------------------------
-// | 官方网站: http://www.laravel.cn
-// +----------------------------------------------------------------------
-// | Author: laravel开发员 <laravel.qq.com>
-// +----------------------------------------------------------------------
-
-namespace App\Services;
-
-/**
- * 谷歌验证码管理-服务类
- * Class GoogleCodeService
- * @package App\Services
- */
-class GoogleCodeService extends BaseService
-{
-    // 静态对象
-    protected static $instance = null;
-
-    /**
-     * 初始化配置
-     * @return bool
-     */
-    public function __construct()
-    {
-        $this->config = ConfigService::make()->getConfigByGroup(2);
-        if (empty($this->config)) {
-            return false;
-        }
-    }
-
-    /**
-     * 静态入口
-     * @return static|null
-     */
-    public static function make()
-    {
-        if (!self::$instance) {
-            self::$instance = (new static());
-        }
-        return self::$instance;
-    }
-
-    public function getQrcode($userId)
-    {
-
-    }
-
-    /**
-     * 发送谷歌验证码
-     * @param $userId
-     * @param string $scene 场景:默认reg-注册
-     * @return bool
-     */
-    public function sendCode($userId, $scene = 'reg')
-    {
-        try {
-            $cacheKey = "stores:codes:google_{$scene}:{$userId}";
-
-        } catch (\Exception $exception) {
-            $this->error = $exception->getMessage();
-            return false;
-        }
-    }
-
-
-    /**
-     * 验证手机短信
-     * @param $mobile
-     * @param $code
-     * @param string $scene 场景:默认reg-注册
-     * @return bool
-     */
-    public function check($mobile, $code, $scene = 'reg')
-    {
-        $cacheKey = "stores:codes:sms_{$scene}:". substr($mobile, -3, 3) . '_' . md5($mobile);
-        $codeData = RedisService::get($cacheKey);
-        $checkCode = isset($codeData['code']) ? $codeData['code'] : 0;
-        $checkMobile = isset($codeData['mobile']) ? $codeData['mobile'] : '';
-        if (empty($codeData) || empty($checkCode)) {
-            $this->error = 2010;
-            return false;
-        }
-
-        if ($checkMobile != $mobile || $checkCode != $code) {
-            $this->error = 2006;
-            return false;
-        }
-
-        return true;
-    }
-
-
-}

+ 832 - 0
app/Services/UsdtWalletService.php

@@ -0,0 +1,832 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Services;
+
+use App\Models\CapitalLogModel;
+use App\Models\CoinLogModel;
+use App\Models\MemberModel;
+use App\Services\Api\MemberService;
+use App\Services\Common\CoinLogService;
+use BitWasp\Bitcoin\Address\AddressCreator;
+use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
+use BitWasp\Bitcoin\Bitcoin;
+use BitWasp\Bitcoin\Crypto\Random\Random;
+use BitWasp\Bitcoin\Key\Factory\HierarchicalKeyFactory;
+use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
+use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39Mnemonic;
+use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator;
+use BitWasp\Bitcoin\Mnemonic\MnemonicFactory;
+use BitWasp\Bitcoin\Script\WitnessProgram;
+use GuzzleHttp\Client;
+use IEXBase\TronAPI\Tron;
+use Tron\Api;
+use Tron\TRC20;
+use Tron\TRX;
+use Web3\Personal;
+use Web3\Web3;
+use Web3p\EthereumUtil\Util;
+
+/**
+ * USDT链管理-服务类
+ * Class UsdtWalletService
+ * @package App\Services
+ */
+class UsdtWalletService extends BaseService
+{
+    protected $apiUrl = '';
+    protected $config = [];
+    protected $apiUrls = [
+        'usdt_trx2_transfer_log' => '/v1/accounts/%s/transactions/trc20?limit=%s&only_to=%s&only_from=%s&only_confirmed=true&contract_address=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
+        'usdt_trx2_transfer_logs' => '/v1/accounts/%s/transactions/trc20?limit=%s&only_to=%s&only_from=%s&contract_address=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
+    ];
+
+    /**
+     * 构造函数
+     * UsdtWalletService constructor.
+     */
+    public function __construct()
+    {
+        $this->memberModel = new MemberModel();
+        $this->coinModel = new CoinLogModel();
+        $this->capitalModel = new CapitalLogModel();
+        $this->config = ConfigService::make()->getConfigOptionByGroup(4);
+        $this->apiUrl = isset($this->config['usdt_api_url']) ? $this->config['usdt_api_url'] : '';
+        if (empty($this->config) || empty($this->apiUrl)) {
+            return false;
+        }
+    }
+
+    /**
+     * 静态入口
+     * @return UsdtWalletService|null
+     */
+    public static function make()
+    {
+        return parent::make(); // TODO: Change the autogenerated stub
+    }
+
+    /**
+     * 获取TRC2.0钱包地址
+     * @throws \Tron\Exceptions\TronErrorException
+     */
+    public function getTrxAddress()
+    {
+        $api = new Api(new Client(['base_uri' => $this->config['tron_api_url']]));
+
+        $trxWallet = new TRX($api);
+        $addressData = $trxWallet->generateAddress();
+        $addressData = (array)$addressData;
+        return ['wif' => $addressData['privateKey'], 'hexAddress' => $addressData['hexAddress'], 'address' => $addressData['address']];
+    }
+
+    /**
+     * 获取TRC2.0钱包地址
+     * @throws \Tron\Exceptions\TronErrorException
+     */
+    public function getTrxAddress1($userId = 0)
+    {
+        $api = new Api(new Client(['base_uri' => $this->config['tron_api_url']]));
+
+        $trxWallet = new TRX($api);
+        $addressData = $trxWallet->generateAddress();
+    }
+
+    /**
+     * trx 转账
+     * @param $to 进账账户
+     * @param $amount 转账金额
+     * @throws \Tron\Exceptions\TransactionException
+     * @throws \Tron\Exceptions\TronErrorException
+     */
+    public function trxTransfer($to, $amount, $from = '')
+    {
+        if ($amount <= 0) {
+            $this->error = '2205';
+            return false;
+        }
+
+
+        if (empty($this->config['tron_api_url'])) {
+            $this->error = '2206';
+            return false;
+        }
+
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        $api = new Api(new Client(['base_uri' => $this->config['tron_api_url'], 'headers' => $headers]));
+        $trxWallet = new TRX($api);
+
+        // 获取钱包参数
+        try {
+            $otcAddress = ConfigService::make()->getConfigByCode('trc_out_address');
+            $otcAddressPrivate = ConfigService::make()->getConfigByCode('trc_out_private_key');
+            if (empty($otcAddress) || empty($otcAddressPrivate)) {
+                $this->error = '2203';
+                return false;
+            }
+
+            $tron = new Tron();
+            // 获取平台钱包hex
+            $tron->setAddress($otcAddress);
+            $otcAddress = $tron->getAddress();
+
+
+            $tron->setAddress($to);
+            $toAddress = $tron->getAddress();
+            $from = new \Tron\Address($otcAddress['base58'], $otcAddressPrivate, $otcAddress['hex']);
+            $to = new \Tron\Address($toAddress['base58'], '', $toAddress['hex']);
+            $result = $trxWallet->transfer($from, $to, $amount);
+
+            return $result;
+        } catch (\Exception $exception) {
+            $message = $exception->getMessage();
+            $this->error = $message;
+            return false;
+        }
+    }
+
+    /**
+     * usdt-trc2.0 转账
+     * @param $to 进账账户
+     * @param $amount 转账金额
+     * @param $from 转账账户
+     * @param $fromPrivate 转账账户私钥
+     * @throws \Tron\Exceptions\TransactionException
+     * @throws \Tron\Exceptions\TronErrorException
+     */
+    public function usdtTrcTransfer($to, $amount, $from = '', $fromPrivate = '')
+    {
+        if ($amount <= 0) {
+            $this->error = '2205';
+            return false;
+        }
+
+        if (empty($this->config['tron_api_url'])) {
+            $this->error = '2206';
+            return false;
+        }
+
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        $api = new Api(new Client(['base_uri' => $this->config['tron_api_url'], 'headers' => $headers]));
+        $trxWallet = new TRC20($api, ['contract_address' => $this->config['tron_contract_address'], 'decimals' => 6]);
+
+        // 获取钱包参数
+        try {
+
+            // 用出账钱包转账
+            $otcAddress = $from ? $from : ConfigService::make()->getConfigByCode('trc_out_address');
+            $otcAddressPrivate = $from ? $fromPrivate : ConfigService::make()->getConfigByCode('trc_out_private_key');
+            if (empty($otcAddress) || empty($otcAddressPrivate)) {
+                $this->error = '2203';
+                return false;
+            }
+
+            $tron = new Tron();
+            // 获取平台钱包hex
+            $tron->setAddress($otcAddress);
+            $otcAddress = $tron->getAddress();
+
+            // 获取收款钱包hex
+            $tron->setAddress($to);
+            $toAddress = $tron->getAddress();
+            $from = new \Tron\Address($otcAddress['base58'], $otcAddressPrivate, $otcAddress['hex']);
+            $to = new \Tron\Address($toAddress['base58'], '', $toAddress['hex']);
+            $result = $trxWallet->transfer($from, $to, $amount);
+            return $result;
+        } catch (\Exception $exception) {
+            $message = $exception->getMessage();
+
+            $this->error = $message;
+            return false;
+        }
+    }
+
+    /**
+     * usdt-trc2.0 归集
+     * @throws \Tron\Exceptions\TransactionException
+     * @throws \Tron\Exceptions\TronErrorException
+     */
+    public function usdtTrcTrigger($force = false)
+    {
+
+        if (empty($this->config['tron_api_url'])) {
+            $this->error = '2206';
+            return false;
+        }
+
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        $api = new Api(new Client(['base_uri' => $this->config['tron_api_url'], 'headers' => $headers]));
+        $trcWallet = new TRC20($api, ['contract_address' => $this->config['tron_contract_address'], 'decimals' => 6]);
+        $trxWallet = new TRX($api, ['contract_address' => $this->config['tron_contract_address'], 'decimals' => 6]);
+
+        // 获取钱包参数
+        try {
+
+            // 用收账钱包归集
+            $otcAddress = ConfigService::make()->getConfigByCode('trc_address');
+            $otcAddressPrivate = ConfigService::make()->getConfigByCode('trc_private_key');
+            // 出账手续费钱包
+            $otcOutAddress = ConfigService::make()->getConfigByCode('trc_out_address');
+            $otcOutAddressPrivate = ConfigService::make()->getConfigByCode('trc_out_private_key');
+            $triggerMin = ConfigService::make()->getConfigByCode('trade_trigger_min');
+            $triggerTime = ConfigService::make()->getConfigByCode('trade_trigger_time');
+            $triggerFree = ConfigService::make()->getConfigByCode('trade_trigger_free');
+            $triggerFree = $triggerFree > 0 ? $triggerFree : 8;
+            $triggerMin = $triggerMin > 0 ? $triggerMin : 0.1;
+            $triggerTime = $triggerTime > 0 ? $triggerTime * 86400 : 86400;
+            if (empty($otcAddress) || empty($otcAddressPrivate)) {
+                $this->error = '2203';
+                return false;
+            }
+
+            // 出账钱包
+            if (empty($otcOutAddress) || empty($otcOutAddressPrivate)) {
+                $this->error = '2203';
+                return false;
+            }
+
+            $page = RedisService::get("caches:wallet:transferPage");
+            $page = $page ? $page : 1;
+
+            // 归集时间段为凌晨0点-5点
+            if ((date('H:i') >= '05:00') && !$force) {
+                $this->error = '不在归集时间段';
+                return false;
+            }
+
+            if (RedisService::get("caches:wallet:triggerLock:{$page}")) {
+                $this->error = '不要频繁操作,30秒后重试';
+                return false;
+            }
+
+            // 上锁
+            RedisService::set("caches:wallet:triggerLock:{$page}", 1, rand(10, 30));
+            $addrList = MemberService::make()->getTriggerAddressList($triggerMin, $page, 200);
+            if (empty($addrList)) {
+                RedisService::set("caches:wallet:transferPage", 1, 600);
+                $this->error = '1019';
+                return false;
+            }
+
+
+            // 平台钱包地址
+            $count = 0;
+            $failedCount = 0;
+            $tron = new Tron();
+            $tron->setAddress($otcAddress);
+            $otcAddress = $tron->getAddress();
+            $otcAddressData = new \Tron\Address($otcAddress['base58'], $otcAddressPrivate, $otcAddress['hex']);
+
+            // 平台出账钱包地址
+            $tron->setAddress($otcOutAddress);
+            $otcOutAddress = $tron->getAddress();
+            $otcOutAddressData = new \Tron\Address($otcOutAddress['base58'], $otcOutAddressPrivate, $otcOutAddress['hex']);
+            $cacheKey = "caches:wallet:trigger:";
+            foreach ($addrList as $v) {
+                try {
+                    // 获取子钱包TRC-USDT余额
+                    $userId = isset($v['id']) ? $v['id'] : 0;
+                    $address = isset($v['trc_address']) ? $v['trc_address'] : '';
+                    $hexAddress = isset($v['trc_hexaddress']) ? $v['trc_hexaddress'] : '';
+                    $addressPrivate = isset($v['trc_wif']) ? $v['trc_wif'] : '';
+                    $triggerAddress = new \Tron\Address($address, $addressPrivate, $hexAddress);
+                    // 可归集的USDT余额
+                    $triggerUsdt = $trcWallet->balance($triggerAddress);
+
+                    // USDT 余额低于归集金额,则不归集
+                    if ($triggerUsdt < $triggerMin) {
+                        $failedCount++;
+                        $error = ['data' => $v, 'usdt' => $triggerUsdt, 'triggerMin' => $triggerMin, 'error' => '用户余额不足归集', 'date' => date('Y-m-d H:i:s')];
+                        RedisService::set($cacheKey . "U_{$userId}:error", $error, 7200);
+                        continue;
+                    }
+
+                    // 获取子钱包TRX余额
+                    $triggerTrx = $trxWallet->balance($triggerAddress);
+
+                    // 获取平台出账钱包TRX余额
+                    $otcOutTrxTotal = $trxWallet->balance($otcOutAddressData);
+
+                    // 如果子钱包和平台钱包TRX余额不足手续费,则不归集
+                    if ($triggerTrx < $triggerFree && $otcOutTrxTotal < $triggerFree) {
+                        $failedCount++;
+                        $error = ['data' => $v, 'usdt' => $triggerUsdt, 'triggerMin' => $triggerMin, 'triggerTrx' => $triggerTrx, 'otcTrx' => $otcOutTrxTotal, 'error' => '平台钱包手续费不足', 'date' => date('Y-m-d H:i:s')];
+                        RedisService::set($cacheKey . "U_{$userId}:error", $error, 7200);
+                        continue;
+                    }
+
+                    // 如果子钱包TRX不足手续费8个,平台TRX充足则自动充值后下次调用时归集
+                    if ($triggerTrx < $triggerFree) {
+                        $failedCount++;
+                        $result = $this->trxTransfer($address, $triggerFree);
+                        $error = ['data' => $v, 'usdt' => $triggerUsdt, 'triggerMin' => $triggerMin, 'triggerTrx' => $triggerTrx, 'transfer' => $result, 'error' => '归集钱包手续费不足,先充值', 'date' => date('Y-m-d H:i:s')];
+                        RedisService::set($cacheKey . "U_{$userId}:catch", $error, 7200);
+                        continue;
+                    }
+
+                    // 满足归集条件处理
+                    $result = $trcWallet->transfer($triggerAddress, $otcAddressData, $triggerUsdt);
+                    RedisService::set($cacheKey . "U_{$userId}:result", ['data' => $v, 'result' => $result, 'msg' => '归集已提交', 'date' => date('Y-m-d H:i:s')], 7200);
+                    $count++;
+
+                } catch (\Exception $exception) {
+                    $failedCount++;
+                    RedisService::set($cacheKey . "U_{$userId}:exception", ['data' => $v, 'msg' => $exception->getMessage(), 'date' => date('Y-m-d H:i:s')], 7200);
+                }
+
+            }
+
+            // 超出分页数,下次处理下一页
+            if (count($addrList) >= 200) {
+                RedisService::set("caches:wallet:transferPage", $page + 1, 600);
+            }
+            if ($count > 0) {
+                return ['success' => $count, 'fail' => $failedCount];
+            } else {
+                $this->error = 1021;
+                return false;
+            }
+        } catch (\Exception $exception) {
+            $this->error = $exception->getMessage();
+            return false;
+        }
+    }
+
+
+    /**
+     * 监听USDT-TRC2.0转账记录并进账
+     * @param $userId 用户ID
+     * @param $address 用户钱包地址
+     * @param int $coinType 币种:1-usdt
+     * @param int $limit 转账记录数,最新的
+     * @return array|false
+     */
+    public function getTrc20RechargeLog($userId, $address, $coinType = 1, $limit = 50)
+    {
+        if ($userId <= 0 || empty($address)) {
+            $this->error = '1013';
+            return false;
+        }
+
+        $url = sprintf($this->apiUrls['usdt_trx2_transfer_log'], $address, $limit, 'true', 'false');
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        RedisService::set("caches:wallets:recharge_temp_{$userId}", ['url' => $this->config['tron_api_url'] . $url], 600);
+        $result = curl_get($this->config['tron_api_url'] . $url, [], $headers, 10);
+        $result = $result ? json_decode($result, true) : [];
+        $datas = isset($result['data']) ? $result['data'] : [];
+        $status = isset($result['success']) ? $result['success'] : '';
+        if ($status != true || empty($datas)) {
+            $this->error = '2207';
+            return false;
+        }
+
+        $logs = [];
+        $coinInMin = ConfigService::make()->getConfigByCode('trc_in_limit');
+        $coinInMin = $coinInMin > 0 ? $coinInMin : 0;
+        foreach ($datas as $v) {
+            $amount = isset($v['value']) ? intval($v['value']) : 0;
+            $amount = moneyFormat($amount / 1000000, 6);
+            $time = isset($v['block_timestamp']) ? intval($v['block_timestamp'] / 1000) : 0;
+            $txid = isset($v['transaction_id']) ? $v['transaction_id'] : '';
+            if (!CoinLogService::make()->checkExists('txid', $txid) && $time > time() - 12 * 3600) {
+                $balance = $this->memberModel->where(['id' => $userId])->value('usdt_num');
+                $orderNo = get_order_num('TR');
+                $log = [
+                    'user_id' => $userId,
+                    'change_type' => 1,
+                    'coin_type' => $coinType,
+                    'contact_type' => 1,
+                    'order_no' => $orderNo,
+                    'from_address' => isset($v['from']) ? $v['from'] : '',
+                    'to_address' => isset($v['to']) ? $v['to'] : '',
+                    'txid' => $txid,
+                    'num' => $amount,
+                    'balance' => $balance,
+                    'create_time' => $time ? $time : time(),
+                    'update_time' => time(),
+                    'status' => 2,
+                    'mark' => 1,
+                ];
+
+                if ($amount >= $coinInMin && $this->memberModel->where(['id' => $userId])->increment('usdt_num', $amount)) {
+                    $this->memberModel->where(['id' => $userId])->increment('trc_usdt', $amount);
+                    $log['status'] = 1;
+
+                    $data = [
+                        'order_no' => $orderNo,
+                        'user_id' => $userId,
+                        'type' => 4,
+                        'pay_type' => 1,
+                        'trade_type' => 3,
+                        'change_type' => 1,
+                        'num' => $amount,
+                        'total' => 0,
+                        'balance' => floatval($balance+$amount),
+                        'create_time' => time(),
+                        'update_time' => time(),
+                        'remark' => '存币',
+                        'status' => 1,
+                        'mark' => 1,
+                    ];
+
+                    $this->capitalModel->edit($data);
+                }
+
+                $logs[] = $log;
+                $this->coinModel->insert($log);
+            }
+        }
+
+        return $logs;
+    }
+
+    /**
+     * 获取USDT-TRC2.0交易记录(进出账)
+     * @param $address 用户钱包地址
+     * @param int $coinType 币种:1-usdt
+     * @param int $limit 转账记录数,最新的
+     * @return array|false
+     */
+    public function getTrc20TransferLog($address, $type = 1, $limit = 50)
+    {
+        if (empty($address)) {
+            $this->error = '1013';
+            return false;
+        }
+
+        // 存币
+        if($type == 1){
+            $url = sprintf($this->apiUrls['usdt_trx2_transfer_log'], $address, $limit, 'true', 'false');
+        }
+        // 提币
+        else{
+            $url = sprintf($this->apiUrls['usdt_trx2_transfer_log'], $address, $limit, 'false', 'true');
+        }
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        RedisService::set("caches:wallets:transfer_temp_otc_{$type}", ['url' => $this->config['tron_api_url'] . $url], 600);
+        $result = curl_get($this->config['tron_api_url'] . $url, [], $headers, 10);
+        $result = $result ? json_decode($result, true) : [];
+        $datas = isset($result['data']) ? $result['data'] : [];
+        $status = isset($result['success']) ? $result['success'] : '';
+        if ($status != true || empty($datas)) {
+            $this->error = '2207';
+            return false;
+        }
+
+        if($datas){
+            foreach ($datas as &$item){
+                $time = ($item['block_timestamp']/1000);
+                $item['time_text'] = $time? datetime($time, 'm-d H:i') : '';
+                $item['num'] = floatval($item['value']/1000000);
+                $item['contact_type'] = 1;
+                $item['change_type'] = $type;
+                $item['status'] = 1;
+            }
+        }
+
+
+        return $datas;
+    }
+
+    /**
+     * 监听USDT-TRC2.0提币记录并进账(平台钱包)
+     * @param $address 用户钱包地址
+     * @param int $limit 转账记录数,最新的
+     * @return array|false
+     */
+    public function getTrc20TransferLogByOtc($address, $limit = 50)
+    {
+        if (empty($address)) {
+            $this->error = '1013';
+            return false;
+        }
+
+        $url = sprintf($this->apiUrls['usdt_trx2_transfer_log'], $address, $limit, 'false', 'true');
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        RedisService::set("caches:wallets:transfer_temp_otc", ['url' => $this->config['tron_api_url'] . $url], 600);
+        $result = curl_get($this->config['tron_api_url'] . $url, [], $headers, 10);
+        $result = $result ? json_decode($result, true) : [];
+        $datas = isset($result['data']) ? $result['data'] : [];
+        $status = isset($result['success']) ? $result['success'] : '';
+        if ($status != true || empty($datas)) {
+            $this->error = '2207';
+            return false;
+        }
+
+        $logs = [];
+        foreach ($datas as $v) {
+            $amount = isset($v['value']) ? intval($v['value']) : 0;
+            $amount = moneyFormat($amount / 1000000, 6);
+            $time = isset($v['block_timestamp']) ? intval($v['block_timestamp'] / 1000) : 0;
+            $txid = isset($v['transaction_id']) ? $v['transaction_id'] : '';
+
+            if ($time > time() - 12 * 3600) {
+
+                // 有记录,且是用户提币
+                $coinInfo = CoinLogService::make()->getCacheInfoByTxid($txid);
+                $userId = isset($coinInfo['user_id']) ? $coinInfo['user_id'] : 0;
+                if ($coinInfo && $userId && $coinInfo['status'] == 4) {
+                    // 直接更新提币状态
+                    CoinLogModel::where(['txid' => $txid, 'user_id' => $userId])->update(['status' => 1, 'update_time' => time()]);
+
+                    // 明细处理
+                    $num = floatval($coinInfo['num'] + $coinInfo['free']);
+                    $data = [
+                        'order_no' => $coinInfo['order_no'],
+                        'user_id' => $userId,
+                        'type' => 5,
+                        'pay_type' => 1,
+                        'trade_type' => 3,
+                        'change_type' => 2,
+                        'num' => $num,
+                        'total' => 0,
+                        'balance' => floatval($coinInfo['balance']-$num),
+                        'create_time' => time(),
+                        'update_time' => time(),
+                        'remark' => '提币',
+                        'status' => 1,
+                        'mark' => 1,
+                    ];
+
+                    $this->capitalModel->edit($data);
+
+                    $logs[] = ['log'=> $v,'order'=> $coinInfo];
+                }
+            }
+        }
+
+        return $logs;
+    }
+
+    /**
+     * 监听USDT-TRC2.0充值记录并进账(用户子钱包)
+     * @param $userId 用户ID
+     * @param $address 用户钱包地址
+     * @param int $coinType 币种:1-usdt
+     * @param int $limit 转账记录数,最新的
+     * @return array|false
+     */
+    public function getTrc20TransferLogByUser($userId, $address, $coinType = 1, $limit = 50)
+    {
+        if ($userId <= 0 || empty($address)) {
+            $this->error = '1013';
+            return false;
+        }
+
+        $url = sprintf($this->apiUrls['usdt_trx2_transfer_log'], $address, $limit, 'false', 'true');
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        RedisService::set("caches:wallets:transfer_temp_{$userId}", ['url' => $this->config['tron_api_url'] . $url], 600);
+        $result = curl_get($this->config['tron_api_url'] . $url, [], $headers, 10);
+        $result = $result ? json_decode($result, true) : [];
+        $datas = isset($result['data']) ? $result['data'] : [];
+        $status = isset($result['success']) ? $result['success'] : '';
+        if ($status != true || empty($datas)) {
+            $this->error = '2207';
+            return false;
+        }
+
+        $logs = [];
+        $coinOutMin = ConfigService::make()->getConfigByCode('trc_out_limit');
+        $coinOutMin = $coinOutMin > 0 ? $coinOutMin : 0;
+        foreach ($datas as $v) {
+            $amount = isset($v['value']) ? intval($v['value']) : 0;
+            $amount = moneyFormat($amount / 1000000, 6);
+            $time = isset($v['block_timestamp']) ? intval($v['block_timestamp'] / 1000) : 0;
+            $txid = isset($v['transaction_id']) ? $v['transaction_id'] : '';
+            if (!CoinLogService::make()->checkExists('txid', $txid) && $time > time() - 12 * 3600) {
+                $balance = $this->memberModel->where(['id' => $userId])->value('usdt_num');
+                $orderNo = get_order_num('TW');
+                $log = [
+                    'user_id' => $userId,
+                    'change_type' => 2,
+                    'coin_type' => $coinType,
+                    'contact_type' => 1,
+                    'order_no' => $orderNo,
+                    'from_address' => isset($v['from']) ? $v['from'] : '',
+                    'to_address' => isset($v['to']) ? $v['to'] : '',
+                    'txid' => $txid,
+                    'num' => $amount,
+                    'balance' => $balance,
+                    'create_time' => $time ? $time : time(),
+                    'update_time' => time(),
+                    'status' => 2,
+                    'mark' => 1,
+                ];
+
+                if ($amount >= $coinOutMin && $this->memberModel->where(['id' => $userId])->decrement('usdt_num', $amount)) {
+                    $this->memberModel->where(['id' => $userId])->decrement('trc_usdt', $amount);
+                    $log['status'] = 1;
+
+                    // 明细处理
+                    $data = [
+                        'order_no' => $orderNo,
+                        'user_id' => $userId,
+                        'type' => 5,
+                        'pay_type' => 1,
+                        'trade_type' => 3,
+                        'change_type' => 2,
+                        'num' => $amount,
+                        'total' => 0,
+                        'balance' => floatval($balance - $amount),
+                        'create_time' => time(),
+                        'update_time' => time(),
+                        'remark' => '提币',
+                        'status' => 1,
+                        'mark' => 1,
+                    ];
+
+                    $this->capitalModel->edit($data);
+
+                }
+
+                $logs[] = $log;
+                $this->coinModel->insert($log);
+            }
+        }
+
+        return $logs;
+    }
+
+    /**
+     * TRX余额
+     * @param $address
+     * @return false|float|string
+     */
+    public function getTrxBalance($address)
+    {
+        $cacheKey = "caches:wallet:balance:{$address}";
+        if (RedisService::get($cacheKey)) {
+            return false;
+        }
+
+        if (empty($address)) {
+            $this->error = '1018';
+            return false;
+        }
+
+        if (empty($this->config['tron_api_url'])) {
+            $this->error = '2206';
+            return false;
+        }
+
+        try {
+            $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+            $api = new Api(new Client(['base_uri' => $this->config['tron_api_url'], 'headers' => $headers]));
+            $trxWallet = new TRX($api, ['contract_address' => $this->config['tron_contract_address'], 'decimals' => 6]);
+
+            $tron = new Tron();
+            $tron->setAddress($address);
+            $address = $tron->getAddress();
+            $address = new \Tron\Address($address['base58'], '', $address['hex']);
+            $result = $trxWallet->balance($address);
+
+            return $result ? floatval($result) : '0.00';
+
+        } catch (\Exception $exception) {
+            $this->error = $exception->getMessage();
+            return false;
+        }
+    }
+
+    /**
+     * USDT-TRC20余额
+     * @param $address
+     * @return false|float|string
+     */
+    public function getTrc20Usdt($address)
+    {
+        if (empty($address)) {
+            $this->error = '1018';
+            return false;
+        }
+
+        if (empty($this->config['tron_api_url'])) {
+            $this->error = '2206';
+            return false;
+        }
+
+        try {
+            $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+            $api = new Api(new Client(['base_uri' => $this->config['tron_api_url'], 'headers' => $headers]));
+            $trxWallet = new TRC20($api, ['contract_address' => $this->config['tron_contract_address'], 'decimals' => 6]);
+
+            $tron = new Tron();
+            $tron->setAddress($address);
+            $address = $tron->getAddress();
+            $address = new \Tron\Address($address['base58'], '', $address['hex']);
+            $result = $trxWallet->balance($address);
+            return $result ? floatval($result) : '0.00';
+
+        } catch (\Exception $exception) {
+            $this->error = $exception->getMessage();
+            return false;
+        }
+    }
+
+    /**********************   ERC钱包  **************************/
+
+    /**
+     * 获取ERC2.0钱包地址
+     * @param string $type
+     * @throws \BitWasp\Bitcoin\Exceptions\RandomBytesFailure
+     */
+    public function getErcAddress()
+    {
+        $random = new Random();
+        $network = Bitcoin::getNetwork();
+        $privateKeyFactory = new PrivateKeyFactory();
+        $privateKey = $privateKeyFactory->generateCompressed($random);
+        $publicKey = $privateKey->getPublicKey();
+
+        // p2pkh 格式的地址
+        $addressService = new PayToPubKeyHashAddress($publicKey->getPubKeyHash());
+
+        // 将生成的钱包保存到数据库中
+        $wif = $privateKey->toWif($network);
+        $address = $addressService->getAddress();
+
+        return ['wif' => $wif, 'hexAddress' => $this->getHash16Address($address), 'address' => $address];
+    }
+
+
+    /**
+     * 获取HASH钱包地址
+     * @param $address 钱包地址
+     * @return \BitWasp\Buffertools\BufferInterface
+     * @throws \BitWasp\Bitcoin\Exceptions\UnrecognizedAddressException
+     */
+    public function getHexAddress($address)
+    {
+        $data = WitnessProgram::v0((new AddressCreator())->fromString($address)->getHash());
+        $buffer = $data->getProgram()->getHex();
+        return $buffer ? '0x' . $buffer : '';
+    }
+
+    /**
+     * 监听USDT-ERC2.0提币记录并进账(平台钱包)
+     * @param $address 用户钱包地址
+     * @param int $limit 转账记录数,最新的
+     * @return array|false
+     */
+    public function getErc20TransferLogByOtc($address, $limit = 50)
+    {
+        return false;
+
+        if (empty($address)) {
+            $this->error = '1013';
+            return false;
+        }
+
+        $url = sprintf($this->apiUrls['usdt_trx2_transfer_log'], $address, $limit, 'false', 'true');
+        $headers = ["TRON-PRO-API-KEY" => $this->config['tron_api_key']];
+        RedisService::set("caches:wallets:transfer_temp_otc", ['url' => $this->config['tron_api_url'] . $url], 600);
+
+    }
+
+    /**
+     * USDT-ERC20余额
+     * @param $address
+     * @return false|float|string
+     */
+    public function getErc20Usdt($address)
+    {
+        $cacheKey = "caches:wallet:balance:{$address}";
+        if (RedisService::get($cacheKey)) {
+            return false;
+        }
+
+        if (empty($address)) {
+            $this->error = '1018';
+            return false;
+        }
+
+        try {
+            return '0.00';
+
+        } catch (\Exception $exception) {
+            $this->error = $exception->getMessage();
+            return false;
+        }
+    }
+
+    /**
+     * 获取USDT-ERC2.0交易记录(进出账)
+     * @param $address 用户钱包地址
+     * @param int $coinType 币种:1-usdt
+     * @param int $limit 转账记录数,最新的
+     * @return array|false
+     */
+    public function getErc20TransferLog($address, $type = 1, $limit = 50)
+    {
+
+    }
+
+}

+ 0 - 147
app/Services/UsdtWalletService_back.php

@@ -1,147 +0,0 @@
-<?php
-// +----------------------------------------------------------------------
-// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
-// +----------------------------------------------------------------------
-// | 版权所有 2017~2021 LARAVEL研发中心
-// +----------------------------------------------------------------------
-// | 官方网站: http://www.laravel.cn
-// +----------------------------------------------------------------------
-// | Author: laravel开发员 <laravel.qq.com>
-// +----------------------------------------------------------------------
-
-namespace App\Services;
-
-use App\Models\MemberModel;
-use BitWasp\Bitcoin\Address\AddressCreator;
-use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
-use BitWasp\Bitcoin\Address\SegwitAddress;
-use BitWasp\Bitcoin\Bitcoin;
-use BitWasp\Bitcoin\Crypto\Random\Random;
-use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
-use BitWasp\Bitcoin\Network\NetworkInterface;
-use BitWasp\Bitcoin\Script\ScriptFactory;
-use BitWasp\Bitcoin\Script\WitnessProgram;
-use BitWasp\Bitcoin\Script\WitnessScript;
-use BitWasp\Buffertools\Buffer;
-use Web3\Web3;
-
-/**
- * USDT链管理-服务类
- * Class UsdtWalletService
- * @package App\Services
- */
-class UsdtWalletService extends BaseService
-{
-    protected $config = [];
-    protected $apiUrl = [];
-
-    /**
-     * 构造函数
-     * UsdtWalletService constructor.
-     */
-    public function __construct()
-    {
-        $this->config = ConfigService::make()->getConfigOptionByGroup(4);
-        $this->apiUrl = isset($this->config['usdt_api_url'])? $this->config['usdt_api_url'] : '';
-        if (empty($this->config) || empty($this->apiUrl)) {
-            return false;
-        }
-    }
-
-    /**
-     * 静态入口
-     * @return UsdtWalletService|null
-     */
-    public static function make()
-    {
-        return parent::make(); // TODO: Change the autogenerated stub
-    }
-
-
-    /**
-     * 获取钱包地址
-     * @param string $type
-     * @throws \BitWasp\Bitcoin\Exceptions\RandomBytesFailure
-     */
-    public function getWalletAddress($type = 'trc')
-    {
-        $random = new Random();
-        $network = Bitcoin::getNetwork();
-        $privateKeyFactory = new PrivateKeyFactory();
-        $privateKey = $privateKeyFactory->generateCompressed($random);
-        $publicKey = $privateKey->getPublicKey();
-
-        // p2pkh 格式的地址
-        $addressService = new PayToPubKeyHashAddress($publicKey->getPubKeyHash());
-
-        // 将生成的钱包保存到数据库中
-        $wif = $privateKey->toWif($network);
-        $address = $addressService->getAddress();
-
-        return ['wif'=> $wif, 'address'=> $address];
-    }
-
-    public function getWebAddress($label='1')
-    {
-        $web3 = new Web3();
-        $web3->personal->newAccount($label, function ($err, $account) use (&$newAccount) {
-            if ($err !== null) {
-                echo 'Error: ' . $err->getMessage();
-                return;
-            }
-            $newAccount = $account;
-            echo 'New account: ' . $account . PHP_EOL;
-        });
-    }
-
-    /**
-     * 获取HASH钱包地址
-     * @param $address 钱包地址
-     * @return \BitWasp\Buffertools\BufferInterface
-     * @throws \BitWasp\Bitcoin\Exceptions\UnrecognizedAddressException
-     */
-    public function getHash16Address($address)
-    {
-        $data = WitnessProgram::v0((new AddressCreator())->fromString($address)->getHash());
-        $buffer = $data->getProgram()->getHex();
-        return $buffer? '0x'.$buffer : '';
-    }
-
-    /**
-     * 创建交易参数
-     * @param $payWif
-     * @param $address
-     * @param $amount
-     * @param string $coin
-     * @throws \BitWasp\Bitcoin\Exceptions\Base58ChecksumFailure
-     * @throws \BitWasp\Bitcoin\Exceptions\InvalidPrivateKey
-     * @throws \BitWasp\Bitcoin\Exceptions\UnrecognizedAddressException
-     * @throws \BitWasp\Bitcoin\Exceptions\WitnessScriptException
-     * api: https://services.tokenview.com/vipapi/onchainwallet/{币种简称小写}?apikey={apikey}
-     */
-    public function createTrade($payAddress, $address, $amount, $coin='etc')
-    {
-        $data = [
-            'owner_address'=> $payAddress,
-            'to_address'=> $address,
-            'amount'=> $amount,
-            'method'=> 'createtransaction',
-            'visible'=> false,
-        ];
-        $this->apiUrl = $this->apiUrl."/onchainwallet/{$coin}?apikey=".$this->config['usdt_apikey'];
-        var_dump($data);
-        var_dump($this->apiUrl);
-        $result = curl_api($this->apiUrl, $data, ["Content-Type: application/json"]);
-
-        var_dump($result);
-    }
-
-    /**
-     * 广播交易上链
-     * api: https://services.tokenview.com/vipapi/onchainwallet/trx?apikey=R8UNuoal7yGtw32PlksD
-     */
-    public function broadcastTrade()
-    {
-
-    }
-}