-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
445fc2e
commit 86bf1eb
Showing
4 changed files
with
872 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
<?php | ||
/** | ||
* @author lin <[email protected]> | ||
* */ | ||
|
||
namespace Lin\Bitmex\Api\WebSocket; | ||
|
||
use Lin\Bitmex\Api\WebSocket\SocketGlobal; | ||
use Lin\Bitmex\Api\WebSocket\SocketFunction; | ||
|
||
use Workerman\Lib\Timer; | ||
use Workerman\Worker; | ||
|
||
class SocketClient | ||
{ | ||
use SocketGlobal; | ||
use SocketFunction; | ||
|
||
private $config=[]; | ||
private $keysecret=[]; | ||
|
||
|
||
function __construct(array $config=[]) | ||
{ | ||
$this->config=$config; | ||
|
||
$this->client(); | ||
|
||
$this->init(); | ||
} | ||
|
||
protected function init(){ | ||
//初始化全局变量 | ||
$this->add('global_key',[]);//保存全局变量key | ||
|
||
$this->add('all_sub',[]);//目前总共订阅的频道 | ||
|
||
$this->add('add_sub',[]);//正在订阅的频道 | ||
|
||
$this->add('del_sub',[]);//正在删除的频道 | ||
|
||
$this->add('keysecret',[]);//目前总共key | ||
} | ||
|
||
function keysecret(array $keysecret=[]){ | ||
$this->keysecret=$keysecret; | ||
return $this; | ||
} | ||
|
||
/** | ||
* @param array $sub | ||
*/ | ||
public function subscribe(array $sub=[]){ | ||
// 是否又私有频道订阅 | ||
if(!empty($this->keysecret)) { | ||
$keysecret=$this->get('keysecret'); | ||
|
||
if(!isset($keysecret[$this->keysecret['key']]['connection'])) | ||
$this->keysecretInit($this->keysecret,[ | ||
'connection'=>0, | ||
]); | ||
} | ||
|
||
$this->save('add_sub',$this->resub($sub)); | ||
} | ||
|
||
/** | ||
* @param array $sub | ||
*/ | ||
public function unsubscribe(array $sub=[]){ | ||
$this->save('del_sub',$this->resub($sub)); | ||
} | ||
|
||
/** | ||
* @param array $sub 默认获取所有public订阅的数据,private数据需要设置keysecret | ||
* @param null $callback | ||
* @param bool $daemon | ||
* @return mixed | ||
*/ | ||
public function getSubscribe(array $sub,$callback=null,$daemon=false){ | ||
if($daemon) $this->daemon($callback,$sub); | ||
|
||
return $this->getData($this,$callback,$sub); | ||
} | ||
|
||
/** | ||
* 返回订阅的所有数据 | ||
* @param null $callback | ||
* @param bool $daemon | ||
* @return array | ||
*/ | ||
public function getSubscribes($callback=null,$daemon=false){ | ||
if($daemon) $this->daemon($callback); | ||
|
||
return $this->getData($this,$callback); | ||
} | ||
|
||
protected function daemon($callback=null,$sub=[]){ | ||
$worker = new Worker(); | ||
$worker->onWorkerStart = function() use($callback,$sub) { | ||
$global = $this->client(); | ||
|
||
$time=isset($this->config['data_time']) ? $this->config['data_time'] : 0.5 ; | ||
|
||
Timer::add($time, function() use ($global,$callback,$sub){ | ||
$this->getData($global,$callback,$sub); | ||
}); | ||
}; | ||
Worker::runAll(); | ||
} | ||
|
||
/** | ||
* @param $global | ||
* @param null $callback | ||
* @param array $sub 返回规定的频道 | ||
* @return array | ||
*/ | ||
protected function getData($global,$callback=null,$sub=[]){ | ||
$all_sub=$global->get('all_sub'); | ||
if(empty($all_sub)) return []; | ||
|
||
$temp=[]; | ||
//print_r($all_sub);die; | ||
//默认返回所有数据 | ||
if(empty($sub)){ | ||
foreach ($all_sub as $k=>$v){ | ||
if(is_array($v)) $table=$k; | ||
else $table=$v; | ||
|
||
$data=$global->get(strtolower($table)); | ||
if(empty($data)) continue; | ||
$temp[$table]=$data; | ||
} | ||
}else{ | ||
//返回规定的数据 | ||
if(!empty($this->keysecret)) { | ||
//是否有私有数据 | ||
if(isset($all_sub[$this->keysecret['key']])) $sub=array_merge($sub,$all_sub[$this->keysecret['key']]); | ||
} | ||
|
||
foreach ($sub as $k=>$v){ | ||
//判断私有数据是否需要走队列数据 | ||
$temp_v=explode('=',$v); | ||
if(count($temp_v)>1){ | ||
//private | ||
$data=$global->getQueue(strtolower($v)); | ||
}else{ | ||
//public | ||
|
||
$data=$global->get(strtolower($v)); | ||
} | ||
if(empty($data)) continue; | ||
|
||
$temp[$v]=$data; | ||
} | ||
} | ||
|
||
if($callback!==null){ | ||
call_user_func_array($callback, array($temp)); | ||
} | ||
|
||
return $temp; | ||
} | ||
|
||
function test(){ | ||
print_r($this->client->all_sub); | ||
print_r($this->client->add_sub); | ||
print_r($this->client->del_sub); | ||
print_r($this->client->keysecret); | ||
print_r($this->client->global_key); | ||
} | ||
|
||
function test2(){ | ||
//print_r($this->client->global_key); | ||
$global_key=$this->client->global_key; | ||
foreach ($global_key as $k=>$v){ | ||
echo count($this->client->$v).'----'.$k.PHP_EOL; | ||
echo json_encode($this->client->$v).PHP_EOL; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
<?php | ||
/** | ||
* @author lin <[email protected]> | ||
* */ | ||
|
||
namespace Lin\Bitmex\Api\WebSocket; | ||
|
||
|
||
trait SocketFunction | ||
{ | ||
/** | ||
* @param array $sub | ||
* @return array | ||
*/ | ||
protected function resub(array $sub=[]){ | ||
$new_sub=[]; | ||
|
||
//私有频道 | ||
$temp1=[ | ||
"affiliate", | ||
"execution", | ||
"order", | ||
"margin", | ||
"position", | ||
"privateNotifications", | ||
"transact", | ||
"wallet" | ||
]; | ||
|
||
foreach ($sub as $v) { | ||
$temp_tag=false; | ||
$temp2=[$v]; | ||
foreach ($temp1 as $tv){ | ||
if(strpos($v, $tv) !== false){ | ||
//order是私有 orderBook是公共 需要区别一下 | ||
if($tv=='order' && strpos($v, 'orderBook') !== false) { | ||
array_push($new_sub,$temp2); | ||
$temp_tag=true; | ||
} | ||
else array_push($temp2,empty($this->keysecret)? [] : $this->keysecret); | ||
} | ||
} | ||
if(!$temp_tag) array_push($new_sub,$temp2); | ||
} | ||
|
||
return $new_sub; | ||
} | ||
|
||
protected function log($message){ | ||
if (!is_string($message)) $message=json_encode($message); | ||
|
||
$time=time(); | ||
$tiemdate=date('Y-m-d H:i:s',$time); | ||
|
||
$message=$tiemdate.' '.$message.PHP_EOL; | ||
|
||
if(isset($this->config['log'])){ | ||
if(is_array($this->config['log']) && isset($this->config['log']['filename'])){ | ||
$filename=$this->config['log']['filename'].'-'.date('Y-m-d',$time).'.txt'; | ||
}else{ | ||
$filename=date('Y-m-d',$time).'.txt'; | ||
} | ||
|
||
file_put_contents($filename,$message,FILE_APPEND); | ||
} | ||
|
||
echo $message; | ||
} | ||
|
||
/** | ||
* 设置用户key | ||
* @param $keysecret | ||
*/ | ||
protected function userKey(array $keysecret,string $sub){ | ||
return $keysecret['key'].'='.$sub; | ||
} | ||
|
||
/** | ||
* 根据Bitmex规则排序 | ||
* */ | ||
protected function sort($param) | ||
{ | ||
$u = []; | ||
$sort_rank = []; | ||
foreach ($param as $k => $v) { | ||
if(is_array($v)) $v=json_encode($v); | ||
$u[] = $k . "=" . urlencode($v); | ||
$sort_rank[] = ord($k); | ||
} | ||
asort($u); | ||
|
||
return $u; | ||
} | ||
|
||
private function sign(array $keysecret){ | ||
//签名是十六进制的 hex(HMAC_SHA256(secret, 'GET/realtime' + expires)) | ||
// expires 必须是一个数字,而不是一个字符串。 | ||
//{"op": "authKeyExpires", "args": ["<APIKey>", <expires>, "<signature>"]} | ||
|
||
//Time delay 10 seconds | ||
$expires=time()+10; | ||
|
||
$signature=hash_hmac('sha256', 'GET/realtime'.$expires, $keysecret['secret']); | ||
|
||
return [ | ||
$keysecret['key'], | ||
$expires, | ||
$signature | ||
]; | ||
} | ||
} |
Oops, something went wrong.