NestJS调用NetSuite REST API带q参数查询时出现INVALID_LOGIN错误
问题:NetSuite API带q参数请求返回INVALID_LOGIN错误
我正在使用NetSuite API,按照官方文档通过q参数查询员工数据,端点示例为GET https://demo123.suitetalk.api.netsuite.com/services/rest/record/v1/customer?q=email START_WITH barbara。Postman调用该端点可正常获取结果,但在NestJS代码中调用带q参数的请求时,收到错误'o:errorCode': 'INVALID_LOGIN'。无参数的请求可正常执行,推测问题与OAuth 1.0认证或签名生成方式有关,求解决建议。
我的代码
async conectNetSuiteTests(): Promise<any> { const baseUrl = `${NETSUITEURL}}/services/rest/record/v1/employee?q=custentity_bit_lt_entitydocument+CONTAIN+${documentEmployee}'`; const oauthNonce = crypto.randomBytes(5).toString('hex'); const oauthTimestamp = Math.floor(Date.now() / 1000); const oauthSignatureMethod = 'HMAC-SHA256'; const oauthVersion = '1.0'; const realm = `5900181_SB1`; const oauthParameters = { oauth_consumer_key: process.env.CONSUMER_KEY, oauth_token: process.env.ACCESS_TOKEN, oauth_nonce: oauthNonce, oauth_timestamp: oauthTimestamp, oauth_signature_method: oauthSignatureMethod, oauth_version: oauthVersion, }; // Ordenar los parámetros de OAuth alfabéticamente por clave const sortedParameters = Object.keys(oauthParameters) .sort() .map((key) => `${key}=${encodeURIComponent(oauthParameters[key])}`) .join('&'); console.log('sor', sortedParameters) // Crear la cadena base para la firma const signatureBaseString = `GET&${encodeURIComponent(baseUrl)}&${encodeURIComponent(sortedParameters)}`; // Crear la clave de firma const signingKey = `${process.env.CONSUMER_SECRET}&${process.env.ACCESS_TOKEN_SECRET}`; // Calcular la firma HMAC-SHA256 const hmac = crypto.createHmac('sha256', signingKey); hmac.update(signatureBaseString); const oauthSignature = hmac.digest('base64'); // Construir la cabecera de autorización const authorizationHeader = `OAuth realm="${realm}", oauth_consumer_key="${process.env.CONSUMER_KEY}", oauth_token="${process.env.ACCESS_TOKEN}", oauth_nonce="${oauthNonce}", oauth_timestamp="${oauthTimestamp}", oauth_signature="${oauthSignature}", oauth_signature_method="${oauthSignatureMethod}", oauth_version="${oauthVersion}"`; // Configuración de la solicitud Axios console.log('authorizationHeader', authorizationHeader) const axiosConfig: AxiosRequestConfig = { method: 'get', url: baseUrl, headers: { 'Prefer': 'transient', 'Content-Type': 'application/json', 'Authorization': authorizationHeader, }, }; try { const response = await axios(axiosConfig); return { "PRO":response.data.custentity_ks_empleado_proveedor_employe.refName.split(' ')[0].split('-')[1], "CLI":response.data.custentitycustentity_ks_empleado_cliente.refName.split(' ')[0].split('-')[1], }; } catch (error) { console.error('error', error); console.error('error', error['response']['data']['o:errorDetails']); throw error; } }
解决建议
修正URL语法错误:你的
baseUrl存在两处语法错误:多了一个闭合大括号},末尾还有多余的单引号'。同时必须对documentEmployee进行URL编码,避免特殊字符破坏请求结构。修正后的URL拼接:const baseUrl = `${NETSUITEURL}/services/rest/record/v1/employee?q=custentity_bit_lt_entitydocument+CONTAIN+${encodeURIComponent(documentEmployee)}`;将查询参数纳入OAuth签名计算:OAuth 1.0要求所有请求参数(包括查询参数)都要加入签名基字符串的参数集合,你当前只使用了OAuth参数,漏掉了
q参数。需要把查询参数合并到参数列表中再排序编码:// 合并OAuth参数和查询参数 const requestParams = { ...oauthParameters, q: `custentity_bit_lt_entitydocument+CONTAIN+${documentEmployee}` }; // 对合并后的参数排序编码 const sortedParameters = Object.keys(requestParams) .sort() .map((key) => `${key}=${encodeURIComponent(requestParams[key])}`) .join('&');拆分签名基字符串的URL与参数:签名基字符串中的URL必须是不带查询参数的基础URL,不能包含
q参数。正确的做法是分离基础URL和查询参数:const baseUrlWithoutQuery = `${NETSUITEURL}/services/rest/record/v1/employee`; const queryParams = { q: `custentity_bit_lt_entitydocument+CONTAIN+${documentEmployee}` }; // 签名基字符串使用无参数的基础URL const signatureBaseString = `GET&${encodeURIComponent(baseUrlWithoutQuery)}&${encodeURIComponent(sortedParameters)}`; // Axios请求用params传递查询参数,避免手动拼接URL的错误 const axiosConfig: AxiosRequestConfig = { method: 'get', url: baseUrlWithoutQuery, params: queryParams, headers: { 'Prefer': 'transient', 'Content-Type': 'application/json', 'Authorization': authorizationHeader, }, };校验OAuth头格式:对比Postman生成的Authorization头,确保你的头参数没有多余空格、引号为英文双引号,参数间用逗号加空格分隔,避免格式错误导致认证失败。
内容的提问来源于stack exchange,提问作者Jhon Alejandro Suarez
相关产品推荐
相关产品推荐

