60, //1分钟 '5min'=>300,//5分钟 '15min'=>900,//15分钟 '30min'=>1800,//30分钟 '60min'=>3600,//1小时 '1day'=>86400,//1天 '1week'=>604800,//1周 '1mon'=>2592000, //1月 //'1year'=>31536000, //1年 ]; private $time_lists = ['1min','5min','15min','30min','1day','1week','1mon']; private $symbol_list = ['market.btcusdt.trade.detail',]; private $all_cons = []; private $all_symbols = ['btcusdt','ethusdt','ltcusdt','bchusdt','eosusdt']; //private $all_dic = []; private $testip = array("192.168.10.234", "192.168.230.1"); private $huobi_id = 0;//连接火币服务器的连接id,防止心跳把火币连接关闭 private $reconnect_num = 0;//与火币服务器的重连次数,超过一定次数重启Worker,目前是10次,windows下无法重启 private $async_message_time = 0;//与火币服务器的消息交互时间,超过一定时间没有消息往来重启Worker,目前是300s,windows下无法重启 public function index() { // 创建一个Worker监听2345端口,使用http协议通讯 $this->worker = new Worker("websocket://0.0.0.0:8686"); $info = "启动Worker-start:".date('Y-m-d H:i:s'); echo "\r\n ".$info; $this->saveLog("huobi", $info); $this->ctrl = []; $this->historykline = []; // 启动1个进程对外提供服务 $this->worker->count = 1; $this->worker->name = 'huobikline'; $this->worker->onWorkerStart = function($worker) { $this->onWorkerStart($worker); }; $this->huobiflag = false; $this->userdy = []; // 接收到浏览器发送的数据时回复hello world给浏览器 $this->worker->onMessage = function($connection, $data) { $this->onWorkerMessage($connection, $data); }; Worker::runAll(); } function onWorkerStart($worker) { $info = "启动Worker-start success:".date('Y-m-d H:i:s'); echo "\r\n ".$info; $this->saveLog("huobi", $info); // 进程启动后设置一个每秒运行一次的定时器 Timer::add(1, function()use($worker){ $time_now = time(); if(count($worker->connections) > 0) { $this->saveLog("all", '心跳计时器,count:' . count($worker->connections)); } foreach($worker->connections as $connection) { if ($connection->id == $this->huobi_id) { $this->saveLog("all", '心跳计时器,huobi_id:'.$this->huobi_id); continue; } // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间 if (empty($connection->lastMessageTime)) { $connection->lastMessageTime = $time_now; continue; } // 上次通讯时间间隔大于心跳间隔*2,则认为客户端已经下线,关闭连接 if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME * 2) { $this->saveLog("all", '心跳计时器,心跳超时,cid:'.$connection->id.',now:'.date('Y-m-d H:i:s', $time_now).',lastMessageTime:'.date('Y-m-d H:i:s', $connection->lastMessageTime)); $connection->close(); //unset($this->all_cons[$connection->id]); } } // if ($this->reconnect_num >= 10) {//与火币的连接断开重连超过10次,重启Worker // $info = "与火币的连接断开重连超过10次,重启Worker:".date('Y-m-d H:i:s'); // echo "\r\n".$info; // $this->saveLog("huobi", $info); // Worker::stopAll(); // } // if ($time_now - $this->async_message_time > 300) { // $info = "与火币的连接超过300s没有消息交互,重启Worker:".date('Y-m-d H:i:s'); // echo "\r\n".$info; // $this->saveLog("huobi", $info); // Worker::stopAll(); // } //查询控制价格是否有值 $ctrl = Db::name('hb_ctrl') ->where('ts','>=',(time() - 10)) ->select(); if($ctrl) { $this->ctrl = []; foreach ($ctrl as $key=>$value) { $this->ctrl[$value['symbol']][$value['ts']] = $value['price']; } $this->saveLog("all", '调控价格:'.json_encode($this->ctrl)); }else{ $this->ctrl = []; } }); // 异步建立一个到火币服务器的连接 $con = new AsyncTcpConnection($this->host); $this->cons = $con; if ($this->flag) {//正式环境 $con->transport = 'ssl'; } $this->onAsyncConnect($con); // 当服务器连接发来数据时,转发给对应客户端的连接 $con->onMessage = function($con, $message) use($worker) { $this->onAsyncMessage($con, $message, $worker); }; $con->onError = function($con, $err_code, $err_msg) { // var_dump(6); echo "$err_code, $err_msg"; $info = "Async onError err_code:{$err_code},err_msg:{$err_msg}"; echo "\r\n ".$info; $this->saveLog("huobi", $info); }; $con->onClose = function($con) { $this->saveLog("huobi", '火币连接断开,正在重连'); // 如果连接断开,则在1秒后重连 $this->onWorkerStart($this->worker); $con->reConnect(1); }; $con->connect(); //var_dump(1); } function onWorkerMessage($connection, $data) { // 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间 $connection->lastMessageTime = time(); $data = json_decode($data, true); $connection->lastMessageTime = time(); if(isset($data['pong'])) {//客户端返回心跳pong $connection->send(json_encode(array('pong success'))); } // else if($data['subs'] == 'history'){ // $result = json_decode($this->http_curl("http://149apis.ms2722.com/api/index/get_huobi","post",['url'=> // 'https://api.huobi.pro/market/history/kline?period='.$data['period'].'&size='.$data['size'].'&symbol='.$data['symbol']]),true); // $result = $result['data']; // $result['subs'] = 'history'; // $klines = $result['data']; // $last_names = array_column($klines,'id'); // array_multisort($last_names,SORT_ASC,$klines); // $result['data'] = $klines; // $connection->send(json_encode($result)); // $info = "\r\n cid ".$connection->id."订阅K线历史".json_encode($data);//."--".json_encode($result); // echo $info; // $this->saveLog("all", $info); // } else if($data['subs'] == 'history') { $from = time() - $this->time_list[$data['period']] * $data['size']; $to = time(); $datas = [ 'req' => "market.".$data['symbol'].".kline.".$data['period'], 'id' => 'id'.time(), 'from' => $from, 'to' => $to ]; $this->historykline[$datas['id']] = $connection->id; $this->cons->send(json_encode($datas)); $info = "\r\n cid ".$connection->id."订阅K线历史".json_encode($data);//."--".json_encode($result); echo $info; $this->saveLog("all", $info); }else if($data['subs'] == 'tradenow'){ if(isset($data['sub'])) { $this->userdy[$data['sub']][] = $connection->id; } if(isset($data['unsub'])) { $keys = array_search($connection->id, $this->userdy[$data['unsub']]); if($keys>=0) unset($this->userdy[$data['unsub']][$keys]); } // var_dump($data); $info = "\r\n cid ".$connection->id."订阅k线数据".json_encode($data); echo $info; $this->saveLog("all", $info); }else if($data['subs'] == 'start_order'){ //下单 if(isset($data['times'])) { var_dump('---' . date('Y-m-d H:i:s') . '---' . $data['times']); } $result = $this->start_order($data); $result['type'] = 'start_order'; $result['subs'] = 'start_order'; $connection->send(json_encode($result)); $info = "\r\n cid ".$connection->id."下单周期:".json_encode($data).'--'.date('Y-m-d H:i:s'); echo $info; $this->saveLog("all", $info); }else if($data['subs'] == 'get_profit_order') //获取盈利订单 { $result = $this->get_profit_order($data); $result['subs'] = $data['subs']; $connection->send(json_encode($result)); }else if($data['subs'] == 'get_cycle_coin') //获取支持周期的币种 { $result = $this->get_cycle_coin($data); $result['subs'] = $data['subs']; $connection->send(json_encode($result)); }else if($data['subs'] == 'get_order') //获取持仓订单 { $result = $this->get_order($data); $result['subs'] = $data['subs']; $connection->send(json_encode($result)); }else if($data['subs'] == 'get_all_order') //获取全部订单 { $result = $this->get_all_order($data); $result['subs'] = $data['subs']; $connection->send(json_encode($result)); }else if($data['subs'] == 'cancel_order') //5秒取消 { $result = $this->cancel_order($data); $result['subs'] = $data['subs']; $connection->send(json_encode($result)); } } /** * * @param type $url * @param type $type * @param type $arr * @return type */ function http_curl($url, $type = 'get', $arr = '') { if($arr){ $o = ""; foreach ( $arr as $k => $v ) { $o.= "$k=" . urlencode( $v ). "&" ; } $arr = substr($o,0,-1); } $ch = curl_init(); $user_agent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"; curl_setopt($ch, CURLOPT_USERAGENT,$user_agent); curl_setopt($ch, CURLOPT_URL, $url); //设置访问的地址 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //获取的信息返回 // curl_setopt($ch, CURLOPT_PROXY, "hk2.cable-modem.org"); //代理服务器地址 // curl_setopt($ch, CURLOPT_PROXYPORT,"46543"); //代理服务器端口 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_TIMEOUT, 20000); if ($type == 'post') { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $arr); } $output = curl_exec($ch); if (curl_error($ch)) { return curl_error($ch); } return $output; } function onAsyncConnect($con) { $this->async_message_time = time(); $this->huobi_id = $con->id; foreach ($this->all_symbols as $key=>$value) { foreach ($this->time_lists as $k=>$val) { $data = [ 'sub' => "market.".$value.".kline.".$val, "id" => "id".time(), ]; $this->userdy[$data['sub']] = []; $this->saveLog("all", '异步连接火币,订阅:'.$data['sub'].'-'.json_encode($this->userdy)); $con->send(json_encode($data)); } } } function onAsyncMessage($con, $message, $worker) { $data = json_decode($message, true); if (!$data) {//说明采用了GZIP压缩 $data = gzdecode($message); // $this->saveLog("huobi", $data); $data = json_decode($data, true); } else { $this->saveLog("huobi", $message); } // var_dump($data); if(isset($data['ping'])) { $this->async_message_time = time(); $con->send(json_encode([ "pong" => $data['ping'] ])); foreach($worker->connections as $connection) { $connection->send(json_encode($data)); } }else if (isset($data['ch'])) { $this->async_message_time = time(); $data['subs'] = 'tradenow'; // echo "
";
//            var_dump($this->userdy);
            if(strpos($data['ch'],'btcusdt') !== false) $symbol = 'btcusdt';
            else if(strpos($data['ch'],'ethusdt') !== false) $symbol = 'ethusdt';
            else if(strpos($data['ch'],'ltcusdt') !== false) $symbol = 'ltcusdt';
            else if(strpos($data['ch'],'bchusdt') !== false) $symbol = 'bchusdt';
            else if(strpos($data['ch'],'eosusdt') !== false) $symbol = 'eosusdt';
            else $symbol = '';
            if($symbol && $this->ctrl && isset($this->ctrl[$symbol]) && isset($this->ctrl[$symbol][time()]))
            {
                $data['tick']['close'] = (float)sprintf("%.2f",$this->ctrl[$symbol][time()]);
                $this->saveLog("all", '调控数据推送:'.json_encode($data));
            }
            foreach ($this->userdy[$data['ch']] as $key=>$value)
            {
                if(!isset($worker->connections[$value]))
                {
                    unset($this->userdy[$data['ch']][$key]);
                }else {
                    $worker->connections[$value]->send(json_encode($data));
                }
            }
        }else if (isset($data['rep'])){
            $data['subs'] = 'history';
            $data['ch'] = $data['rep'];
            $worker->connections[$this->historykline[$data['id']]]->send(json_encode($data));
        }
    }

    function saveLog($symbol, $msg){
        $dir =  __DIR__ ."/logs";
        if( !file_exists($dir) ) mkdir($dir, 0777);
        $today = date('Ymd');
        $file_path =$dir."/a-".$symbol."-".$today.".log";
        $handle = fopen($file_path, "a+");
        @fwrite($handle, date("H:i:s"). $msg . "\r\n");
        @fclose($handle);
    }

    //开始下单
    public function start_order($params)
    {
        $times = time();  //-691200
        if(isset($params['times']) && ($times - $params['times']) < 5) $times = $params['times'];
        $config = \think\Config::get('token');
        $tokens =  hash_hmac($config['hashalgo'], $params['token'], $config['key']);
        $auth = Db::name('user_token')->where('token',$tokens)->find();
        if(!$auth)
        {
            return ['code'=>0,'msg'=>'登录失效','time'=>time(),'data'=>''];
        }
        if(!isset($params['symbol']) || empty($params['symbol']))
        {
            return ['code'=>0,'msg'=>'请选择交易对','time'=>time(),'data'=>''];
        }
        if(!isset($params['num']) || empty($params['num']) || !is_numeric($params['num']) || $params['num']<=0)
        {
            return ['code'=>0,'msg'=>'请输入正确的交易数量','time'=>time(),'data'=>''];
        }
        if(!isset($params['cycle']) || empty($params['cycle']))
        {
            return ['code'=>0,'msg'=>'请选择交易周期','time'=>time(),'data'=>''];
        }
        if(!isset($params['position']) || empty($params['position']))
        {
            return ['code'=>0,'msg'=>'请选择交易涨跌','time'=>time(),'data'=>''];
        }
        //周期信息
        $symbol = Db::name('app_cycleset')
            ->where('symbol',$params['symbol'])
            ->find();
        if(!$symbol){
            return ['code'=>0,'msg'=>'交易对不存在','time'=>time(),'data'=>''];
        }

        $cycletime = explode(',',$symbol['trade_time']);
        if(!in_array($params['cycle'],$cycletime)){
            return ['code'=>0,'msg'=>'交易周期错误','time'=>time(),'data'=>''];
        }

        $cyclejson = json_decode($symbol['cyclejson'],true);
        $hour = date('H');
        $min = date('i');
        $winpl = 0;
        foreach ($cyclejson as $key=>$value)
        {
            $cycletime = explode('-', $key);
            $cycletime1 = explode(":", $cycletime[0]);
            $cycletime2 = explode(":", $cycletime[1]);
//                var_dump($cycletime,$cycletime1,$cycletime2,$hour,$min);exit;
            if($hour >= (int)$cycletime1[0] && $min >= (int)$cycletime1[1] && $hour< (int)$cycletime2[0])
            {
                $winpl = $value;
                break;
            }
        }
        $lostjson = json_decode($symbol['lostjson'],true);
        $lostpl = 0;
        foreach ($lostjson as $key=>$value)
        {
            $cycletime = explode('-', $key);
            $cycletime1 = explode(":", $cycletime[0]);
            $cycletime2 = explode(":", $cycletime[1]);
//                var_dump($cycletime,$cycletime1,$cycletime2,$hour,$min);exit;
            if($hour >= (int)$cycletime1[0] && $min >= (int)$cycletime1[1] && $hour< (int)$cycletime2[0])
            {
                $lostpl = $value;
                break;
            }
        }
        $tablename = 'hb_1s_'.str_replace('usdt','',$params['symbol']);
        for($i=1;$i<=10;$i++) {
            $current_price = Db::name($tablename)
                ->where('ts', $times)
                ->order('ts', 'desc')->find();
            if($current_price){
                break;
            }
        }
        if(!$current_price)
        {
            $current_price = Db::name($tablename)
                ->where('ts',"<=", $times)
                ->order('ts', 'desc')->find();
        }
//        var_dump($current_price,date('Y-m-d H:i:s',$current_price['ts']),date('Y-m-d H:i:s',$times),$i);exit;
        //redis防重复点击
        $symbol = "order" . $auth['user_id'];
        $submited = pushRedis($symbol);
        if (!$submited) {
            return ['code'=>0,'msg'=>'操作频繁','time'=>time(),'data'=>''];
        }

        $currency = Db::name('app_currency_user')
            ->field('num,id')
            ->where('user_id',$auth['user_id'])
            ->where('curr_id',1)->find();
        if($currency['num'] < $params['num'])
        {
            lopRedis($symbol);
            return ['code'=>0,'msg'=>'账号余额不足','time'=>time(),'data'=>''];
        }
        //下单数据
        $order = [
            'serial_no' => time().Random::build('numeric',8),
            'user_id' => $auth['user_id'],
            'createtime' => $times,
            'symbol' => $params['symbol'],
            'trade_num' => $params['num'],
            'trade_cycle' => $params['cycle'],
            'expect_percent' => $winpl,
            'expect_income' => sprintf("%.2f",$params['num']*$winpl),
            'lose_percent' => $lostpl,
            'lose_income' => sprintf('%.2f',$params['num']*$lostpl),
            'current_price' => $current_price['price'],
            'rise_or_fall' => $params['position'],
            'open_time' => $times+$params['cycle']
        ];
        $lostnum = $currency['num'] - $params['num'];
        //收支记录
        $detailed = [
            'user_id' => $auth['user_id'],
            'curr_id' => 1,
            'price' => $params['num'],
            'cart' => '2',
            'type' => '3',
            'serial_no' => $order['serial_no'],
            'order_result' => 'process',
            'description' => '周期持仓',
            'createtime' => $times,
            'notice' => '周期持仓',
            'before_num' => $currency['num'],
            'after_num' => $lostnum,
        ];
        Db::startTrans();
        try {
            $ret = Db::name('app_currency_user')
                ->where('id',$currency['id'])->update(['num'=>$lostnum,'updatetime'=>time()]);
            if(!$ret)
            {
                lopRedis($symbol);
                Db::rollback();
                return ['code'=>0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
            }
            $ret1 = Db::name('order')->insertGetId($order);
            if(!$ret1)
            {
                lopRedis($symbol);
                Db::rollback();
                return ['code'=>0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
            }
            $ret2 = Db::name('app_detailed')->insert($detailed);
            if(!$ret2)
            {
                lopRedis($symbol);
                Db::rollback();
                return ['code'=>0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
            }
            lopRedis($symbol);
            Db::commit();
            $return = $order;
            $return['current_price'] = sprintf("%.2f",$return['current_price']);
            $return['trade_num'] = sprintf("%.2f",$return['trade_num']);
            $return['id'] = $ret1;
            $return['nowtime'] = time();
            $return['show_name'] = strtoupper(str_replace('usdt','',$return['symbol'])).'/USDT';
            return ['code'=>1,'msg'=>'提交成功','time'=>time(),'data'=>$return];
        } catch (Exception $e) {
            Db::rollback();
            return ['code'=>0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
        }
    }


    //获取盈利订单
    public function get_profit_order($params)
    {
        $size = (isset($params['size']))?$params['size']:20;
        $symbol = (!isset($params['symbol']))?'btcusdt':$params['symbol'];
        $data = Db::name('his_order')
            ->field('createtime,symbol,trade_result_num,rise_or_fall,close_price as price')
            ->where('symbol',$symbol)
            ->where('trade_result','win')
            ->order('id','desc')
            ->paginate($size,false,['query' => request()->param()]);
        foreach ($data as $key=>$value)
        {
            $value['trade_result_num'] = sprintf('%.2f',$value['trade_result_num']);
            $value['createtime'] = date('m-d H:i',$value['createtime']);
            $data[$key] = $value;
        }
        return ['code' => 1,'msg'=>'success','time'=>time(),'data'=>$data];
    }

    //获取支持周期的币种
    public function get_cycle_coin($params)
    {
        $config = \think\Config::get('token');
        $tokens =  hash_hmac($config['hashalgo'], $params['token'], $config['key']);
        $auth = Db::name('user_token')->where('token',$tokens)->find();
        if(!$auth)
        {
            return ['code'=>0,'msg'=>'登录失效','time'=>time(),'data'=>''];
        }
        if(isset($params['id']) && !empty($params['id']))
        {
            $data = Db::name('app_cycleset')
                ->where('id',$params['id'])
                ->find();
            $hour = date('H');
            $min = date('i');
            $data['cyclejson'] = json_decode($data['cyclejson'], true);
            $data['lostjson'] = json_decode($data['lostjson'], true);
            $data['trade_time'] = explode(',', $data['trade_time']);
            $winpl = 0;
            $usdt = Db::name('app_currency_user')
                ->field('num')
                ->where('user_id',$auth['user_id'])
                ->where('curr_id',1)->find();
            $data['usdt'] = $usdt['num'];
            $data['nowtime'] = time();
            foreach ($data['cyclejson'] as $key=>$value)
            {
                $cycletime = explode('-', $key);
                $cycletime1 = explode(":", $cycletime[0]);
                $cycletime2 = explode(":", $cycletime[1]);
//                var_dump($cycletime,$cycletime1,$cycletime2,$hour,$min);exit;
                if($hour >= (int)$cycletime1[0] && $min >= (int)$cycletime1[1] && $hour< (int)$cycletime2[0])
                {
                    $winpl = $value;
                    break;
                }

            }
            $data['winpl'] = $winpl;
            $data['exchange_rate'] = Config::get('site.exchange_rate');
        }else {
            $data = Db::name('app_cycleset a')
                ->field('a.*,b.high,b.low,b.open,b.close,b.increase')
                ->join('app_rate b','a.curr_id=b.id','left')
                ->order('curr_id','asc')
                ->select();
            foreach ($data as $key => $value) {
                if($value['symbol'] == 'btcusdt')
                {
                    $coindata = Db::name('hb_1s_btc')->order('ts','desc')
                        ->find();
                    $value['close'] = $coindata['price'];
                }else if($value['symbol'] == 'ethusdt')
                {
                    $coindata = Db::name('hb_1s_eth')->order('ts','desc')
                        ->find();
                    $value['close'] = $coindata['price'];
                }
                else if($value['symbol'] == 'bchusdt')
                {
                    $coindata = Db::name('hb_1s_bch')->order('ts','desc')
                        ->find();
                    $value['close'] = $coindata['price'];
                }
                else if($value['symbol'] == 'ltcusdt')
                {
                    $coindata = Db::name('hb_1s_ltc')->order('ts','desc')
                        ->find();
                    $value['close'] = $coindata['price'];
                }
                else if($value['symbol'] == 'eosusdt')
                {
                    $coindata = Db::name('hb_1s_eos')->order('ts','desc')
                        ->find();
                    $value['close'] = $coindata['price'];
                }
                $value['cyclejson'] = json_decode($value['cyclejson'], true);
                $value['lostjson'] = json_decode($value['lostjson'], true);
                $value['trade_time'] = explode(',', $value['trade_time']);
                if($value['symbol'] == 'eosusdt') {
                    $value['high'] = sprintf('%.4f',$value['high']);
                    $value['low'] = sprintf('%.4f',$value['low']);
                    $value['open'] = sprintf('%.4f',$value['open']);
                    $value['close'] = sprintf('%.4f', $value['close']);
                }else{
                    $value['high'] = sprintf('%.2f',$value['high']);
                    $value['low'] = sprintf('%.2f',$value['low']);
                    $value['open'] = sprintf('%.2f',$value['open']);
                    $value['close'] = sprintf('%.2f', $value['close']);
                }
                $hour = date('H');
                $min = date('i');
                $winpl = 0;
                $usdt = Db::name('app_currency_user')
                    ->field('num')
                    ->where('user_id',$auth['user_id'])
                    ->where('curr_id',1)->find();
                $value['usdt'] = $usdt['num'];
                foreach ($value['cyclejson'] as $k=>$val)
                {
                    $cycletime = explode('-', $k);
                    $cycletime1 = explode(":", $cycletime[0]);
                    $cycletime2 = explode(":", $cycletime[1]);
//                var_dump($cycletime,$cycletime1,$cycletime2,$hour,$min);exit;
                    if($hour >= (int)$cycletime1[0] && $min >= (int)$cycletime1[1] && $hour< (int)$cycletime2[0])
                    {
                        $winpl = $val;
                        break;
                    }

                }
                $value['winpl'] = $winpl;
                $value['exchange_rate'] = Config::get('site.exchange_rate');
                $value['nowtime'] = time();
                $data[$key] = $value;
            }

        }
        return ['code' => 1,'msg'=>'success','time'=>time(),'data'=>$data];
    }

    //获取持仓订单
    public function get_order($params)
    {
        $config = \think\Config::get('token');
        $tokens =  hash_hmac($config['hashalgo'], $params['token'], $config['key']);
        $auth = Db::name('user_token')->where('token',$tokens)->find();
        if(!$auth)
        {
            return ['code'=>0,'msg'=>'登录失效','time'=>time(),'data'=>''];
        }
        $data = Db::name('order')
            ->where('user_id',$auth['user_id'])
            ->order('id','asc')->select();
        foreach ($data as $key=>$value)
        {
            $difftime = time() - $value['createtime'];
            if($difftime >= $value['trade_cycle']){
                unset($data[$key]);
            }
            $value['nowtime'] = time();
            $value['current_price'] = sprintf("%.2f",$value['current_price']);
            $value['trade_num'] = sprintf("%.2f",$value['trade_num']);
            $value['show_name'] = strtoupper(str_replace('usdt','',$value['symbol'])).'/USDT';
            $data[$key] = $value;
        }
        sort($data);
        return ['code' => 1,'msg'=>'success','time'=>time(),'data'=>$data];
    }

    //获取全部订单
    public function get_all_order($params)
    {
        $config = \think\Config::get('token');
        $tokens =  hash_hmac($config['hashalgo'], $params['token'], $config['key']);
        $auth = Db::name('user_token')->where('token',$tokens)->find();
        if(!$auth)
        {
            return ['code'=>0,'msg'=>'登录失效','time'=>time(),'data'=>''];
        }
        $size = (isset($params['size']))?$params['size']:20;
        $symbol = (isset($params['symbol']))?$params['symbol']:'btcusdt';
        $data = Db::name('his_order')
            ->field('createtime,symbol,trade_num,trade_cycle,expect_percent,current_price,close_price,trade_result_num,
            trade_result,rise_or_fall')
            ->where('user_id',$auth['user_id'])
            ->where('symbol',$symbol)
            ->order('id','desc')
            ->paginate($size,false,['query' => request()->param()]);
        foreach ($data as $key => $value)
        {
            $value['createtime'] = date('m-d H:i:s',$value['createtime']);
            $value['current_price'] = sprintf("%.2f",$value['current_price']);
            $value['close_price'] = sprintf("%.2f",$value['close_price']);
            $value['show_name'] = strtoupper(str_replace('usdt','',$value['symbol'])).'/USDT';
            $value['current_price'] = sprintf("%.2f",$value['current_price']);
            $value['trade_num'] = sprintf("%.2f",$value['trade_num']);
            $data[$key] = $value;
        }
        return ['code' => 1,'msg'=>'success','time'=>time(),'data'=>$data];
    }

    //5秒取消
    public function cancel_order($params)
    {
        $config = \think\Config::get('token');
        $tokens =  hash_hmac($config['hashalgo'], $params['token'], $config['key']);
        $auth = Db::name('user_token')->where('token',$tokens)->find();
        if(!$auth)
        {
            return ['code'=>0,'msg'=>'登录失效','time'=>time(),'data'=>''];
        }
        if(!isset($params['id']) || empty($params['id']))
        {
            $this->error(__('请选择要取消的订单'));
        }
        $order = Db::name('order')
            ->where('user_id',$auth['user_id'])
            ->where('id',$params['id'])->find();
        if(!$order){
            return ['code' => 0,'msg'=>'订单不存在','time'=>time(),'data'=>''];
        }

        //订单取消5秒内
        $difftime = time() - $order['createtime'];
        if($difftime>5){
            return ['code' => 0,'msg'=>'订单超时,不能取消','time'=>time(),'data'=>''];
        }
        $symbol = "order_cancel" . $auth['user_id'];
        $submited = pushRedis($symbol);
        if (!$submited) {
            return ['code' => 0,'msg'=>'操作频繁','time'=>time(),'data'=>''];
        }

        $currency = Db::name('app_currency_user')
            ->field('num,id')
            ->where('user_id',$auth['user_id'])
            ->where('curr_id',1)->find();
        $kcnum = sprintf("%.4f",$order['trade_num']*Config::get('site.cycle_cancle'));
        $lostnum = $currency['num'] + $order['trade_num'] - $kcnum;

        $detailed = [
            'user_id' => $auth['user_id'],
            'curr_id' => 1,
            'price' => $kcnum,
            'cart' => '2',
            'type' => '3',
            'serial_no' => $order['serial_no'],
            'order_result' => 'result',
            'description' => '周期持仓取消',
            'createtime' => time(),
            'notice' => '周期持仓取消',
            'before_num' => $currency['num']+$order['trade_num'],
            'after_num' => $lostnum,
        ];
        Db::startTrans();
        try {
            $ret = Db::name('app_currency_user')
                ->where('id',$currency['id'])->update(['num'=>$lostnum,'updatetime'=>time()]);
            if(!$ret)
            {
                lopRedis($symbol);
                Db::rollback();
                return ['code' => 0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
            }
            $ret1 = Db::name('order')->where('id',$order['id'])->delete();
            if(!$ret1)
            {
                lopRedis($symbol);
                Db::rollback();
                return ['code' => 0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
            }
            $ret2 = Db::name('app_detailed')->insert($detailed);
            if(!$ret2)
            {
                lopRedis($symbol);
                Db::rollback();
                return ['code' => 0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
            }
            lopRedis($symbol);
            Db::commit();
            return ['code' => 1,'msg'=>'提交成功','time'=>time(),'data'=>''];
        } catch (Exception $e) {
            Db::rollback();
            return ['code' => 0,'msg'=>'系统繁忙','time'=>time(),'data'=>''];
        }

    }
}