当我使用此URL查询NS API时:
https://'.$accountID.'.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql
它返回我在我的身体中指定的任何东西(例如SELECT * FROM customer
)
然而,当我尝试使用这个URL(它有一个限制参数)查询它:
https://'.$accountID.'.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql?limit=6
它不工作,并返回下面显示的错误
{
"type":"https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2",
"title":"Unauthorized",
"status":401,
"o:errorDetails":[
{
"detail":"Invalid login attempt. For more details, see the Login Audit Trail in the NetSuite UI at Setup > Users/Roles > User Management > View Login Audit Trail.",
"o:errorCode":"INVALID_LOGIN"
}
]
}
我想问题可能是我传递参数的方式(例如limit
)或签名的生成。
如果我在PostMan中运行此查询,它可以工作,但是当涉及到PHP时,它不工作与我传递给Netsuite API的任何参数。
如果我打开"登录审计跟踪搜索",你可以看到URL列没有?limit=7
,就像这样:/services/rest/query/v1/suiteql
,以及"详细信息"。列显示InvalidSignature
我在PHP中使用的代码是:
$httpMethod ="POST";
$accountID = 'NNNNNNN-sb1';
$realm = "NNNNNNN_SB1";
// this one is working fine
$url = 'https://'.$accountID.'.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql';
// when adding this limit it throws the error in PHP code (but postman works fine)
$url = 'https://'.$accountID.'.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql?limit=6';
$ckey = "NNNNN"; //Consumer Key
$csecret = "NNNNN"; //Consumer Secret
$tkey = "NNNNN"; //Token ID
$tsecret = "NNNNN"; //Token Secret
$timestamp = time();
$nonce = md5(mt_rand());
$signatureMethod = 'HMAC-SHA256';
$data["q"] = "SELECT * FROM customer WHERE LENGTH(externalid) = 32";
$baseString = $httpMethod . '&' . rawurlencode($url) . '&'
. rawurlencode(
"oauth_consumer_key=" . rawurlencode($ckey)
. "&oauth_nonce=" . rawurlencode($nonce)
. "&oauth_signature_method=" . rawurlencode($signatureMethod)
. "&oauth_timestamp=" . rawurlencode($timestamp)
. "&oauth_token=" . rawurlencode($tkey)
. "&oauth_version=1.0"
);
$key = rawurlencode($csecret) . '&' . rawurlencode($tsecret);
$signature = base64_encode(hash_hmac('sha256', $baseString, $key, true));
$signature = rawurlencode($signature);
$header = array(
"Authorization: OAuth realm="$realm", oauth_consumer_key="$ckey", oauth_token="$tkey", oauth_nonce="$nonce", oauth_timestamp="$timestamp", oauth_signature_method="$signatureMethod", oauth_version="1.0", oauth_signature="$signature"",
'Cookie: NS_ROUTING_VERSION=LAGGING',
'prefer: transient',
'Content-Type: text/plain',
'Accept: */*',
'Content-length: ' . strlen(json_encode($data)),
);
$curl = curl_init();
$opts = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $httpMethod,
CURLOPT_HTTPHEADER => $header,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => json_encode($data)
);
curl_setopt_array($curl, $opts);
$response = curl_exec($curl);
curl_close($curl);
截图(netsuite设置和邮差):https://i.stack.imgur.com/2KtuJ.jpg
NS - netsuite
我的一个朋友帮了我很大的忙,我们对这个模棱两可的问题有了答案。下面是代码解决方案。
- 在基本字符串中,你必须只有2个&号,在baseUrl上没有编码。
- 所有参数必须按字母顺序排列
<?php
$httpMethod ="POST";
$accountID = 'NNNNNNN-sb1';
$realm = "NNNNNNN_SB1";
// this one is working fine
$baseUrl = 'https://'.$accountID.'.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql';
$ckey = "NNNNN"; //Consumer Key
$csecret = "NNNNN"; //Consumer Secret
$tkey = "NNNNN"; //Token ID
$tsecret = "NNNNN"; //Token Secret
$timestamp = time();
$nonce = md5(mt_rand());
$signatureMethod = 'HMAC-SHA256';
$data["q"] = "SELECT * FROM customer WHERE LENGTH(externalid) = 32";
$baseString = $httpMethod . '&' . rawurlencode($baseUrl) . '&'
. rawurlencode(
//APPLY PARAMETERS IN ALPHABETICAL ORDER, URL ENCODED IN HERE
"limit=2"
. "&oauth_consumer_key=" . rawurlencode($ckey)
. "&oauth_nonce=" . rawurlencode($nonce)
. "&oauth_signature_method=" . rawurlencode($signatureMethod)
. "&oauth_timestamp=" . rawurlencode($timestamp)
. "&oauth_token=" . rawurlencode($tkey)
. "&oauth_version=1.0"
. "&offset=2"
);
$key = rawurlencode($csecret) . '&' . rawurlencode($tsecret);
$signature = base64_encode(hash_hmac('sha256', $baseString, $key, true));
$signature = rawurlencode($signature);
$header = array(
"Authorization: OAuth realm="$realm", oauth_consumer_key="$ckey", oauth_token="$tkey", oauth_nonce="$nonce", oauth_timestamp="$timestamp", oauth_signature_method="$signatureMethod", oauth_version="1.0", oauth_signature="$signature"",
'Cookie: NS_ROUTING_VERSION=LAGGING',
'prefer: transient',
'Content-Type: text/plain',
'Content-length: ' . strlen(json_encode($data)),
);
$curl = curl_init();
$opts = array(
CURLOPT_URL => $baseUrl . '?limit=2&offset=2', // APPLY LIMIT MANUALLY HERE
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $httpMethod,
CURLOPT_HTTPHEADER => $header,
CURLOPT_POSTFIELDS => json_encode($data)
);
curl_setopt_array($curl, $opts);
$response = curl_exec($curl);
curl_close($curl);
var_dump($response);
exit;
沙箱帐号ID
NetSuite REST API中401的一个潜在原因可能是帐户ID的格式无效。例如,12345-sb1
应该与12345_SB1