#php #coinbase-api
Вопрос:
У меня проблема с авторизацией. Я пытаюсь написать свой собственный код для управления API. Я не могу понять, почему я получаю ошибку {" errors ": [{" id ":" authentication_error "," message ":" invalid timestamp "}]}
Вот полный текст моего запроса ( CB-TEXT-TO-SIGN
это отладочная информация, CB-ACCESS-KEY
и секретный ключ api верен. CB-ACCESS-TIMESTAMP
выглядит правильно):
НЕОБРАБОТАННЫЙ HTTP-КОД
GET /v2/accounts HTTP/1.1
Host: api.coinbase.com
Accept: */*
CB-ACCESS-KEY: O###########b
CB-ACCESS-SIGN: YCanHaHFXdFu6lidCroLIUgk3ayzvG/oCwR/68MfLYw=
CB-ACCESS-TIMESTAMP: 2021-08-12T15:04:29.175Z
CB-TEXT-TO-SIGN: 2021-08-12T15:04:29.175ZGET/v2/accounts
Content-Type: application/json
User-Agent: Mozilla/5.0
HTTP/1.1 401 Unauthorized
Date: Thu, 12 Aug 2021 15:04:11 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: private, no-cache, must-revalidate
Content-Disposition: attachment; filename=response.json
Content-Security-Policy: <DELETED>
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
Set-Cookie: <DELETED>
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Trace-Id: 8618971493290804459
Vary: Origin,Accept-Encoding
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-Powered-By: Proof-of-Work
X-Request-Id: 1a0f2ff3-6fa8-49b3-b9ca-ee5d80b54d27
X-Xss-Protection: 1; mode=block
CF-Cache-Status: DYNAMIC
Set-Cookie: <DELETED>
Set-Cookie: <DELETED>
Server: cloudflare
CF-RAY: 67da983b9a4ab514-VNO
TIMESTAMP: 2021-08-12T15:04:30.203Z
{"errors":[{"id":"authentication_error","message":"invalid timestamp"}]}
исходный код
<?php
class Config{
public static $config=[
"apiKey"=>"O##############b",
"apiSecret"=>"F##############################e",
//"passphrase"=>'',
];
public static $debug=1;
}
class Utils
{
static $apiKey = "O##############b";
static $apiSecret = "F##############################e";
//static $passphrase = '';
static $textToSign = '';
const FUTURE_API_URL = 'https://api.coinbase.com';
const SERVER_TIMESTAMP_URL = '/time';
public function __construct($config)
{
self::setParams($config);
}
public static function request($requestPath, $params, $method)
{
if (strtoupper($method) == 'GET') {
$requestPath .= $params ? '?'.http_build_query($params) : '';
$params = [];
}
$url = self::FUTURE_API_URL.$requestPath;
$ch= curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
$body = $params ? json_encode($params, JSON_UNESCAPED_SLASHES) : '';
$timestamp = self::getTimestamp();
$sign = self::signature($timestamp, $method, $requestPath, $body, self::$apiSecret);
$headers = self::getHeader(self::$apiKey, $sign, $timestamp, /*self::$passphrase,*/ self::$textToSign);
if($method == "POST") {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
// curl_setopt($ch, CURLOPT_TIMEOUT_MS,60);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT,true);
curl_setopt($ch, CURLOPT_HEADER, true);
// curl_setopt($ch, CURLOPT_NOBODY,true);
$return = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headerTotal = strlen($return);
$bodySize = $headerTotal - $headerSize;
$body = substr($return, $headerSize, $bodySize);
if(!curl_errno($ch))
{
$info = curl_getinfo($ch,CURLINFO_HEADER_OUT);
if (Config::$debug)
{
}
switch (true)
{
case Config::$debug==1;
echo ($info);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
// $header = substr($return, 0, $headerSize);
print_r(substr($return, 0, $headerSize-2));
print_r("TIMESTAMP: ".self::getTimestamp());
print_r("nn");
print_r($body);
print_r("nn");
break;
case Config::$debug==2;
$ntime = self::getTimestamp();
print_r($ntime." $bodyn");
break;
}
}
// $body = substr($sContent, $headerSize, $bodySize);
// print_r("headerSize:".$headerSize."n");
// print_r("headerTotal:".$headerTotal."n");
// print_r("bodySize:".$bodySize."n");
$body = json_decode($body,true);
return $body;
}
public static function getHeader($apiKey, $sign, $timestamp, /*$passphrase,*/ $textToSign)
{
$headers = array();
$headers[] = "CB-ACCESS-KEY: $apiKey";
$headers[] = "CB-ACCESS-SIGN: $sign";
$headers[] = "CB-ACCESS-TIMESTAMP: $timestamp";
/* $headers[] = "CB-ACCESS-PASSPHRASE: $passphrase"; */
$headers[] = "CB-TEXT-TO-SIGN: $textToSign";
$headers[] = "Content-Type: application/json";
$headers[] = "User-Agent: Mozilla/5.0";
return $headers;
}
public static function getTimestamp()
{
ini_set("date.timezone","UTC");
return date("Y-m-dTH:i:s"). substr((string)microtime(), 1, 4) . 'Z';
}
function dateToTimestamp($isoTime)
{
@list($usec, $sec) = explode(".", $isoTime);
$date = strtotime($usec);
$return_data = str_pad($date.$sec,13,"0",STR_PAD_RIGHT);
return substr($return_data, 0, -1);
}
public static function getServerTimestamp(){
try{
$response = file_get_contents(self::FUTURE_API_URL.self::SERVER_TIMESTAMP_URL);
$response = json_decode($response,true);
return $response['iso'];
}catch (Exception $e){
return '';
}
}
public static function signature($timestamp, $method, $requestPath, $body, $secretKey)
{
$message = (string) $timestamp . strtoupper($method) . $requestPath . (string) $body;
self::$textToSign = $message;
return base64_encode(hash_hmac('sha256', $message, $secretKey, true));
}
public static function wsSignature($timestamp, $method, $requestPath, $body, $secretKey)
{
$message = (string) $timestamp . strtoupper($method) . $requestPath . (string) $body;
$ntime = self::getTimestamp();
print_r($ntime." TEXT-TO-SIGN:$messagen");
return base64_encode(hash_hmac('sha256', $message, $secretKey, true));
}
public static function get_millisecond()
{
$time = microtime(true);
$msec=round($time*1000);
return $msec/1000;
}
public static function setParams($configs){
self::$apiKey=$configs["apiKey"];
self::$apiSecret=$configs["apiSecret"];
//self::$passphrase=$configs["passphrase"];
}
}
$obj = new utils(Config::$config);
echo $res = $obj -> request('/v2/accounts', [], 'GET');
Any ideas, please?