从User Event脚本调用Restlet遇INVALID_LOGIN_ATTEMPT错误咨询
问题描述
从User Event脚本调用Restlet时收到错误:
body":"error code: INVALID_LOGIN_ATTEMPT
error message: Invalid login attempt
疑问:
- 是否需要传递凭证?
- 应传递Client ID、Client Secret吗?
- 还有其他可行方法吗?
- 尝试使用
url.resolveScript但未解决问题,附上代码:
/** * @NApiVersion 2.x * @NScriptType UserEventScript * @NModuleScope Public */ define(["N/https", "N/log", "N/record", "N/url" ], function(https, log, record, url) { function beforeLoad(context) { // log.debug('beforeLoad Triggered'); // context.newRecord; // context.type; // context.form; return; } function afterSubmit(context) { log.debug('Before code'); var record = context.newRecord; var requestBody = { "recordId": record.id, "recordType": record.type, }; var output = url.resolveScript({ scriptId: '1157', deploymentId: '1', }); var output1 = 'https://12345-sb5.restlets.api.netsuite.com'; log.debug('After code', output ); var response = https.post({ url: output1 + output, body: requestBody, }); if (response.code === 200) { // success! } else { // handle error } log.debug('After code', response ); return; } function beforeSubmit(context) { // log.debug('beforeSubmit Triggered'); // context.newRecord; // context.oldRecord; // context.type; return; } return { beforeLoad : beforeLoad, afterSubmit : afterSubmit, beforeSubmit : beforeSubmit } })
解决方案
错误原因
User Event脚本调用Restlet时,默认不会自动携带身份认证信息,必须显式处理认证逻辑,否则会触发INVALID_LOGIN_ATTEMPT错误。你之前用url.resolveScript无效,是因为手动拼接了外部域名,破坏了该方法自动生成的带认证参数的完整URL结构。
方法1:正确使用url.resolveScript(推荐同账号内调用)
url.resolveScript会自动生成包含NetSuite域名、脚本/部署ID,以及临时认证参数的完整URL,无需手动拼接域名。修正代码如下:
function afterSubmit(context) { log.debug('Before code'); var record = context.newRecord; var requestBody = { "recordId": record.id, "recordType": record.type, }; // 正确生成Restlet的完整认证URL var restletUrl = url.resolveScript({ scriptId: '1157', // 建议使用自定义脚本ID(如customscript_my_restlet)而非数字ID deploymentId: '1', // 同理建议用customdeploy_my_restlet returnExternalUrl: false // 同账号内调用设为false,默认值,生成内部可访问的带认证URL }); log.debug('Restlet URL', restletUrl); var response = https.post({ url: restletUrl, // 直接使用生成的完整URL,无需额外拼接 body: requestBody, headers: { 'Content-Type': 'application/json' // 确保请求头正确,Restlet需要JSON格式的话要加这个 } }); if (response.code === 200) { log.debug('Success', response.body); } else { log.error('Error', response.body); } return; }
方法2:使用Token-Based Authentication(TBA)传递Client ID/Secret
如果需要跨账号或更安全的认证方式,可配置TBA:
- 在NetSuite中创建集成记录,获取Client ID和Client Secret
- 创建访问令牌(Token ID和Token Secret)
- 在请求中生成签名并添加Authorization头
示例代码(简化版):
var oauth = require('N/oauth'); // 需要引入N/oauth模块 function afterSubmit(context) { // ... 其他代码 ... var tokenAuth = oauth.createToken({ consumerKey: 'YOUR_CLIENT_ID', consumerSecret: 'YOUR_CLIENT_SECRET', token: 'YOUR_TOKEN_ID', tokenSecret: 'YOUR_TOKEN_SECRET' }); var response = tokenAuth.post({ url: 'https://12345-sb5.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=1157&deploy=1', body: requestBody, headers: { 'Content-Type': 'application/json' } }); // ... 处理响应 ... }
方法3:使用Session认证(不推荐生产环境)
如果是同账号内且脚本运行在用户会话中,可尝试传递当前用户的会话参数,但安全性较低:
- 在请求头中添加
Cookie,值为当前会话的JSESSIONID和NS_ROUTING_VERSION - 但这种方式依赖会话有效期,容易失效,不建议生产使用
关键注意事项
- 确保Restlet的部署设置中,允许调用User Event脚本的角色访问
- 使用
url.resolveScript时,不要手动拼接域名,否则会丢失自动生成的认证参数 - 传递请求体时,务必设置正确的
Content-Type头(如application/json),否则Restlet可能无法解析请求
内容的提问来源于stack exchange,提问作者Krunal Patel
相关产品推荐
相关产品推荐

