OKX v5 API如何在PHP中签名请求

nwnhqdif  于 2023-05-05  发布在  PHP
关注(0)|答案(1)|浏览(217)

bounty还有4天到期。回答此问题可获得+500声望奖励。Bogdan Bogdanov想要引起更多关注这个问题:你有12个小时来解决它...

我试图签署一个API请求到OKX,但一直得到“无效的签名”的响应。这很难调试,所以希望以前有人这样做过。这就是我的:

// AUTHENTICATION https://www.okx.com/docs-v5/en/#rest-api-authentication

function api_request( $endpoint, $parameters ) {

    $timestamp = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) );
    $timestamp = $timestamp->format( 'Y-m-d\TH:i:s.v\Z' );
    $header = array( );

    $passphrase = 'xxx';
    $apikey = 'xxx';
    $secretkey = 'xxx';
    $url = 'https://aws.okx.com';
    
    // build request path

    $requestpath = '/api/v5/' . $endpoint;
    if( count( $parameters ) > 0 ) {
        $parameters = http_build_query( $parameters ); // query string encode the parameters
        $requestpath .= '?' . $parameters;    
    }

    // build header
    
    $signed = base64_encode( hash_hmac( 'sha256', $timestamp . 'GET' . $requestpath, $secretkey ) );

    $header[] = 'OK-ACCESS-KEY: ' . $apikey;
    $header[] = 'OK-ACCESS-SIGN: ' . $signed;
    $header[] = 'OK-ACCESS-TIMESTAMP: ' . $timestamp;
    $header[] = 'OK-ACCESS-PASSPHRASE: ' . $passphrase;
    
    // send request and receive response

    $curl = curl_init(); // Get cURL resource
    curl_setopt_array( $curl, array( // Set cURL options
        CURLOPT_HTTPHEADER => $header,      // set the header
        CURLOPT_URL => $url . $requestpath,        // set the request URL
        CURLOPT_RETURNTRANSFER => 1         // ask for raw response instead of bool
    ) );

    $response = curl_exec($curl); // Send the request, save the response
    curl_close($curl); // Close request
    
    $response = json_decode( $response, true ); // Convert to array
    
    return $response;
    
}

// CHECK BALANCE https://www.okx.com/docs-v5/en/#rest-api-funding-get-balance

$a = api_request( 'account/balance', array() );
echo( '<pre>' ); var_dump( $a ); echo( '</pre>' );

这就是我得到的:

array(2) {
  ["msg"]=>
  string(12) "Invalid Sign"
  ["code"]=>
  string(5) "50113"
}

我试着在$requestpath中包含基本URL,带或不带查询参数等。我也不是很熟悉哈希,我见过python脚本试图做同样的事情,它会用这样的东西来哈希它:hash_hmac( 'sha256', bytes( $message, 'utf8' ), bytes( $secret, 'utf8' ),不确定我是否应该在PHP中也使用这样的东西。

gr8qqesn

gr8qqesn1#

在创建签名时有一个小错误。您应该向hash_hmac函数添加第四个参数true,以返回原始二进制格式。
因此,签名的最终代码应该如下所示:

$signed = base64_encode(hash_hmac('sha256', $timestamp . 'GET' . $requestpath, $secretkey, true));

最终工作代码:

<?php

// AUTHENTICATION https://www.okx.com/docs-v5/en/#rest-api-authentication

function api_request( $endpoint, $parameters ) {

    $timestamp = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) );
    $timestamp = $timestamp->format( 'Y-m-d\TH:i:s.v\Z' );
    $header = array( );

    $passphrase = 'xxx';
    $apikey = 'xxx';
    $secretkey = 'xxx';
    $url = 'https://aws.okx.com';

    // build request path

    $requestpath = '/api/v5/' . $endpoint;
    if( count( $parameters ) > 0 ) {
        $parameters = http_build_query( $parameters ); // query string encode the parameters
        $requestpath .= '?' . $parameters;
    }

    // build header

    $signed = base64_encode( hash_hmac( 'sha256', $timestamp . 'GET' . $requestpath, $secretkey, true ) );

    $header[] = 'OK-ACCESS-KEY: ' . $apikey;
    $header[] = 'OK-ACCESS-SIGN: ' . $signed;
    $header[] = 'OK-ACCESS-TIMESTAMP: ' . $timestamp;
    $header[] = 'OK-ACCESS-PASSPHRASE: ' . $passphrase;

    // send request and receive response

    $curl = curl_init(); // Get cURL resource
    curl_setopt_array( $curl, array( // Set cURL options
        CURLOPT_HTTPHEADER => $header,      // set the header
        CURLOPT_URL => $url . $requestpath,        // set the request URL
        CURLOPT_RETURNTRANSFER => 1         // ask for raw response instead of bool
    ) );

    $response = curl_exec($curl); // Send the request, save the response
    curl_close($curl); // Close request

    $response = json_decode( $response, true ); // Convert to array

    return $response;

}

