作者 karlet

feat:更新常用类

  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +use Jiaoyin\MongoPool;
  6 +
  7 +class MongoCli
  8 +{
  9 + private $pool;
  10 + private $database;
  11 + public function __construct($host,$port,$username,$password,$database, $num = 20)
  12 + {
  13 + $this->database = $database;
  14 + $userInfo = $username?"{$username}:{$password}@":"";
  15 + $dsn = "mongodb://{$userInfo}{$host}:{$port}/{$database}";
  16 + $this->pool = new MongoPool($dsn,$num);
  17 + }
  18 +
  19 + /*
  20 + * 创建集合
  21 + */
  22 + public function createCollection($table,$createIndex=[]){
  23 + try {
  24 + $mongodb = $this->pool->get();
  25 + $database = $mongodb->selectDatabase($this->database);
  26 + $collections = $database->listCollections(['filter' => ['name' => $table]]);
  27 + $collectionExists = iterator_count($collections) > 0;
  28 + if (empty($collectionExists)) {
  29 + // 集合不存在,创建集合并添加索引
  30 + $database->createCollection($table);
  31 + $collection = $database->selectCollection($table);
  32 + $collection->createIndex($createIndex);
  33 + }
  34 + $this->pool->push($mongodb);
  35 + } catch (\Exception $e) {
  36 + output($e->getMessage());
  37 + }
  38 + }
  39 + /*
  40 + * 检查集合是否存在
  41 + * */
  42 + public function checkCollection($table): bool
  43 + {
  44 + try {
  45 + $mongodb = $this->pool->get();
  46 + $database = $mongodb->selectDatabase($this->database);
  47 + $collections = $database->listCollections(['filter' => ['name' => $table]]);
  48 + $collectionExists = iterator_count($collections) > 0;
  49 + $this->pool->push($mongodb);
  50 + if (empty($collectionExists)) {
  51 + // 集合不存在
  52 + return false;
  53 + }
  54 + return true;
  55 + } catch (\Exception $e) {
  56 + output($e->getMessage());
  57 + return false;
  58 + }
  59 + }
  60 +
  61 + /*
  62 + * 写入数据
  63 + * $collection->insertOne(['name' => 'John Doe']);
  64 + * */
  65 + public function insertOne($table,$data = [])
  66 + {
  67 + try {
  68 + $mongodb = $this->pool->get();
  69 + $database = $mongodb->selectDatabase($this->database);
  70 + $collection = $database->selectCollection($table);
  71 + $result = $collection->insertOne($data);
  72 + $this->pool->push($mongodb);
  73 + return $result;
  74 + } catch (\Exception $e) {
  75 + output($e->getMessage());
  76 + return false;
  77 + }
  78 + }
  79 +
  80 + /*
  81 + * 批量写入数据
  82 + * $collection->insertMany([['name' => 'John Doe'],['name' => 'John Doe']]);
  83 + * */
  84 + public function insertAll($table,$data = [])
  85 + {
  86 + try {
  87 + $mongodb = $this->pool->get();
  88 + $database = $mongodb->selectDatabase($this->database);
  89 + $collection = $database->selectCollection($table);
  90 + $result = $collection->insertMany($data);
  91 + $this->pool->push($mongodb);
  92 + return $result;
  93 + } catch (\Exception $e) {
  94 + output($e->getMessage());
  95 + return [];
  96 + }
  97 + }
  98 +
  99 + /*
  100 + * 查询单条数据
  101 + * $collection->findOne(['name' => 'John Doe']);
  102 + * */
  103 + public function findOne($table,$where = [])
  104 + {
  105 + try {
  106 + $mongodb = $this->pool->get();
  107 + $database = $mongodb->selectDatabase($this->database);
  108 + $collection = $database->selectCollection($table);
  109 + $result = $collection->findOne($where);
  110 + $this->pool->push($mongodb);
  111 + return $result;
  112 + } catch (\Exception $e) {
  113 + output($e->getMessage());
  114 + return [];
  115 + }
  116 + }
  117 +
  118 + /*
  119 + * 查询所有数据
  120 + * $collection->findOne(['name' => 'John Doe']);
  121 + * ['t' => ['$gt' => 1]]; // 查询大于1的数据
  122 + * ['t' => ['$lt' => 1]]; // 查询小于1的数据
  123 + * ['t' => ['$gte' => 1]]; // 查询大于等于1的数据
  124 + * ['t' => ['$lte' => 1]]; // 查询小于等于1的数据
  125 + * $options = [
  126 + * 'sort' => ['field_name' => 1], // 1 表示升序,-1 表示降序,
  127 + * 'limit' => 100,
  128 + * ];
  129 + * */
  130 + public function findAll($table,$where = [], $options=[])
  131 + {
  132 + try {
  133 + $mongodb = $this->pool->get();
  134 + $database = $mongodb->selectDatabase($this->database);
  135 + $collection = $database->selectCollection($table);
  136 + $result = $collection->find($where,$options);
  137 + $this->pool->push($mongodb);
  138 + // 遍历结果集
  139 + $data = [];
  140 + if ($result){
  141 + $arr = $result->toArray();
  142 + foreach ($arr as $item) {
  143 + $data[] = $item->getArrayCopy();
  144 + }
  145 + return $data;
  146 + }
  147 + return [];
  148 + } catch (\Exception $e) {
  149 + output($e->getMessage());
  150 + return [];
  151 + }
  152 + }
  153 +
  154 + /*
  155 + * 更新数据
  156 + * $collection->updateOne(['name' => 'John Doe'], ['$set' => ['age' => 31]]);
  157 + * */
  158 + public function updateOne($table,$where = [],$upData = [])
  159 + {
  160 + try {
  161 + $mongodb = $this->pool->get();
  162 + $database = $mongodb->selectDatabase($this->database);
  163 + $collection = $database->selectCollection($table);
  164 + $result = $collection->updateOne($where,$upData);
  165 + $this->pool->push($mongodb);
  166 + return $result;
  167 + } catch (\Exception $e) {
  168 + output($e->getMessage());
  169 + return [];
  170 + }
  171 + }
  172 +
  173 + /*
  174 + * 删除数据
  175 + * $collection->deleteOne(['name' => 'John Doe']);
  176 + * */
  177 + public function deleteOne($table,$where = [])
  178 + {
  179 + try {
  180 + $mongodb = $this->pool->get();
  181 + $database = $mongodb->selectDatabase($this->database);
  182 + $collection = $database->selectCollection($table);
  183 + $result = $collection->deleteOne($where);
  184 + $this->pool->push($mongodb);
  185 + return $result;
  186 + } catch (\Exception $e) {
  187 + output($e->getMessage());
  188 + return [];
  189 + }
  190 + }
  191 +
  192 + /*
  193 + * 批量删除数据
  194 + * $collection->deleteMany(['name' => 'John Doe']);
  195 + * */
  196 + public function deleteBatch($table,$where = [])
  197 + {
  198 + try {
  199 + $mongodb = $this->pool->get();
  200 + $database = $mongodb->selectDatabase($this->database);
  201 + $collection = $database->selectCollection($table);
  202 + $result = $collection->deleteMany($where);
  203 + $this->pool->push($mongodb);
  204 + return $result;
  205 + } catch (\Exception $e) {
  206 + output($e->getMessage());
  207 + return [];
  208 + }
  209 + }
  210 +
  211 +}
  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +use Swoole\Coroutine;
  6 +use Swoole\Coroutine\Channel;
  7 +use MongoDB\Client;
  8 +class MongoPool
  9 +{
  10 + private $pool;
  11 + private $maxSize;
  12 + private $currentSize;
  13 + private $mongoUri;
  14 + private $options;
  15 +
  16 + public function __construct($mongoUri, $maxSize=20, $options = [])
  17 + {
  18 + $this->mongoUri = $mongoUri;
  19 + $this->maxSize = $maxSize;
  20 + $this->currentSize = 0;
  21 + $this->options = $options;
  22 + $this->pool = new Channel($maxSize);
  23 +
  24 + // 初始化连接池
  25 + for ($i = 0; $i < $maxSize; $i++) {
  26 + $this->pool->push($this->createConnection());
  27 + }
  28 + }
  29 +
  30 + private function createConnection()
  31 + {
  32 + $manager = new Client($this->mongoUri, $this->options);
  33 + return $manager;
  34 + }
  35 +
  36 + public function get()
  37 + {
  38 + while ($this->pool->isEmpty()){
  39 +// output('Mongodb连接池为空,等待释放连接');
  40 + Coroutine::sleep(0.1);
  41 + }
  42 + $connection = $this->pool->pop();
  43 + if (!$connection) {
  44 + if ($this->currentSize < $this->maxSize) {
  45 + // 如果连接池未满,则创建新连接
  46 + $connection = $this->createConnection();
  47 + $this->currentSize++;
  48 + } else {
  49 + // 连接池已满,等待其他协程释放连接
  50 + $connection = $this->pool->pop();
  51 + }
  52 + }
  53 + return $connection;
  54 + }
  55 +
  56 + public function push($connection)
  57 + {
  58 + // 检查连接是否有效,这里仅做示例,实际应用中可能需要更复杂的逻辑
  59 + if (is_object($connection) && get_class($connection) === Client::class) {
  60 + $this->pool->push($connection);
  61 + }else{
  62 + $this->currentSize -= 1;
  63 + }
  64 + }
  65 +
  66 + public function close()
  67 + {
  68 + while (!$this->pool->isEmpty()) {
  69 + $connection = $this->pool->pop();
  70 + if (is_resource($connection)) {
  71 + $connection->close();
  72 + }
  73 + }
  74 + $this->currentSize = 0;
  75 + }
  76 +}
