瀏覽代碼

no message

BF-202205051124\Administrator 3 年之前
父節點
當前提交
9d3030db65
共有 3 個文件被更改,包括 598 次插入0 次删除
  1. 559 0
      app/Servers/BroadcastServer.php
  2. 12 0
      app/Servers/Icon/TronRPC.php
  3. 27 0
      app/Servers/PassServer.php

+ 559 - 0
app/Servers/BroadcastServer.php

@@ -0,0 +1,559 @@
+<?php
+
+
+namespace App\Servers;
+
+use App\Models\Broadcast;
+use App\Models\CoinTypes;
+use App\Models\Config;
+use App\Models\MemberCoins;
+use App\Models\Withdraw;
+use App\Servers\Eth\Utils;
+use Illuminate\Support\Facades\Log;
+use Web3p\EthereumTx\Transaction;
+
+
+/**
+ * 广播接口
+ */
+class BroadcastServer
+{
+
+    public static $type_str=[
+        1=>'BTC充值',
+        2=>'ETH充值',
+        3=>'USDT充值',
+        4=>'BTC提现',
+        5=>'ETH提现',
+        6=>'USDT提现',
+        7=>'ETH手续费',
+    ];
+
+
+
+    /**
+     * @param $eth_address ## 用户钱包地址
+     * @return bool|mixed|string|null
+     *
+     * 查询用户NYTR余额
+     */
+    public static function getUsdtNum($eth_address)
+    {
+        $eth = EthereumRPCServer::getInstance();
+        $tx = [];
+        $tx['from'] = $eth_address;                                 //用户地址
+//        $tx['to'] = config('muc.hy_address', '');   //系统钱包地址
+        $tx['to'] =Config::where('key','hy_address')->value('value');   //系统钱包地址
+        $tx['data'] = Utils::decodeSolMethod('balanceOf(address)', [$eth_address]);
+        $balance = $eth->call($tx);
+        $balance = Utils::hex2dec($balance);
+        $balance = Utils::int2fund($balance,6); // 18位小数
+        $balance = Utils::fund2int($balance, 2);
+        $balance = round($balance / 100, 2);
+        return $balance;
+    }
+
+
+    /**
+     * 获取ETH余额
+     * @param $eth_address ##用户钱包地址
+     * @return bool|mixed|string
+     */
+    public static function getEthNum($eth_address)
+    {
+        $eth = EthereumRPCServer::getInstance();
+        $eth_num = $eth->getBalance($eth_address);
+        $eth_num = Utils::hex2dec($eth_num);
+        $eth_num = Utils::int2fund($eth_num, 18);
+        return $eth_num;
+    }
+
+    /**
+     * 获取BTC数量
+     * @param $btc_address
+     * @return string
+     */
+    public static function getBtcNum($btc_address)
+    {
+        $btc = BtcereumRPCServer::getInstance();
+        $btc_num = $btc->bitcoinBalanceOfAddress($btc_address);
+        return $btc_num;
+    }
+
+
+    public static function addBroadcast($coin_id, $money, $from, $from_key, $to, $member_id, $order_id = 0, $status_type = 0, $from_id = 0, $status = 1)
+    {
+        //保留数量
+        $retain_num = CoinTypes::where('id', $coin_id)->value('retain_num');
+        $transaction = [
+            'depend' => 0,
+            'from' => $from,
+            'to' => $to,
+            'nonce' => '',
+            'coin_id' => $coin_id,
+            'value' => '0x0',
+            'data' => !empty($tx['data']) ? $tx['data'] : Utils::fixHex(bin2hex('NYT')),
+            'chain_id' => 0,
+            'gas_price' => '',
+            'gas_limit' => '',
+            'to_address' => $to,
+            'sign' => '',
+            'hash' => $status == 5 ? '系统内部转账,直接成功,无需链上广播' : '',
+            'from_key' => $from_key,
+            'money' =>$coin_id!=4? round($money - $retain_num,6):$money,
+            'status' => $status,
+            'type' => $status_type,
+            'm_id' => $member_id,
+            'order_id' => $order_id,
+//            'from_id' => $from_id,
+            'retain_num' => $retain_num,
+            'send_money' => $money,
+        ];
+        if ($coin_id == 1) {
+//            $btc = BtcereumRPCServer::getInstance();
+//            $feeAddressUXTO = $btc->listunspent(0, 999999, [$from]);
+//            if (empty($feeAddressUXTO)) {
+//                $transaction['error'] = "手续费地址uxto为空";
+//                $transaction['status'] = 4;
+//            } else {
+//                $inputs = [];
+//                foreach ($feeAddressUXTO as $item) {
+//                    $inputs[] = [
+//                        'txid' => $item['txid'],
+//                        'vout' => $item['vout'],
+//                    ];
+//                }
+//                $output = [$to => $transaction['money']];
+//                $rawtx = $btc->createrawtransaction($inputs, $output);
+//                if ($rawtx === false) {
+//                    $transaction['error'] = "创建裸交易失败";
+//                    $transaction['status'] = 4;
+//                } else {
+//                    $transaction['data'] = $rawtx;
+//                }
+//            }
+        } else {
+            $eth = EthereumRPCServer::getInstance();
+            $transaction['chain_id'] = $eth->chainId;
+            $depend = 0;
+            if ($coin_id == 4) {
+                $hy_address=Config::where('key','hy_address')->value('value');
+                $tx = static::build(
+                    $from,
+                    $hy_address,//系统钱包地址
+                    '0x0',
+                    Utils::decodeSolMethod(
+                        'transfer(address,uint256)',
+                        [$to, Utils::fund2int($money, 6)]
+//                        [$to, Utils::fund2int($money, 18)]
+                    )
+                );
+                $transaction['from'] = $tx['from'];
+                $transaction['to'] = $tx['to'];
+                $transaction['data'] = $tx['data'];
+                $my_eth = static::getEthNum($tx['from']);
+                if ($my_eth * 1 < 0.002) {
+                    $depend = static::withholdServiceCharge($tx, $member_id);
+                }
+            }else{
+                $transaction['value'] =Utils::dec2hex(Utils::fund2int($transaction['money'] * 1)); // 转账金额
+                $transaction['data'] =  '0x0';
+            }
+            $transaction['depend'] = $depend;
+//            $nonce = $eth->getTransactionCount($transaction['from']);
+//            $transaction['nonce'] = $nonce;//交易顺序十六进制。由eth_getTransactionCount获取
+//            $gas_price = $eth->getGasPrice();
+//            $transaction['gas_price'] = Utils::dec2hex(Utils::toWei("1gwei") + Utils::hex2dec($gas_price));//燃料十六进制。由eth_estimateGas获取
+//            $gas_limit = static::getGasLimit($transaction);
+//            $transaction['gas_limit'] = $gas_limit;
+            //写入数据库代码  $transaction
+        }
+        $transaction = Broadcast::create($transaction);
+//        //写入 返回成功
+        return $transaction->{'id'};
+    }
+
+
+    /**
+     * 导入广播
+     * @param $from
+     * @param $to
+     * @param $nonce
+     * @param $value
+     * @param $data
+     * @param $chain_id
+     * @param $gas_price
+     * @param $gas_limit
+     * @param $sign
+     * @param $hash
+     * @param $money
+     * @param $order_id
+     * @param $coin_id
+     * @param $status
+     * @return mixed
+     */
+    public static function addSysBroadcast($from, $to, $nonce, $value, $data, $chain_id, $gas_price, $gas_limit, $sign, $hash, $money, $order_id, $coin_id, $status)
+    {
+        $withdraws = Withdraw::where('id', $order_id)->first();
+        if (empty($withdraws)) {
+            Log::info('导入提现信息不存在,提现ID:' . $order_id);
+            return false;
+        }
+        if($withdraws->{'status'}!=1)return false;
+        $transaction_id = Broadcast::where('order_id', $order_id)->where('type', '2')->value('id');
+        //保留数量
+        $transaction = [
+            'depend' => 0,
+            'from' => $from,
+            'to' => $to,
+            'nonce' => $nonce,
+            'coin_id' => $coin_id,
+            'value' => $value,
+            'data' => $data,
+            'chain_id' => $chain_id,
+            'gas_price' => $gas_price,
+            'gas_limit' => $gas_limit,
+            'sign' => $sign,
+            'hash' => $hash,
+            'from_key' => '',
+            'money' => $money,
+            'status' => 3,
+            'type' => $status,
+            'm_id' => $withdraws->{'m_id'},
+            'order_id' => $order_id,
+            'created_at' => date('Y-m-d H:i:s'),
+            'updated_at' => date('Y-m-d H:i:s'),
+
+        ];
+        if (empty($transaction_id)) {
+            $transaction_id = Broadcast::insertGetId($transaction);
+        } else {
+            Broadcast::where('id', $transaction_id)->update($transaction);
+        }
+        Withdraw::where('id', $order_id)->update(['updated_at' => date('Y-m-d H:i:s'),'hash'=>$hash, 'status' => '2']);
+//        //写入 返回成功
+        return $transaction_id;
+    }
+
+    /**
+     * 广播签名
+     * @return bool
+     */
+    public static function signBroadcast()
+    {
+        $btc = BtcereumRPCServer::getInstance();
+        $list = Broadcast::where('status', '1')->select(['id', 'depend', 'chain_id', 'm_id', 'from', 'to', 'nonce', 'value', 'data', 'gas_price', 'gas_limit', 'sign', 'money', 'from_key', 'coin_id'])->groupBy('m_id')->limit(10)->get()->toArray();
+//        $service_money='4000000000000000';
+
+        // 手续费交易 转账0.0015个
+//        $serviceFee = Utils::dec2hex($service_money); // 手续费
+       
+        if (empty($list)) return false;
+        $sys_wei=Config::where('key','service_charge')->value('value');
+        $sys_wei=empty($sys_wei)?'15':$sys_wei;
+        $eth = EthereumRPCServer::getInstance();
+        foreach ($list as $value) {
+            $update_info = [];
+            $from_key = PassServer::getSecretKey($value['from_key'], $value['m_id']);
+            $send_num = Broadcast::whereIn('status', ['2'])->where('from', $value['from'])->count();
+            if ($send_num > 0) continue;
+            if ($value['depend']) {
+                $num = Broadcast::where('id', $value['depend'])->where('status', 5)->where('updated_at','<',date('Y-m-d H:i:s',time()-15))->count();
+                if ($num <= 0) continue;
+            }
+            if ($value['coin_id'] == 1) {
+                $feeAddressUXTO = $btc->listunspent(0, 999999, [$value['from']]);
+                if (empty($feeAddressUXTO)) {
+                    $update_info['error'] = "手续费地址uxto为空";
+                    $update_info['status'] = 4;
+                } else {
+                    $inputs = [];
+                    foreach ($feeAddressUXTO as $item) {
+                        $inputs[] = [
+                            'txid' => $item['txid'],
+                            'vout' => $item['vout'],
+                        ];
+                    }
+                    $output = [$value['to'] => $value['money']*1];
+                    $rawtx = $btc->createrawtransaction($inputs, $output);
+                    if ($rawtx === false) {
+                        $update_info['error'] = "创建裸交易失败";
+                        $update_info['status'] = 4;
+                    } else {
+                        $value['data'] = $rawtx;
+                        $privKeys[] = $from_key;
+                        $sign = $btc->signrawtransactionwithkey($value['data'], $privKeys,null);
+                        if ($sign === false) {
+                            $update_info['error'] = '签名失败';
+                            $update_info['status'] = 5;
+                        } else {
+                            $update_info['sign'] = $sign['hex'];
+                            $update_info['status'] = 2;
+                        }
+                    }
+                }
+            } else {
+				
+                if($value['coin_id']==4){
+                    $my_eth = static::getEthNum($value['from']);
+					//dd( $my_eth);
+                    if ($my_eth * 1 < 0.005) {
+                        $depend = static::withholdServiceCharge($value, $value['m_id']);
+                        Broadcast::where('id', $value['id'])->update(['depend' => $depend]);
+                        continue;
+                    }
+
+                }else{
+//                    $value['value'] =Utils::dec2hex(Utils::fund2int($value['money'] * 1)); // 转账金额
+                }
+                if(empty($value['nonce']) || true){
+                    $nonce = $eth->getTransactionCount($value['from']);
+                    //交易顺序十六进制。由eth_getTransactionCount获取
+
+                    $nonce_count = Broadcast::where('nonce', $nonce)->where('from',$value['from'])->where('id','<>', $value['id'])->count();
+                    if ($nonce_count >= 1) {
+                        continue;
+//                    $nonce=Utils::dec2hex(Utils::hex2dec($nonce) + 1);
+                    }
+                    $value['nonce'] = $nonce;
+                }
+
+                $gas_price = $eth->getGasPrice();
+				
+                $value['gas_price'] =  Utils::dec2hex(Utils::toWei($sys_wei."gwei") + Utils::hex2dec($gas_price));//燃料十六进制。由eth_estimateGas获取
+//                $value['gas_price'] = $gas_price;//燃料十六进制。由eth_estimateGas获取
+                $gas_limit = static::getGasLimit($value);
+                $value['gas_limit'] = $gas_limit;
+                $sign = static::sign($value, $from_key);          //交易签名
+				 
+                if ($sign === false) {
+                    $update_info['error'] = '签名失败';
+                    $update_info['status'] = 4;
+                } else {
+                    $update_info['sign'] = $sign;
+                    $update_info['status'] = 2;
+                    $update_info['nonce'] = $value['nonce'];
+                    $update_info['gas_limit'] = $value['gas_limit'];
+                    $update_info['gas_price'] = $value['gas_price'];
+                }
+            }
+            Broadcast::where('id', $value['id'])->update($update_info);
+            sleep(5);
+        }
+        return true;
+    }
+
+    /**
+     * 广播交易
+     * @return bool
+     */
+    public static function sendBroadcast()
+    {
+        $btc = BtcereumRPCServer::getInstance();
+        $eth = EthereumRPCServer::getInstance();
+        $list = Broadcast::where('status', '2')->select(['id', 'm_id', 'from', 'to', 'nonce', 'value', 'data', 'gas_price', 'gas_limit', 'sign', 'money', 'from_key', 'coin_id'])->limit(10)->get()->toArray();
+        if (empty($list)) return false;
+        foreach ($list as $value) {
+            $update_info = [];
+            if ($value['coin_id'] == 1) {
+                $txid = $btc->sendrawtransaction($value['sign']);
+                if ($txid == false) {
+                    $update_info['error'] = '广播失败';
+                    $update_info['status'] = 4;
+                } else {
+                    $update_info['hash'] = $txid;
+                    $update_info['status'] = 3;
+                }
+            } else {
+                $hash = $eth->sendRawTransaction($value['sign'], $error);//广播交易
+                if ($hash == false) {
+                    $update_info['error'] = json_encode($error);
+                    $update_info['status'] = 4;
+                } else {
+                    $update_info['hash'] = $hash;
+                    $update_info['status'] = 3;
+                }
+            }
+            Broadcast::where('id', $value['id'])->update($update_info);
+        }
+        return true;
+    }
+
+    /**
+     * 广播查询
+     */
+    public static function getBroadcast(){
+        $btc = BtcereumRPCServer::getInstance();
+        $eth = EthereumRPCServer::getInstance();
+        $list = Broadcast::where('status', '3')->select(['id', 'm_id', 'from', 'to', 'send_money', 'value', 'coin_id', 'type', 'sign', 'money', 'from_key', 'coin_id','hash','send_money','order_id'])->limit(10)->get()->toArray();
+        if (empty($list)) return false;
+        foreach ($list as $value) {
+            $update_info = [];
+            if ($value['coin_id'] == 1) {
+                $deal_info=$btc->getrawtransaction ($value['hash'],true);
+                if(empty($deal_info['confirmations']) || $deal_info['confirmations'] <=3){
+                    continue;
+                }else{
+                    $update_info['success'] = json_encode($deal_info);
+                    $update_info['status'] = 5;
+                }
+            } else {
+                $receipt = $eth->getTransactionReceipt($value['hash']);//交易查询
+                if (empty($receipt)) {
+                    //交易正在广播中,下次继续查询
+                    continue;
+                } else {
+                    //交易已完成 返回数据格式数据 ,将数据json保存
+                    if ($receipt['status'] != '0x1') {
+                        $update_info['error'] = json_encode($receipt);
+                        $update_info['status'] = 4;
+                    }else{
+                        $update_info['success'] = json_encode($receipt);
+                        $update_info['status'] = 5;
+                    }
+
+                }
+            }
+            if(!empty($update_info)){
+                Broadcast::where('id', $value['id'])->update($update_info);
+                if($update_info['status']==5){
+                    //广播成功,增加会员余额
+                    if($value['type']<=3){
+                        $member_coin= MemberCoins::where('m_id',$value['m_id'])->where('coin_id',$value['coin_id'])->select(['id','coin_name','coin_id','num','m_id'])->first();
+                        MemberCoins::where('id',$member_coin->{'id'})->update(['num'=>$member_coin->{'num'}+$value['send_money']]);
+                        MoneyDetailServer::write($member_coin['coin_id'], MoneyDetailServer::$status['coin_recharge'], $value['send_money'], MoneyDetailServer::$add_reduce['add'], $member_coin->{'m_id'}, $member_coin->{'mobile'}, '充币' .$value['send_money'] .''. $member_coin->{'coin_name'}, '', $value['id'], $member_coin->{'num'}, 'Recharge ' . $member_coin->{'money'} . $member_coin->{'coin_name'});
+                    }elseif($value['type']<=6){
+                        $withdraws = Withdraw::where('id', $value['order_id'])->where('m_id', $value['m_id'])->first();
+                        if (!empty($withdraws)) {
+                            Withdraw::where('id', $value['order_id'])->update([ 'status' => '3']);
+                            $member_coin = MemberCoins::where('m_id', $value['m_id'])->where('coin_id', $value['coin_id'])->select(['id', 'coin_name', 'coin_id', 'num', 'm_id','lock_num'])->first();
+                            $lock_num = $member_coin->{'lock_num'} - $withdraws->{'money'};
+                            if ($lock_num < 0) $lock_num = 0;
+                            MemberCoins::where('id', $member_coin->{'id'})->update(['lock_num' => $lock_num]);
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 系统手续费转账
+     * @param $tx
+     * @param $member_id
+     * @return mixed
+     */
+    public static function withholdServiceCharge($tx, $member_id)
+    {
+        $eth = EthereumRPCServer::getInstance();
+        $gasPrice = $eth->getGasPrice(); // 手续费
+        $cb_address = Config::where('key', 'cb_address')->value('value');
+        $address_key = Config::where('key', 'address_key')->value('value');
+        $sys_wei=Config::where('key','service_charge')->value('value');
+        $service_money=Config::where('key','service_money')->value('value');
+        $sys_wei=empty($sys_wei)?'15':$sys_wei;
+        $service_money=empty($service_money)?'3000000000000000':$service_money;
+        $tx = [
+            'from' => $cb_address,
+            'to' => $tx['from'],
+            'value' => '0x0',
+            'data' => $tx['data'],
+        ];
+        $gasLimit = $eth->estimateGas($tx);
+        // 手续费交易 转账0.0015个
+        $serviceFee = Utils::dec2hex($service_money); // 手续费
+        // 广播手续费
+        $transaction = [
+            'depend' => 0,
+            'from' => $cb_address,
+            'to' => $tx['to'],
+            'nonce' => '',
+            'value' => $serviceFee,//转账0.004个
+            'data' => '0x0',
+            'money' => round($service_money/1000000000000000000,6),
+            'gas_limit' => $gasLimit,
+            'chain_id' => $eth->chainId,
+            'gas_price' => '',
+            'to_address' => $tx['to'],
+            'coin_id' => 2,
+            'sign' => '',
+            'hash' => '',
+            'from_key' => $address_key,//系统支付秘钥
+            'status' => 1,//系统支付秘钥
+            'type' => 7,//系统支付秘钥
+            'm_id' => 0,
+            'send_money' => round($service_money/1000000000000000000,6),
+        ];
+        $nonce = $eth->getTransactionCount($transaction['from']);
+        $transaction['nonce'] = $nonce;//交易顺序十六进制。由eth_getTransactionCount获取
+        $transaction['gas_price'] = Utils::dec2hex(Utils::toWei($sys_wei."gwei") + Utils::hex2dec($gasPrice));//燃料十六进制。由eth_estimateGas获取
+        $transaction['gas_limit'] = $gasLimit;
+        //写入数据库代码  $transaction
+        $nytr = Broadcast::create($transaction);
+        return $nytr->{'id'};
+    }
+
+
+    /**
+     * 转账内容拼接
+     * @param $from
+     * @param $to
+     * @param $value
+     * @param $data
+     * @return array
+     * @throws
+     */
+    protected static function build($from, $to, $value, $data)
+    {
+        $tx = [];
+        $tx['from'] = $from;
+        $tx['to'] = $to;
+        $tx['value'] = $value;
+        $tx['data'] = $data;
+
+        return $tx;
+    }
+
+    /**
+     * @param  $transaction
+     * @return string
+     */
+    public static function getGasLimit($transaction)
+    {
+        $tx = [
+            'from' => $transaction['from'],
+            'to' => $transaction['to'],
+            'nonce' => $transaction['nonce'],
+            'value' => $transaction['value'],
+            'data' => $transaction['data'],
+            'chainId' => 1,
+            'gasPrice' => $transaction['gas_price'],
+        ];
+        $eth = EthereumRPCServer::getInstance();
+        $gasLimit = $eth->estimateGas($tx);
+        if (!$gasLimit) {
+            $gasLimit = 10 * 10000; // 预估失败, 最高10万
+        }
+        return $gasLimit;
+    }
+
+    protected static function sign($transaction, $key)
+    {
+        $tx = [
+            'from' => $transaction['from'],
+            'to' => $transaction['to'],
+            'nonce' => $transaction['nonce'],
+            'value' => $transaction['value'],
+            'data' => $transaction['data'],
+            'chainId' => $transaction['chain_id'],
+            'gasPrice' => $transaction['gas_price'],
+            'gasLimit' => $transaction['gas_limit'],
+        ];
+        // 数据签名
+
+        $tr = new Transaction($tx);
+        $tr->sign($key);
+        return Utils::fixHex($tr->serialize()->toString('hex'));
+    }
+}

+ 12 - 0
app/Servers/Icon/TronRPC.php

@@ -116,6 +116,18 @@ class TronRPC
         return $generateAddress->getRawData();
     }
 
+
+    /**
+     * 获取Base58地址
+     * @param $str
+     * @return string
+     */
+    function getBase58CheckAddress($str){
+        $new_str = $this->getTron()->getBase58CheckAddress($str);
+        return $new_str;
+    }
+
+
     /**
      * 获取TRX数量
      * @param $address

+ 27 - 0
app/Servers/PassServer.php

@@ -154,4 +154,31 @@ class PassServer
     }
 
 
+
+    public static function setSecretKey($private_key, $key_num = 0)
+    {
+        $key_num = $key_num % 20;
+        if ($key_num == 0) $key_num = 15;
+        $private_one = substr($private_key, 0, $key_num);
+        $private_two = substr($private_key, $key_num, 5);
+        $private_three = substr($private_key, $key_num + 5);
+        $new_private = $private_three . $private_one . $private_two;
+        return $new_private;
+    }
+
+    public static function getSecretKey($private_key, $key_num = 0)
+    {
+        $key_num = $key_num % 20;
+        if ($key_num == 0) $key_num = 15;
+        $private_length = strlen($private_key);
+        $three_length = $private_length - $key_num - 5;
+        $private_three = substr($private_key, 0, $three_length);
+        $private_two = substr($private_key, -5);
+        $private_one = substr($private_key, $three_length, $key_num);
+        $new_private = $private_one . $private_two . $private_three;
+        return $new_private;
+    }
+
+
+
 }