// CHECK BALANCE https://www.okx.com/docs-v5/en/#rest-api-funding-get-balance

$a = api_request( 'account/balance', array() );
echo( '<pre>' ); var_dump( $a ); echo( '</pre>' );

使用3个终点进行测试:帐户/余额帐户/利率帐户/交易费

已更新:在下面添加了适用于两种请求类型(GET和POST)的代码:

<?php

// AUTHENTICATION https://www.okx.com/docs-v5/en/#rest-api-authentication

function api_request( $endpoint, $type = 'GET', $parameters = []) {

    $timestamp = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) );
    $timestamp = $timestamp->format( 'Y-m-d\TH:i:s.v\Z' );
    $header = array( );

    $passphrase = 'xxx';
    $apikey = 'xxx';
    $secretkey = 'xxx';
    $url = 'https://aws.okx.com';

    // build request path

    $requestpath = '/api/v5/' . $endpoint;
    $body = '';
    if( count( $parameters ) > 0) {
        if ($type === 'GET') {
            $parameters = http_build_query($parameters); // query string encode the parameters
            $requestpath .= '?' . $parameters;
        } else {
            $body = json_encode($parameters);
        }
    }

    // build header

    $signed = base64_encode( hash_hmac( 'sha256', $timestamp . $type . $requestpath . $body, $secretkey, true ) );

    $header[] = 'Content-Type: application/json';
    $header[] = 'OK-ACCESS-KEY: ' . $apikey;
    $header[] = 'OK-ACCESS-SIGN: ' . $signed;
    $header[] = 'OK-ACCESS-TIMESTAMP: ' . $timestamp;
    $header[] = 'OK-ACCESS-PASSPHRASE: ' . $passphrase;

    // send request and receive response

    $curl = curl_init(); // Get cURL resource
    curl_setopt_array( $curl, array( // Set cURL options
        CURLOPT_HTTPHEADER => $header,      // set the header
        CURLOPT_URL => $url . $requestpath,        // set the request URL
        CURLOPT_RETURNTRANSFER => 1         // ask for raw response instead of bool
    ) );
    if ($type === 'POST') {
        curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
    }
    $response = curl_exec($curl); // Send the request, save the response
    curl_close($curl); // Close request

    $response = json_decode( $response, true ); // Convert to array

    return $response;

}

// CHECK BALANCE https://www.okx.com/docs-v5/en/#rest-api-funding-get-balance

$a = api_request( 'trade/order', 'POST', array(
    'instId' => 'BTC-USDT',
    'tdMode' => 'cash',
    'side' => 'buy',
    'ordType' => 'limit',
    'px' => '1000',
    'sz' => '0.01'
) );

echo( '<pre>' ); var_dump( $a ); echo( '</pre>' );

如果你想在DEMO交易环境中测试你的代码,不要忘记添加一个自定义头:$header[] = 'x-simulated-trading: 1';

相关问题