1 <?php 1 <?php
2 namespace Jiaoyin; 2 namespace Jiaoyin;
3 3
4 -class MysqlCli{  
5 - public function start(){  
6 - echo 'mysqlCli test'; 4 +use Jiaoyin;
  5 +use Swoole\Database\MysqliConfig;
  6 +use Swoole\Database\MysqliPool;
  7 +
  8 +class MysqlCli
  9 +{
  10 +
  11 + private $pool = null;
  12 + private $prefix = '';// 前缀
  13 +
  14 + private int $reconnectCount = 0; //period时间内重连次数
  15 + private int $period = 300;
  16 + private int $lastReconnectTime = 0;
  17 + private $connectConfig = null;
  18 +
  19 + public function __construct($host,$port,$database,$username,$password,$charset='utf8',$prefix='', $connectCount = 20)
  20 + {
  21 + $this->prefix = $prefix;
  22 + $this->connectConfig = [
  23 + 'host' => $host,
  24 + 'port' => $port,
  25 + 'database' => $database,
  26 + 'username' => $username,
  27 + 'password' => $password,
  28 + 'charset' => $charset,
  29 + 'prefix' => $prefix,
  30 + 'connectCount' => $connectCount,
  31 + ];
  32 + $this->poolConnect();
  33 + }
  34 +
  35 + private function poolConnect()
  36 + {
  37 + if($this->pool){
  38 + $this->pool->close();
  39 + }
  40 + $this->pool = new MysqliPool((new MysqliConfig)
  41 + ->withHost($this->connectConfig['host'])
  42 + ->withPort($this->connectConfig['port'])
  43 + ->withDbName($this->connectConfig['database'])
  44 + ->withCharset($this->connectConfig['charset'])
  45 + ->withUsername($this->connectConfig['username'])
  46 + ->withPassword($this->connectConfig['password'])
  47 + ,$this->connectConfig['connectCount']
  48 + );
  49 + $this->prefix = $this->connectConfig['prefix'];
  50 + }
  51 +
  52 + //执行sql
  53 + public function execute($action, $sql)
  54 + {
  55 + $ret = false;
  56 + $db = $this->pool->get();
  57 + try {
  58 + $stmt = $db->query($sql);
  59 + if ($stmt == false) {
  60 + output($db->errno, $db->error);
  61 + } else {
  62 + if ($action == 'SELECT') {
  63 + $ret = $stmt->fetch_all();
  64 + } else {
  65 + $ret = $stmt;
  66 + }
  67 + }
  68 + } catch (\Exception $e) {
  69 + $errorMsg = $e->getMessage();
  70 + output($sql);
  71 + output('sql错误', $errorMsg);
  72 + if ($errorMsg == 'MySQL server has gone away') {
  73 + if ($this->reconnectCount >= 3 && time() - $this->lastReconnectTime < $this->period) {
  74 + //period内重连超过3次,不继续重连但电话通知异常
  75 + output('数据库连接失效,并重连3次失败');
  76 + } else {
  77 + //重连
  78 + output('重新创建mysql连接池', $this->reconnectCount);
  79 + $this->pool->put($db);
  80 + $this->poolConnect();
  81 + if (time() - $this->lastReconnectTime < $this->period) {
  82 + $this->reconnectCount += 1;
  83 + } else {
  84 + $this->reconnectCount = 0;
  85 + }
  86 + $this->lastReconnectTime = time();
  87 + return $this->execute($action, $sql);
  88 + }
  89 + } else {
  90 + output('数据库操作异常');
  91 + }
  92 + }
  93 + $this->pool->put($db);
  94 + return $ret;
  95 + }
  96 +
  97 + //插入数据
  98 + public function insert($table, $data)
  99 + {
  100 + $sql = $this->parseInsert($table, $data);
  101 + if (!$sql) {
  102 + return false;
  103 + }
  104 + return $this->execute('INSERT', $sql);
  105 + }
  106 +
  107 + //select数据
  108 + public function select($table, $where = [], $col = [], $orderBy = '', $limit = '')
  109 + {
  110 +
  111 + $sql = $this->parseSelect($table, $where, $col, $orderBy, $limit);
  112 + if (!$sql) {
  113 + return false;
  114 + }
  115 + $data = $this->execute('SELECT', $sql);
  116 + $newData = [];
  117 + if (empty($col)) {
  118 + $newsql = 'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="' . $this->parseTable($table) . '" ORDER BY `ORDINAL_POSITION` ASC';
  119 + $coldata = $this->execute('SELECT', $newsql);
  120 + if (!$coldata) {
  121 + return false;
  122 + } else {
  123 + foreach ($coldata as $key => $value) {
  124 + $col[] = $value[0];
  125 + }
  126 + }
  127 + }
  128 + foreach ($data as $key => $value) {
  129 + $tmp = [];
  130 + foreach ($col as $k => $v) {
  131 + $tmp[$v] = $value[$k];
  132 + }
  133 + $data[$key] = $tmp;
  134 + }
  135 + return $data;
  136 + }
  137 +
  138 + public function update($table, $data, $where = [])
  139 + {
  140 + $sql = $this->parseUpdate($table, $where, $data);
  141 + if (!$sql) {
  142 + return false;
  143 + }
  144 + return $this->execute('UPDATE', $sql);
7 } 145 }
  146 +
  147 + //查找符合条件的一条记录
  148 + public function find($table, $where, $col = [], $orderBy = '')
  149 + {
  150 + $data = $this->select($table, $where, $col, $orderBy, 1);
  151 + if ($data && isset($data[0])) {
  152 + return $data['0'];
  153 + }
  154 + return $data;
  155 + }
  156 +
  157 + //解析insert
  158 + private function parseInsert($table, $data)
  159 + {
  160 + $table = $this->parseTable($table);
  161 + if (!is_array($data)) {
  162 + output('insert data 不合法');
  163 + return false;
  164 + }
  165 + $keys = array_keys($data);
  166 + $values = array_values($data);
  167 + foreach ($values as $key => $value) {
  168 + $values[$key] = $this->transferValue($value);
  169 + }
  170 + $keysFormat = implode(',', $keys);
  171 + $valuesFormat = implode(',', $values);
  172 + $sql = "insert into {$table}({$keysFormat}) values({$valuesFormat})";
  173 + return $sql;
  174 + }
  175 +
  176 + //解析select
  177 + private function parseSelect($table, $where, $col, $orderBy, $limit)
  178 + {
  179 + $table = $this->parseTable($table);
  180 + if (!empty($col) && !is_array($col)) {
  181 + output('select where col 不合法');
  182 + return false;
  183 + }
  184 + $colTxt = empty($col) ? '*' : implode(',', $col);
  185 + $whereTxt = $this->parseWhere($where);
  186 + $orderByTxt = !empty($orderBy) && isset($orderBy[0]) && isset($orderBy[1]) ? 'order by ' . $orderBy[0] . ' ' . $orderBy[1] : '';
  187 + $limitTxt = !empty($limit) ? 'limit ' . $limit : '';
  188 + $sql = "select {$colTxt} from {$table} {$whereTxt} {$orderByTxt} {$limitTxt}";
  189 + return $sql;
  190 + }
  191 +
  192 + //解析where
  193 + private function parseWhere($where)
  194 + {
  195 + if (empty($where)) {
  196 + return '';
  197 + }
  198 + $whereTxt = 'where ';
  199 + if (is_string($where)) {
  200 + $whereTxt .= $where;
  201 + } else if (is_array($where)) {
  202 + $tmp = '';
  203 + foreach ($where as $key => $value) {
  204 + if (!is_array($value) && !isset($value[1])) {
  205 + output('where 不合法');
  206 + var_dump($where);
  207 + return false;
  208 + }
  209 + $value[1] = $this->transferValue($value[1]);
  210 + $symbol = isset($value[2]) ? $value[2] : '=';
  211 + $tmp .= $value[0] . ' ' . $symbol . ' ' . $value[1];
  212 + $tmp .= $key < count($where) - 1 ? ' and ' : '';
  213 + }
  214 + $whereTxt .= $tmp;
  215 + } else {
  216 + output('where 不合法');
  217 + var_dump($where);
  218 + return false;
  219 + }
  220 + return $whereTxt;
  221 + }
  222 +
  223 + //解析udpate
  224 + private function parseUpdate($table, $where, $data)
  225 + {
  226 + $table = $this->parseTable($table);
  227 + if (!is_array($data) || empty($data)) {
  228 + output('更新数据不能为空');
  229 + return false;
  230 + }
  231 + $setTxt = 'set ';
  232 + $count = 0;
  233 + foreach ($data as $key => $value) {
  234 + $setTxt .= $key . '=';
  235 + $setTxt .= $this->transferValue($value);
  236 + if ($count < count($data) - 1) {
  237 + $setTxt .= ',';
  238 + }
  239 + $count += 1;
  240 + }
  241 + $whereTxt = $this->parseWhere($where);
  242 + $sql = 'update ' . $table . ' ' . $setTxt . ' ' . $whereTxt;
  243 + return $sql;
  244 + }
  245 +
  246 + private function parseTable($table)
  247 + {
  248 + return $this->prefix . $table;
  249 + }
  250 +
  251 + //值转义
  252 + private function transferValue($value)
  253 + {
  254 + $valueNew = null;
  255 + if (is_string($value)) {
  256 + $valueNew = '"' . $value . '"';
  257 + } else if ($value === null) {
  258 + $valueNew = 'NULL';
  259 + } else {
  260 + if (is_numeric($value) && strpos($value . '', 'E') !== false) {
  261 + $value = number_format($value, 8);
  262 + while (substr($value, -1) === '0') {
  263 + $value = substr($value, 0, -1);
  264 + }
  265 + }
  266 + $valueNew = $value;
  267 + }
  268 + return $valueNew;
  269 + }
  270 +
8 } 271 }
  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +use Swoole\Database\RedisConfig;
  6 +use Swoole\Database\RedisPool;
  7 +
  8 +class RedisCli
  9 +{
  10 + private $pool;
  11 + public function __construct($host,$port,$password,$dbIndex, $num = 20)
  12 + {
  13 + $this->pool = new RedisPool((new RedisConfig)
  14 + ->withHost($host)
  15 + ->withPort($port)
  16 + ->withAuth($password)
  17 + ->withDbIndex($dbIndex)
  18 + ->withTimeout(5)
  19 + ,$num //默认64个连接池
  20 + );
  21 + }
  22 + //集合存数据
  23 + public function sAdd($key,$member){
  24 + $redis = $this->pool->get();
  25 + try {
  26 + $res = $redis->sAdd($key,$member);
  27 + } catch (\RedisException $e) {
  28 + return false;
  29 + }
  30 + $this->pool->put($redis);
  31 + return $res;
  32 + }
  33 +
  34 + //获取集合
  35 + public function sMembers($key){
  36 + $redis = $this->pool->get();
  37 + try {
  38 + $res = $redis->sMembers($key);
  39 + } catch (\RedisException $e) {
  40 + return false;
  41 + }
  42 + $this->pool->put($redis);
  43 + return $res;
  44 + }
  45 +
  46 + //移除集合成员
  47 + public function sRem($key,$member){
  48 + $redis = $this->pool->get();
  49 + try {
  50 + $res = $redis->sRem($key,$member);
  51 + }catch (\RedisException $e){
  52 + return false;
  53 + }
  54 +
  55 + $this->pool->put($redis);
  56 + return $res;
  57 + }
  58 +
  59 + //哈希 键 字段 值 设置
  60 + public function hSet($key,$field,$value){
  61 + $redis = $this->pool->get();
  62 + try {
  63 + $res = $redis->hSet($key, $field, $value);
  64 + } catch (\RedisException $e) {
  65 + return false;
  66 + }
  67 + $this->pool->put($redis);
  68 + return $res;
  69 + }
  70 + //获取 键对应字段的值
  71 + public function hGet($key,$field){
  72 + $redis = $this->pool->get();
  73 + try {
  74 + $res = $redis->hGet($key, $field);
  75 + } catch (\RedisException $e) {
  76 + return false;
  77 + }
  78 + $this->pool->put($redis);
  79 + return $res;
  80 + }
  81 + //获取键所有字段和值
  82 + public function hGetAll($key){
  83 + $redis = $this->pool->get();
  84 + try {
  85 + $res = $redis->hGetAll($key);
  86 + } catch (\RedisException $e) {
  87 + return false;
  88 + }
  89 + $this->pool->put($redis);
  90 + return $res;
  91 + }
  92 + //删除一个值
  93 + public function hDel($key,$field){
  94 + $redis = $this->pool->get();
  95 + try {
  96 + $res = $redis->hDel($key, $field);
  97 + } catch (\RedisException $e) {
  98 + return false;
  99 + }
  100 + $this->pool->put($redis);
  101 + return $res;
  102 + }
  103 +
  104 + /*
  105 + * 发布订阅等
  106 + */
  107 + //将信息发送到指定的频道
  108 + public function publish($channel,$message){
  109 + $redis = $this->pool->get();
  110 + try {
  111 + $res = $redis->publish($channel, $message);
  112 + } catch (\RedisException $e) {
  113 + return false;
  114 + }
  115 + $this->pool->put($redis);
  116 + return $res;
  117 + }
  118 +
  119 + public function subscribe($channels,callable $onMessage)
  120 + {
  121 + $redis = $this->pool->get();
  122 + try {
  123 + $res = $redis->subscribe($channels,function($redis, $channel, $message)use($onMessage){
  124 + call_user_func($onMessage,$redis, $channel, $message);
  125 + });
  126 + } catch (\RedisException $e) {
  127 + return false;
  128 + }
  129 + $this->pool->put($redis);
  130 + return $res;
  131 + }
  132 +
  133 +}
  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +use Jiaoyin\Curl;
  6 +
  7 +/*
  8 + binance合约接口
  9 +*/
  10 +class BinanceFutures
  11 +{
  12 + static private string $host = 'https://fapi.binance.com';
  13 + private string $apikey = '';
  14 + private string $secret = '';
  15 +
  16 + public function __construct($apikey='', $secret='',$host='')
  17 + {
  18 + $this->apikey = $apikey;
  19 + $this->secret = $secret;
  20 + if(!empty($host)){
  21 + self::$host = $host;
  22 + }
  23 + }
  24 +
  25 + static private function createUrl($path): string
  26 + {
  27 + return self::$host . $path;
  28 + }
  29 +
  30 + static private function createHeader($apikey): array
  31 + {
  32 + return ["X-MBX-APIKEY:" . $apikey];
  33 + }
  34 +
  35 + static private function createSign($secret, $param)
  36 + {
  37 + $len = count($param);
  38 + if ($len == 0) {
  39 + output('param 为空,签名失败');
  40 + return $param;
  41 + }
  42 + $paramStr = http_build_query($param);
  43 + return hash_hmac('sha256', $paramStr, $secret);
  44 + }
  45 +
  46 + private function requestAccount($method, $path, $param)
  47 + {
  48 + if(empty($this->apikey) || empty($this->secret)){
  49 + output('api 或 secret 为空');
  50 + return ['code'=>-1,'msg'=>'apikey or secret is empty'];
  51 + }
  52 + $url = $this->createUrl($path);
  53 + $param['timestamp'] = getMicrotime();
  54 + $param['signature'] = $this->createSign($this->secret, $param);
  55 + $header = $this->createHeader($this->apikey);
  56 + if (!in_array(strtoupper($method), ['GET', 'POST', 'DELETE'])) {
  57 + output('请求方法错误', $method, $path, $param);
  58 + return 0;
  59 + }
  60 + $data = json_encode([]);
  61 + if (strtoupper($method) == 'POST') {
  62 + $data = Curl::httpPost($url, $param, $header);
  63 + }
  64 + if (strtoupper($method) == 'GET') {
  65 + $data = Curl::httpGet($url, $param, $header);
  66 + }
  67 + if (strtoupper($method) == 'DELETE') {
  68 + $data = Curl::httpDelete($url, $param, $header);
  69 + }
  70 + return json_decode($data, true);
  71 + }
  72 +
  73 + static private function requestMarket($method, $path, $param)
  74 + {
  75 + $url = self::createUrl($path);
  76 + if (!in_array(strtoupper($method), ['GET', 'POST', 'DELETE'])) {
  77 + output('请求方法错误', $method, $path, $param);
  78 + return 0;
  79 + }
  80 + $data = json_encode([]);
  81 + if (strtoupper($method) == 'POST') {
  82 + $data = Curl::httpPost($url, $param);
  83 + }
  84 + if (strtoupper($method) == 'GET') {
  85 + $data = Curl::httpGet($url, $param);
  86 + }
  87 + if (strtoupper($method) == 'DELETE') {
  88 + $data = Curl::httpDelete($url, $param);
  89 + }
  90 + return json_decode($data, true);
  91 + }
  92 +
  93 + public function cancelOrderById($param)
  94 + {
  95 + $path = '/fapi/v1/order';
  96 + $method = 'DELETE';
  97 + return $this->requestAccount($method, $path, $param);
  98 + }
  99 +
  100 + //下单
  101 + public function order($param)
  102 + {
  103 + $path = '/fapi/v1/order';
  104 + $method = 'POST';
  105 + return $this->requestAccount($method, $path, $param);
  106 + }
  107 +
  108 + //获取或者延长listenKey
  109 + public function listenKey($param = [])
  110 + {
  111 + $path = '/fapi/v1/listenKey';
  112 + $method = 'POST';
  113 + return $this->requestAccount($method, $path, $param);
  114 + }
  115 +
  116 + //获取仓位
  117 + public function account($param = [])
  118 + {
  119 + $path = '/fapi/v2/account';
  120 + $method = 'GET';
  121 + return $this->requestAccount($method, $path, $param);
  122 + }
  123 +
  124 + //查询历史订单
  125 + public function allOrders($param)
  126 + {
  127 + $path = '/fapi/v1/allOrders';
  128 + $method = 'GET';
  129 + return $this->requestAccount($method, $path, $param);
  130 + }
  131 +
  132 + //查询持仓模式
  133 + public function positionSideDual($param = [])
  134 + {
  135 + $path = '/fapi/v1/positionSide/dual';
  136 + $method = 'GET';
  137 + return $this->requestAccount($method, $path, $param);
  138 + }
  139 +
  140 + //设置持仓模式
  141 + public function setPositionSideDual($param)
  142 + {
  143 + $path = '/fapi/v1/positionSide/dual';
  144 + $method = 'POST';
  145 + return $this->requestAccount($method, $path, $param);
  146 + }
  147 +
  148 + //查询资产
  149 + public function balance($param = [])
  150 + {
  151 + $path = '/fapi/v2/balance';
  152 + $method = 'GET';
  153 + return $this->requestAccount($method, $path, $param);
  154 + }
  155 +
  156 + //查询杠杆层级
  157 + public function leverageBracket($param = [])
  158 + {
  159 + $path = '/fapi/v1/leverageBracket';
  160 + $method = 'GET';
  161 + return $this->requestAccount($method, $path, $param);
  162 + }
  163 +
  164 + //查询用户持仓风险,杠杆倍数
  165 + public function positionRisk($param = [])
  166 + {
  167 + $path = '/fapi/v2/positionRisk';
  168 + $method = 'GET';
  169 + return $this->requestAccount($method, $path, $param);
  170 + }
  171 +
  172 + //设置杠杆
  173 + public function leverage($param)
  174 + {
  175 + $path = '/fapi/v1/leverage';
  176 + $method = 'POST';
  177 + return $this->requestAccount($method, $path, $param);
  178 + }
  179 + //查询资金流水
  180 + public function income($param)
  181 + {
  182 + $path = '/fapi/v1/income';
  183 + $method = 'GET';
  184 + return $this->requestAccount($method, $path, $param);
  185 + }
  186 +
  187 + /*
  188 + * ==================================
  189 + * 以下公共接口,无限apikey
  190 + * ==================================
  191 + */
  192 + //24小时成交数据
  193 + static public function ticker24hr($param = [])
  194 + {
  195 + $path = '/fapi/v1/ticker/24hr';
  196 + $method = 'GET';
  197 + return self::requestMarket($method, $path, $param);
  198 + }
  199 +
  200 + //获取交易对和交易规则
  201 + static public function exchangeInfo($param = [])
  202 + {
  203 + $path = '/fapi/v1/exchangeInfo';
  204 + $method = 'GET';
  205 + return self::requestMarket($method, $path, $param);
  206 + }
  207 + //获取k线数据
  208 + static public function klines($param)
  209 + {
  210 + $path = '/fapi/v1/klines';
  211 + $method = 'GET';
  212 + return self::requestMarket($method, $path, $param);
  213 + }
  214 +}
  215 +
  216 +?>
  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +use Jiaoyin\Curl;
  6 +
  7 +/*
  8 + binance现货接口
  9 +*/
  10 +class BinanceSpot
  11 +{
  12 + static private string $host = 'https://api.binance.com';
  13 + private string $apikey = '';
  14 + private string $secret = '';
  15 +
  16 + public function __construct($apikey='', $secret='',$host='')
  17 + {
  18 + $this->apikey = $apikey;
  19 + $this->secret = $secret;
  20 + if(!empty($host)){
  21 + self::$host = $host;
  22 + }
  23 + }
  24 +
  25 + static private function createUrl($path): string
  26 + {
  27 + return self::$host . $path;
  28 + }
  29 +
  30 + static private function createHeader($apikey): array
  31 + {
  32 + return ["X-MBX-APIKEY:" . $apikey];
  33 + }
  34 +
  35 + static private function createSign($secret, $param)
  36 + {
  37 + $len = count($param);
  38 + if ($len == 0) {
  39 + output('param 为空,签名失败');
  40 + return $param;
  41 + }
  42 + $paramStr = http_build_query($param);
  43 + return hash_hmac('sha256', $paramStr, $secret);
  44 + }
  45 +
  46 + private function requestAccount($method, $path, $param)
  47 + {
  48 + $url = $this->createUrl($path);
  49 + $param['timestamp'] = getMicrotime();
  50 + $param['signature'] = $this->createSign($this->secret, $param);
  51 + $header = $this->createHeader($this->apikey);
  52 + if (!in_array(strtoupper($method), ['GET', 'POST', 'DELETE'])) {
  53 + output('请求方法错误', $method, $path, $param);
  54 + return 0;
  55 + }
  56 + $data = json_encode([]);
  57 + if (strtoupper($method) == 'POST') {
  58 + $data = Curl::httpPost($url, $param, $header);
  59 + }
  60 + if (strtoupper($method) == 'GET') {
  61 + $data = Curl::httpGet($url, $param, $header);
  62 + }
  63 + if (strtoupper($method) == 'DELETE') {
  64 + $data = Curl::httpDelete($url, $param, $header);
  65 + }
  66 + return json_decode($data, true);
  67 + }
  68 +
  69 + static private function requestMarket($method, $path, $param)
  70 + {
  71 + $url = self::createUrl($path);
  72 + if (!in_array(strtoupper($method), ['GET', 'POST', 'DELETE'])) {
  73 + output('请求方法错误', $method, $path, $param);
  74 + return 0;
  75 + }
  76 + $data = json_encode([]);
  77 + if (strtoupper($method) == 'POST') {
  78 + $data = network\Curl::httpPost($url, $param);
  79 + }
  80 + if (strtoupper($method) == 'GET') {
  81 + $data = network\Curl::httpGet($url, $param);
  82 + }
  83 + if (strtoupper($method) == 'DELETE') {
  84 + $data = network\Curl::httpDelete($url, $param);
  85 + }
  86 + return json_decode($data, true);
  87 + }
  88 +
  89 + //查询用户万向划转历史
  90 + public function getTransfer($param)
  91 + {
  92 + $path = '/sapi/v1/asset/transfer';
  93 + $method = 'GET';
  94 + return $this->requestAccount($method, $path, $param);
  95 + }
  96 + //查询子账户划转历史 (仅适用子账户)
  97 + public function subUserHistory($param)
  98 + {
  99 + $path = '/sapi/v1/sub-account/transfer/subUserHistory';
  100 + $method = 'GET';
  101 + return $this->requestAccount($method, $path, $param);
  102 + }
  103 + //合约资金划转
  104 + public function futuresTransfer($param)
  105 + {
  106 + $path = '/sapi/v1/futures/transfer';
  107 + $method = 'POST';
  108 + return $this->requestAccount($method, $path, $param);
  109 + }
  110 + //子账户向子账户划转
  111 + public function subToSub($param)
  112 + {
  113 + $path = '/sapi/v1/sub-account/transfer/subToSub';
  114 + $method = 'POST';
  115 + return $this->requestAccount($method, $path, $param);
  116 + }
  117 + //获取用户资产
  118 + public function getUserAsset($param)
  119 + {
  120 + $path = '/sapi/v3/asset/getUserAsset';
  121 + $method = 'POST';
  122 + return $this->requestAccount($method, $path, $param);
  123 + }
  124 +
  125 +
  126 + /*
  127 + * ==================================
  128 + * 以下公共接口,无限apikey
  129 + * ==================================
  130 + */
  131 + //24小时成交数据
  132 +// static public function ticker24hr($param = [])
  133 +// {
  134 +// $path = '/fapi/v1/ticker/24hr';
  135 +// $method = 'GET';
  136 +// return self::requestMarket($method, $path, $param);
  137 +// }
  138 +
  139 +}
  140 +
  141 +?>
