OKX v5 API PHP请求签名报错‘Invalid Sign’求助
解决OKX API签名错误(50113 Invalid Sign)
你的代码存在两个核心问题导致签名验证失败,以下是针对性修复方案:
1. 哈希签名生成逻辑错误
OKX要求签名是HMAC-SHA256的二进制结果进行Base64编码,但你当前调用hash_hmac时默认返回十六进制字符串,直接对其Base64编码会导致签名不匹配。需要给hash_hmac添加第四个参数true,获取原始二进制哈希值:
原代码:
$signed = base64_encode( hash_hmac( 'sha256', $timestamp . 'GET' . $requestpath, $secretkey ) );
修正后:
$signed = base64_encode( hash_hmac( 'sha256', $timestamp . 'GET' . $requestpath, $secretkey, true ) );
2. 时间戳格式不符合要求
OKX API要求时间戳为毫秒级精度的ISO8601格式,但PHP的.v格式符会输出6位微秒,不符合平台要求。调整时间戳生成逻辑,截取微秒前三位作为毫秒:
原代码:
$timestamp = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) ); $timestamp = $timestamp->format( 'Y-m-d\TH:i:s.v\Z' );
修正后:
$timestamp = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) ); $milliseconds = substr($timestamp->format('u'), 0, 3); $timestamp = $timestamp->format("Y-m-d\TH:i:s") . "." . $milliseconds . "\Z";
额外验证项
- 确认API密钥、Passphrase、Secret Key完全正确,无多余空格或复制错误
- 检查请求路径是否准确,
/api/v5/account/balance是查询余额的正确路径 - 确保签名中的请求方法(
GET)和实际请求方法完全一致,大小写敏感
修复后的完整函数示例:
function api_request( $endpoint, $parameters ) { $timestamp = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) ); $milliseconds = substr($timestamp->format('u'), 0, 3); $timestamp = $timestamp->format("Y-m-d\TH:i:s") . "." . $milliseconds . "\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 ); $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(); curl_setopt_array( $curl, array( CURLOPT_HTTPHEADER => $header, CURLOPT_URL => $url . $requestpath, CURLOPT_RETURNTRANSFER => 1 ) ); $response = curl_exec($curl); curl_close($curl); $response = json_decode( $response, true ); return $response; } // CHECK BALANCE $a = api_request( 'account/balance', array() ); echo( '<pre>' ); var_dump( $a ); echo( '</pre>' );
内容的提问来源于stack exchange,提问作者eggbeats
相关产品推荐
相关产品推荐

