作者 karlet

feat:ok修改

  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);
  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 +}