1 -<?php  
2 -  
3 -namespace Jiaoyin;  
4 -  
5 -class Test {  
6 - public function sayHello() {  
7 - return "Hello from My Private Library!";  
8 - }  
9 -}  
  1 +<?php
  2 +namespace Jiaoyin;
  3 +//格式化输出
  4 +function output(){
  5 + $args = func_get_args();
  6 + $outStr = '['.timeFormat('ms').']:';
  7 + foreach($args as $key => $value){
  8 + $value = is_array($value) ? json_encode($value) : $value;
  9 + if(is_bool($value)){
  10 + $value = $value ? 'bool:true':'bool:false';
  11 + }
  12 + $outStr .= count($args) - $key > 1 ? $value.' ' : $value;
  13 + }
  14 + echo $outStr.PHP_EOL;
  15 +}
  16 +//格式化时间
  17 +function timeFormat($type='s',$format='Y-m-d H:i:s'){
  18 + date_default_timezone_set('Asia/Shanghai');
  19 + $microTime = microtime();
  20 + list($msTime,$sTime) = explode(' ',$microTime);
  21 + $timeStr = date($format,$sTime);
  22 + if($type == 'ms'){
  23 + $timeStr .= '.'.sprintf("%03d",floor($msTime*1000));
  24 + }
  25 + return $timeStr;
  26 +}
  27 +
  28 +// 获取当前时间的微秒数
  29 +function getMicrotime()
  30 +{
  31 + list($uSec, $sec) = explode(' ', microtime());
  32 + return $sec*1000+round($uSec*1000);
  33 +}
  34 +
  35 +//获取精度
  36 +function getPrecision($number): int
  37 +{
  38 + $count = 0;
  39 + while($number < 1){
  40 + $number *= 10;
  41 + $count += 1;
  42 + }
  43 + return $count;
  44 +}
  45 +
  46 +function getIntervalUnit($interval,$type='s'){
  47 + $unitTime = 0;
  48 + if($interval == '1m'){
  49 + $unitTime = 60;
  50 + }
  51 + if($interval == '5m'){
  52 + $unitTime = 60*5;
  53 + }
  54 + if($interval == '15m'){
  55 + $unitTime = 60*15;
  56 + }
  57 + if($interval == '1h'){
  58 + $unitTime = 60*60;
  59 + }
  60 + if($interval == '4h'){
  61 + $unitTime = 60*60*4;
  62 + }
  63 + if($interval == '1d'){
  64 + $unitTime = 60*60*24;
  65 + }
  66 + return $type == 's' ? $unitTime : $unitTime*1000;
  67 +}
  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +class Curl{
  6 +
  7 + // get 获取数据
  8 + static public function httpGet($url, $param=[], $header=[]){
  9 + if(empty($url)){
  10 + return false;
  11 + }
  12 + if(count($param) > 0){
  13 + $url = $url.'?'.http_build_query($param);
  14 + }
  15 + $ch = curl_init();
  16 + $ch = self::curlSet($ch,$url, $header);
  17 + $output = curl_exec($ch);
  18 + if($output === false){
  19 + echo 'Curl error: ' . curl_error($ch);
  20 + }
  21 + curl_close($ch);
  22 + return $output;
  23 + }
  24 +
  25 + //post 获取数据
  26 + static public function httpPost($url, $param=[], $header=[]){
  27 + if(empty($url)){
  28 + return false;
  29 + }
  30 + if(count($param) > 0){
  31 + $url = $url.'?'.http_build_query($param);
  32 + }
  33 + $ch = curl_init();
  34 + $ch = self::curlSet($ch, $url, $header);
  35 + curl_setopt($ch, CURLOPT_POST, 1);
  36 + $output = curl_exec($ch);
  37 + if($output === false){
  38 + echo 'Curl error: ' . curl_error($ch);
  39 + }
  40 + curl_close($ch);
  41 + return $output;
  42 + }
  43 + //delete 请求
  44 + static public function httpDelete($url, $param=[], $header=[]){
  45 + if(empty($url)){
  46 + return false;
  47 + }
  48 + if(count($param) > 0){
  49 + $url = $url.'?'.http_build_query($param);
  50 + }
  51 + $ch = curl_init();
  52 + $ch = self::curlSet($ch, $url, $header);
  53 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
  54 + $output = curl_exec($ch);
  55 + if($output === false){
  56 + echo 'Curl error: ' . curl_error($ch);
  57 + }
  58 + curl_close($ch);
  59 + return $output;
  60 + }
  61 +
  62 + //curl 参数设置
  63 + static private function curlSet($ch,$url, $header){
  64 + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true) ;
  65 + curl_setopt($ch, CURLOPT_URL, $url);
  66 + //参数为1表示传输数据,为0表示直接输出显示。
  67 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  68 + //参数为0表示不带头文件,为1表示带头文件
  69 + curl_setopt($ch, CURLOPT_HEADER,0);
  70 + if(!empty($header)){
  71 + curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
  72 + }
  73 + // 关闭SSL验证
  74 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  75 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  76 + return $ch;
  77 + }
  78 +}
  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +use Swoole\Coroutine;
  6 +use Swoole\Coroutine\Http\Client;
  7 +use Swoole\WebSocket\Frame;
  8 +
  9 +class Websocket
  10 +{
  11 + private string $host = '';
  12 + private string $path = '';
  13 + private int $port = 443;
  14 + private bool $ssl = true;
  15 + private int $recvTimeout = 60;
  16 + public ?Client $client = null;
  17 + public string $url = '';
  18 + private $lastRecvTime = 0;
  19 + private $onOpen = null;
  20 + private $onMessage = null;
  21 + private $onClose = null;
  22 + private $onPing = null;
  23 + private $onPong = null;
  24 + private $pingState = true;
  25 + private $timerCheck = 0;
  26 + private $timerPing = 0;
  27 + private $desc = 'websocket未命名';
  28 + private $pingCount = 0;
  29 + private $pingDelay = 10000;//ping tick时间 10s
  30 +
  31 + // 例如:wss://fstream.binance.com/stream、ws://175.178.36.217:9528/spot/stream
  32 + public function __construct($url, $desc = null)
  33 + {
  34 + $this->url = $url;
  35 + $pattern = '/(ws{1,2}):\/\/([\w.a-zA-Z]+):*(\d*)([\/\-\wa-zA-Z?=.]*)/';
  36 + preg_match($pattern, $url, $result);
  37 + $this->ssl = $result[1] == 'wss';
  38 + $this->host = $result[2];
  39 + if (empty($result[3])) {
  40 + $this->port = $this->ssl ? 443 : 80;
  41 + } else {
  42 + $this->port = $result[3];
  43 + }
  44 + $this->path = empty($result[4]) ? '/' : $result[4];
  45 + if ($desc) {
  46 + $this->desc = 'websocket ' . $desc;
  47 + }
  48 + output($this->host,$this->port,$this->ssl,$this->path);
  49 + }
  50 +
  51 + public function push($data)
  52 + {
  53 + if ($this->client) {
  54 + $this->client->push($data);
  55 + } else {
  56 + output('push error, client is null');
  57 + }
  58 + }
  59 +
  60 + public function close()
  61 + {
  62 + swoole_timer_clear($this->timerPing);
  63 + swoole_timer_clear($this->timerCheck);
  64 + if ($this->client) {
  65 + $this->client->close();
  66 + }
  67 + }
  68 +
  69 + public function connect(callable $onOpen = null, callable $onMessage = null,
  70 + callable $onClose = null, $onPing = null, $onPong = null)
  71 + {
  72 + $this->close();
  73 + $this->pingCount = 0;
  74 + $this->onOpen = $onOpen;
  75 + $this->onMessage = $onMessage;
  76 + $this->onClose = $onClose;
  77 + $this->onPing = $onPing;
  78 + $this->onPong = $onPong;
  79 + Coroutine::create(function () use ($onOpen, $onMessage, $onClose, $onPing, $onPong) {
  80 + $this->client = new Client($this->host, $this->port, $this->ssl);
  81 + $this->client->set(['timeout' => 5]);
  82 + $ret = $this->client->upgrade($this->path);
  83 + if ($ret) {
  84 + output($this->desc, "连接成功");
  85 + swoole_timer_after(50, function () use ($onOpen) {
  86 + if ($onOpen) {
  87 + call_user_func($onOpen, $this->client);
  88 + }
  89 + $this->sendPing();
  90 + });
  91 + while ($this->client) {
  92 + $frame = $this->client->recv(60);
  93 + if (!$frame && $this->client->errCode!=60) {
  94 + output($this->desc, "错误数据", $frame);
  95 + break;
  96 + }
  97 + $this->lastRecvTime = time();
  98 + if (is_object($frame) && get_class($frame) === Frame::class) {
  99 + if ($frame->opcode == WEBSOCKET_OPCODE_PING) {
  100 + $this->push(self::createPongData($frame->data));
  101 + if ($onPing) {
  102 + call_user_func($onPing, $frame->data);
  103 + }
  104 + }
  105 + if ($frame->opcode == WEBSOCKET_OPCODE_PONG) {
  106 + $this->recvPongData($frame->data);
  107 + if($onPong){
  108 + call_user_func($onPong, $frame->data);
  109 + }
  110 + }
  111 + if ($frame->opcode == WEBSOCKET_OPCODE_TEXT) {
  112 + call_user_func($onMessage, $frame->data);
  113 + }
  114 + if ($frame->opcode == WEBSOCKET_OPCODE_CLOSE) {
  115 + output($this->desc, "服务器主动关闭连接,连接关闭");
  116 + break;
  117 + }
  118 + }
  119 + \Swoole\Coroutine::defer(function () use ($onClose) {
  120 + output($this->desc, "协程退出");
  121 + $this->client = null;
  122 + if ($onClose) {
  123 + call_user_func($onClose);
  124 + }
  125 + });
  126 + }
  127 + } else {
  128 + if($onClose){
  129 + call_user_func($onClose);
  130 + }
  131 + output($this->desc, "升级websocket连接失败,1s后重连");
  132 + swoole_timer_after(1000,function (){
  133 + $this->connect($this->onOpen, $this->onMessage, $this->onClose, $this->onPing, $this->onPong);
  134 + });
  135 + }
  136 + });
  137 + }
  138 +
  139 + static public function createPongData($data = null)
  140 + {
  141 + $frame = new Frame();
  142 + if ($data) {
  143 + $frame->data = $data;
  144 + }
  145 + $frame->opcode = WEBSOCKET_OPCODE_PONG;
  146 + return $frame;
  147 + }
  148 +
  149 + static public function createPingData()
  150 + {
  151 + $frame = new Frame();
  152 + $frame->opcode = WEBSOCKET_OPCODE_PING;
  153 + $frame->data = getMicrotime();
  154 + return $frame;
  155 + }
  156 +
  157 + private function sendPing()
  158 + {
  159 + $this->push(self::createPingData());
  160 + $this->pingState = false;
  161 + $this->timerCheck = swoole_timer_after(5000, function () {
  162 + if (!$this->pingState) {
  163 + output($this->desc, 'ping pong 超时,重新连接');
  164 + $this->connect($this->onOpen, $this->onMessage, $this->onClose, $this->onPing, $this->onPong);
  165 + }
  166 + });
  167 + }
  168 +
  169 + private function recvPongData($data)
  170 + {
  171 + $this->pingState = true;
  172 + $this->pingCount += 1;
  173 + if ($this->pingCount % 100 == 0) {
  174 + output($this->desc, '连接稳定,已连接时间:', $this->pingCount * $this->pingDelay / 1000, '秒');
  175 + }
  176 + swoole_timer_clear($this->timerCheck);
  177 + $this->timerPing = swoole_timer_after($this->pingDelay, function () {
  178 + $this->sendPing();
  179 + });
  180 + }
  181 +}
  1 +<?php
  2 +namespace Jiaoyin;
  3 +
  4 +use Jiaoyin;
  5 +class Feishu{
  6 + //发送预警通知
  7 + static public function send($content)
  8 + {
  9 + $url = 'https://open.feishu.cn/open-apis/bot/v2/hook/f30bbb72-091c-499d-a577-43c45dceb158';
  10 + $content = [
  11 + 'msg_type'=>"text",
  12 + 'content'=>[
  13 + 'text'=>$content
  14 + ]
  15 + ];
  16 + $con = json_encode($content);
  17 + return self::send_post_json($url,$con);
  18 + }
  19 +
  20 + static public function sendNoError($content)
  21 + {
  22 + $url = 'https://open.feishu.cn/open-apis/bot/v2/hook/a344e313-4d5d-4aa4-912b-dda37b2e3ee8';
  23 + $content = [
  24 + 'msg_type'=>"text",
  25 + 'content'=>[
  26 + 'text'=>$content
  27 + ]
  28 + ];
  29 + $con = json_encode($content);
  30 + return self::send_post_json($url,$con);
  31 + }
  32 +
  33 + static public function notice($content,$channel="warning")
  34 + {
  35 + $urls = [
  36 + 'follow' => 'https://open.feishu.cn/open-apis/bot/v2/hook/f30bbb72-091c-499d-a577-43c45dceb158',
  37 + 'warning' => 'https://open.feishu.cn/open-apis/bot/v2/hook/d48c2e4a-0ef9-4684-88d4-e62d878fdaca',
  38 + 'error' => 'https://open.feishu.cn/open-apis/bot/v2/hook/a344e313-4d5d-4aa4-912b-dda37b2e3ee8',
  39 + ];
  40 + $url = $urls[$channel] ?? $urls['warning'];
  41 + $content = [
  42 + 'msg_type'=>"text",
  43 + 'content'=>[
  44 + 'text'=>$content
  45 + ]
  46 + ];
  47 + $con = json_encode($content);
  48 + return self::send_post_json($url,$con);
  49 + }
  50 +
  51 +
  52 + static public function send_post_json($url, $jsonStr)
  53 + {
  54 + $ch = curl_init();
  55 + curl_setopt($ch, CURLOPT_POST, 1);
  56 + curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
  57 + curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
  58 + curl_setopt($ch, CURLOPT_URL, $url);
  59 + curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
  60 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  61 + curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  62 + 'Content-Type: application/json; charset=utf-8',
  63 + 'Content-Length: ' . strlen($jsonStr)
  64 + )
  65 + );
  66 + $response = curl_exec($ch);
  67 + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  68 + curl_close($ch);
  69 + return array($httpCode, $response);
  70 + }
  71 +}