正在显示
3 个修改的文件
包含
261 行增加
和
4 行删除
src/Auth.php
0 → 100644
| 1 | +<?php | ||
| 2 | +namespace Jiaoyin; | ||
| 3 | + | ||
| 4 | +class Auth | ||
| 5 | +{ | ||
| 6 | + /** | ||
| 7 | + * 加密解密字符串 | ||
| 8 | + * @param $string 明文 或 密文 | ||
| 9 | + * @param $operation DECODE表示解密,其它表示加密 | ||
| 10 | + * @param $key 密钥 | ||
| 11 | + * @param $expiry 密文有效期 | ||
| 12 | + * @author nish | ||
| 13 | + */ | ||
| 14 | + public static function authcode($string, $operation = 'DECODE', $key = 'fhjxs', $expiry = 0) | ||
| 15 | + { | ||
| 16 | + // 过滤特殊字符 | ||
| 17 | + if ($operation == 'DECODE') { | ||
| 18 | + $string = str_replace('[a]', '+', $string); | ||
| 19 | + $string = str_replace('[b]', '&', $string); | ||
| 20 | + $string = str_replace('[c]', '/', $string); | ||
| 21 | + } | ||
| 22 | + // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙 | ||
| 23 | + $ckey_length = 4; | ||
| 24 | + // 密匙 | ||
| 25 | + $key = md5($key ? $key : 'fhj'); | ||
| 26 | + // 密匙a会参与加解密 | ||
| 27 | + $keya = md5(substr($key, 0, 16)); | ||
| 28 | + // 密匙b会用来做数据完整性验证 | ||
| 29 | + $keyb = md5(substr($key, 16, 16)); | ||
| 30 | + // 密匙c用于变化生成的密文 | ||
| 31 | + $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : ''; | ||
| 32 | + // 参与运算的密匙 | ||
| 33 | + $cryptkey = $keya . md5($keya . $keyc); | ||
| 34 | + $key_length = strlen($cryptkey); | ||
| 35 | + // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),解密时会通过这个密匙验证数据完整性 | ||
| 36 | + // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确 | ||
| 37 | + $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string; | ||
| 38 | + $string_length = strlen($string); | ||
| 39 | + $result = ''; | ||
| 40 | + $box = range(0, 255); | ||
| 41 | + $rndkey = array(); | ||
| 42 | + // 产生密匙簿 | ||
| 43 | + for ($i = 0; $i <= 255; $i++) { | ||
| 44 | + $rndkey[$i] = ord($cryptkey[$i % $key_length]); | ||
| 45 | + } | ||
| 46 | + // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度 | ||
| 47 | + for ($j = $i = 0; $i < 256; $i++) { | ||
| 48 | + $j = ($j + $box[$i] + $rndkey[$i]) % 256; | ||
| 49 | + $tmp = $box[$i]; | ||
| 50 | + $box[$i] = $box[$j]; | ||
| 51 | + $box[$j] = $tmp; | ||
| 52 | + } | ||
| 53 | + // 核心加解密部分 | ||
| 54 | + for ($a = $j = $i = 0; $i < $string_length; $i++) { | ||
| 55 | + $a = ($a + 1) % 256; | ||
| 56 | + $j = ($j + $box[$a]) % 256; | ||
| 57 | + $tmp = $box[$a]; | ||
| 58 | + $box[$a] = $box[$j]; | ||
| 59 | + $box[$j] = $tmp; | ||
| 60 | + // 从密匙簿得出密匙进行异或,再转成字符 | ||
| 61 | + $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); | ||
| 62 | + } | ||
| 63 | + if ($operation == 'DECODE') { | ||
| 64 | + // substr($result, 0, 10) == 0 验证数据有效性 | ||
| 65 | + // substr($result, 0, 10) - time() > 0 验证数据有效性 | ||
| 66 | + // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性 | ||
| 67 | + // 验证数据有效性,请看未加密明文的格式 | ||
| 68 | + if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) { | ||
| 69 | + return substr($result, 26); | ||
| 70 | + } else { | ||
| 71 | + return ''; | ||
| 72 | + } | ||
| 73 | + } else { | ||
| 74 | + // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因 | ||
| 75 | + // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码 | ||
| 76 | + $ustr = $keyc . str_replace('=', '', base64_encode($result)); | ||
| 77 | + // 过滤特殊字符 | ||
| 78 | + $ustr = str_replace('+', '[a]', $ustr); | ||
| 79 | + $ustr = str_replace('&', '[b]', $ustr); | ||
| 80 | + $ustr = str_replace('/', '[c]', $ustr); | ||
| 81 | + return $ustr; | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | +} |
| @@ -26,12 +26,17 @@ class Curl{ | @@ -26,12 +26,17 @@ class Curl{ | ||
| 26 | if(empty($url)){ | 26 | if(empty($url)){ |
| 27 | return false; | 27 | return false; |
| 28 | } | 28 | } |
| 29 | - if(count($param) > 0){ | ||
| 30 | - $url = $url.'?'.http_build_query($param); | ||
| 31 | - } | ||
| 32 | $ch = curl_init(); | 29 | $ch = curl_init(); |
| 33 | $ch = self::curlSet($ch, $url, $header); | 30 | $ch = self::curlSet($ch, $url, $header); |
| 34 | - curl_setopt($ch, CURLOPT_POST, 1); | 31 | + $opts=[]; |
| 32 | + $opts[CURLOPT_POST]=1; | ||
| 33 | + $opts[CURLOPT_USERAGENT]="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.98 Safari/537.36"; | ||
| 34 | + if (!empty($header) && in_array('Content-Type:application/json', $header)) { | ||
| 35 | + $opts[CURLOPT_POSTFIELDS]= json_encode($param); | ||
| 36 | + } else { | ||
| 37 | + $opts[CURLOPT_POSTFIELDS] = http_build_query($param); | ||
| 38 | + } | ||
| 39 | + curl_setopt_array($ch, $opts); | ||
| 35 | $output = curl_exec($ch); | 40 | $output = curl_exec($ch); |
| 36 | if($output === false){ | 41 | if($output === false){ |
| 37 | echo 'Curl error: ' . curl_error($ch); | 42 | echo 'Curl error: ' . curl_error($ch); |
src/OkApi.php
0 → 100644
| 1 | +<?php | ||
| 2 | +namespace Jiaoyin; | ||
| 3 | + | ||
| 4 | +/* | ||
| 5 | + 所有接口 | ||
| 6 | +*/ | ||
| 7 | +class OkApi | ||
| 8 | +{ | ||
| 9 | + protected string $host = 'https://www.okx.com'; | ||
| 10 | + protected string $apikey = ''; | ||
| 11 | + protected string $secret = ''; | ||
| 12 | + protected string $apipwd = ''; | ||
| 13 | + protected string $nonce = ''; | ||
| 14 | + protected string $signature = ''; | ||
| 15 | + protected array $headers = []; | ||
| 16 | + protected string $method = ''; | ||
| 17 | + protected array $param = []; | ||
| 18 | + protected string $path = ''; | ||
| 19 | + protected array $options = []; | ||
| 20 | + | ||
| 21 | + public function __construct($apikey = '', $secret = '', $apipwd = '', $host = '') | ||
| 22 | + { | ||
| 23 | + $this->apikey = $apikey; | ||
| 24 | + $this->secret = $secret; | ||
| 25 | + $this->apipwd = $apipwd; | ||
| 26 | + if (!empty($host)) { | ||
| 27 | + $this->host = $host; | ||
| 28 | + } | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + // 核心认证过程 | ||
| 32 | + protected function auth() | ||
| 33 | + { | ||
| 34 | + $this->generateNonce(); | ||
| 35 | + $this->generateSignature(); | ||
| 36 | + $this->createHeaders(); | ||
| 37 | + } | ||
| 38 | + // 生成时间戳 | ||
| 39 | + protected function generateNonce() | ||
| 40 | + { | ||
| 41 | + $this->nonce = gmdate('Y-m-d\TH:i:s\.000\Z'); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + // 生成签名 | ||
| 45 | + protected function generateSignature() | ||
| 46 | + { | ||
| 47 | + $body = ''; | ||
| 48 | + $path = $this->method . $this->path; | ||
| 49 | + if (!empty($this->param)) { | ||
| 50 | + if ($this->method == 'GET') { | ||
| 51 | + $path .= '?' . http_build_query($this->param); | ||
| 52 | + } else { | ||
| 53 | + $body = json_encode($this->param); | ||
| 54 | + } | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + $this->signature = base64_encode(hash_hmac('sha256', $this->nonce . $path . $body, $this->secret, true)); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + // 构建请求URL | ||
| 61 | + private function createUrl($path): string | ||
| 62 | + { | ||
| 63 | + return $this->host . $path; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + // 构建请求头 | ||
| 67 | + private function createHeaders(): array | ||
| 68 | + { | ||
| 69 | + $headers = [ | ||
| 70 | + 'Content-Type' => 'application/json', | ||
| 71 | + ]; | ||
| 72 | + if (!empty($this->apikey) && !empty($this->secret)) { | ||
| 73 | + $headers = array_merge($headers, [ | ||
| 74 | + 'OK-ACCESS-KEY' => $this->apikey, | ||
| 75 | + 'OK-ACCESS-TIMESTAMP' => $this->nonce, | ||
| 76 | + 'OK-ACCESS-PASSPHRASE' => $this->apipwd, | ||
| 77 | + 'OK-ACCESS-SIGN' => $this->signature, | ||
| 78 | + ]); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + $headers_array=[]; | ||
| 82 | + foreach ($headers as $key => $value){ | ||
| 83 | + $headers_array[]=$key.':'.$value; | ||
| 84 | + } | ||
| 85 | + $this->headers = $headers_array; | ||
| 86 | + return $headers; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + /* | ||
| 90 | + * 公共请求接口 | ||
| 91 | + * $type 1: 需鉴权 2: 不需鉴权 | ||
| 92 | + * */ | ||
| 93 | + public function request($method, $path, $param,$type=1) | ||
| 94 | + { | ||
| 95 | + $this->method = strtoupper($method); | ||
| 96 | + $this->path = $path; | ||
| 97 | + $this->param = $param; | ||
| 98 | + if($type==2){ | ||
| 99 | + $this->createHeaders(); | ||
| 100 | + }else{ | ||
| 101 | + if (empty($this->apikey) || empty($this->secret) || empty($this->apipwd)) { | ||
| 102 | + return ['code' => -1, 'msg' => 'apikey, secret or apipwd is empty']; | ||
| 103 | + } | ||
| 104 | + $this->auth(); | ||
| 105 | + } | ||
| 106 | + if (!in_array($this->method, ['GET', 'POST', 'DELETE'])) { | ||
| 107 | + return ['code' => -1, 'msg' => 'Invalid HTTP method']; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + $url = $this->createUrl($path); | ||
| 111 | + switch ($this->method) { | ||
| 112 | + case 'GET': | ||
| 113 | + $data = Curl::httpGet($url, $this->param, $this->headers); | ||
| 114 | + break; | ||
| 115 | + case 'POST': | ||
| 116 | + $data = Curl::httpPost($url, $this->param, $this->headers); | ||
| 117 | + break; | ||
| 118 | + case 'DELETE': | ||
| 119 | + $data = Curl::httpDelete($url, $this->param, $this->headers); | ||
| 120 | + break; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + return json_decode($data, true); | ||
| 124 | + } | ||
| 125 | + /** | ||
| 126 | + * 合约账户余额查询 | ||
| 127 | + */ | ||
| 128 | + public function getBalance($param=[]) | ||
| 129 | + { | ||
| 130 | + $path = '/api/v5/account/balance'; | ||
| 131 | + return $this->request('GET', $path, $param); | ||
| 132 | + } | ||
| 133 | + /** | ||
| 134 | + * 资金账户余额查询 | ||
| 135 | + */ | ||
| 136 | + public function getAssetBalance($param=[]) | ||
| 137 | + { | ||
| 138 | + $path = '/api/v5/asset/balances'; | ||
| 139 | + return $this->request('GET', $path, $param); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * 获取持仓信息 | ||
| 144 | + */ | ||
| 145 | + public function getPositions($param) | ||
| 146 | + { | ||
| 147 | + $path = '/api/v5/account/positions'; | ||
| 148 | + return $this->request('GET', $path, $param); | ||
| 149 | + } | ||
| 150 | + /* | ||
| 151 | + * 资金划转 | ||
| 152 | + * */ | ||
| 153 | + public function transfer($param) | ||
| 154 | + { | ||
| 155 | + $path = '/api/v5/asset/transfer'; | ||
| 156 | + return $this->request('POST', $path, $param); | ||
| 157 | + } | ||
| 158 | + /* | ||
| 159 | + * 公共请求接口 | ||
| 160 | + * */ | ||
| 161 | + public function getTransferHistory($path,$param) | ||
| 162 | + { | ||
| 163 | + $path = '/api/v5/asset/bills'; | ||
| 164 | + return $this->request('GET', $path, $param); | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | +} |
-
请 注册 或 登录 后发表评论