- Contract.php: 返回合约账户余额(balance_contract) - My.php: 地址管理增加BTC/ETH - AppContract.php: 一键平仓(closeall) - AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2) - site.php: 手续费减半(0.018→0.009) - agent_permission_setup.sql: 代理权限SQL - crypto_news_crawler.py: 新闻自动采集脚本
881 lines
34 KiB
PHP
Executable File
881 lines
34 KiB
PHP
Executable File
<?php
|
||
namespace app\api\controller;
|
||
use app\common\controller\Api;
|
||
use app\common\model\TradeConfig;
|
||
use think\worker\Server;
|
||
use Workerman\Worker;
|
||
use Workerman\Lib\Timer;
|
||
use Workerman\Connection\AsyncTcpConnection;
|
||
use \Workerman\Autoloader;
|
||
use GatewayWorker\Gateway;
|
||
use think\Log;
|
||
use think\Db;
|
||
use think\Exception;
|
||
use fast\Random;
|
||
use app\common\library\Token;
|
||
|
||
|
||
//use think\console\Input;
|
||
//use think\console\Output;
|
||
//use think\console\Command;
|
||
|
||
//心跳间隔5秒
|
||
define('HEARTBEAT_TIME', 10);
|
||
|
||
/**
|
||
*交易对K线图数据生成-火币
|
||
* 用于实时接收火币K线数据
|
||
*/
|
||
class TradeKline extends Api
|
||
{
|
||
protected $noNeedLogin = ['*'];
|
||
protected $noNeedRight = ['*'];
|
||
|
||
protected $flag = true;//是否正式环境
|
||
|
||
protected $huobi_host = '';
|
||
|
||
protected $server_host = 'ws://api.huobiasia.vip/ws';
|
||
|
||
protected $host = 'ws://api.huobiasia.vip/ws';
|
||
|
||
protected $local_host = 'Websocket://0.0.0.0:8686';// 代理监听本地9999端口
|
||
|
||
private $time_list = [
|
||
'1min'=>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 "<pre>";
|
||
// 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'=>''];
|
||
}
|
||
|
||
}
|
||
} |