PHP cURL调用Netsuite Oauth HMAC-SHA256 GET接口报INVALID_LOGIN_ATTEMPT错误
问题根因与修复方案
你遇到的INVALID_LOGIN_ATTEMPT错误由以下几个可复现的问题导致,逐一修复即可正常请求:
- 缺失签名参数:URL查询串中包含
deploy=1,但你当前的签名基串拼接逻辑没有加入该参数,NetSuite验签时会自动包含所有请求参数,直接导致签名校验失败 - 参数顺序不规范:OAuth 1.0规范强制要求所有参与基串拼接的参数(包含OAuth标准参数和业务查询参数)必须按ASCII码升序排列,手动拼接顺序如果和服务端排序逻辑不一致会直接验签失败
- 多余请求头干扰:GET请求无请求体,你额外添加的
Content-Type: application/json头会触发NetSuite的安全校验拦截 - CURL请求方法兼容问题:部分低版本CURL对
CURLOPT_CUSTOMREQUEST的GET请求处理存在偏差,建议使用原生GET配置
修正后完整代码
$httpMethod = "GET"; $projectid = "xxx"; $taskid = "xxx"; $script = "xxx"; $deploy = "1"; $accountID = 'xxxxx-sb1'; $realm = "xxxxx_SB1"; $url = 'https://'.$accountID.'.restlets.api.netsuite.com/app/site/hosting/restlet.nl'; $ckey = "xxxxx"; //Consumer Key $csecret = "xxxxx"; //Consumer Secret $tkey = "xxxxx"; //Token ID $tsecret = "xxxxx"; //Token Secret $timestamp= time(); $nonce= uniqid(mt_rand(1, 1000)); // 所有参与签名的参数统一放入数组排序 $params = [ 'oauth_consumer_key' => $ckey, 'oauth_nonce' => $nonce, 'oauth_signature_method' => 'HMAC-SHA256', 'oauth_timestamp' => $timestamp, 'oauth_token' => $tkey, 'oauth_version' => '1.0', 'deploy' => $deploy, 'projectid' => $projectid, 'script' => $script, 'taskid' => $taskid ]; ksort($params); $paramString = ''; foreach ($params as $k => $v) { $paramString .= rawurlencode($k) . '=' . rawurlencode($v) . '&'; } $paramString = rtrim($paramString, '&'); // 拼接基串 $baseString = $httpMethod . '&' . rawurlencode($url) . '&' . rawurlencode($paramString); $key = rawurlencode($csecret) . '&' . rawurlencode($tsecret); $signature = rawurlencode(base64_encode(hash_hmac('sha256', $baseString, $key, true))); // 构造请求头 移除多余Content-Type $header = [ "Authorization: OAuth realm=\"$realm\", oauth_consumer_key=\"$ckey\", oauth_token=\"$tkey\", oauth_nonce=\"$nonce\", oauth_timestamp=\"$timestamp\", oauth_signature_method=\"HMAC-SHA256\", oauth_version=\"1.0\", oauth_signature=\"$signature\"", ]; $curl = curl_init(); // 拼接完整请求URL $fullUrl = $url . "?script=$script&deploy=$deploy&taskid=$taskid&projectid=$projectid"; curl_setopt_array($curl, [ CURLOPT_URL => $fullUrl, CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0', CURLOPT_SSL_VERIFYPEER => 1, // 生产环境必须开启SSL校验,本地测试可临时设为0 CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_HTTPGET => true, // 原生GET配置兼容性更好 CURLOPT_HTTPHEADER => $header, ]); $response = curl_exec($curl); curl_close($curl); var_dump($response);
如果还有问题可以硬编码相同的nonce、timestamp参数,把生成的Authorization头和Node.js版本的逐字符对比,排查是否存在隐式的编码差异。
内容的提问来源于stack exchange,提问作者Sivustonikkari
相关产品推荐
相关产品推荐

