I'm struggling to connect NetSuite with Salesforce to create Customer Records in NetSuite using RESTlet scripts and OAuth 1 for authorization. While I can create records using POSTMAN, attempts from Apex callouts fail with a 403 Forbidden error and "Invalid login attempt" message. The NetSuite Login Audit Trail indicates "InvalidSignature."
I tried connecting NetSuite using REST web service and then with RESTlet scripts with Salesforce. But both the approaches work well from POSTMAN and throw 403 Forbidden, Invalid Login Attempt error in Apex when tried from Salesforce Apex callout. When checked in the Login Audit trail of NetSuite, the detail column shows InvalidSignature error.It should be succesfully authenticated from Salesforce apex callout the way it does from POSTMAN.
I've double-checked parameters and used HMAC-SHA256 Signature. Any insights on resolving this would be appreciated. Also, if you've connected NetSuite with Salesforce successfully before, I'd love to hear your approach.
here's the code for my ref.
Here's the code snippet for callout:
public class AuthNetSuite { private static final String NETSUITE_RESTLET_URL = 'https://(ACCOUNT_ID).http://restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=(SCRIPT_ID)&deploy=(DEPLOY_ID)'; private static final String CONSUMER_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; private static final String CONSUMER_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; private static final String ACCESS_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; private static final String TOKEN_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; private static final String REALM = 'xxxxxxxxxxxx'; public static HttpResponse calloutToNet(String endPoint, String bodyString, String methodName) { HttpRequest httpRequestObject = new HttpRequest(); httpRequestObject.setEndpoint(endPoint); httpRequestObject.setMethod(methodName); httpRequestObject.setHeader('Content-Type', 'application/json'); //httpRequestObject.setTimeout(120000); // Setting timeout to 2 minutes if(bodyString != null) { httpRequestObject.setBody(bodyString); } String authHeader = OAuth1.getAuthorizationHeader('POST', NETSUITE_RESTLET_URL, ACCESS_TOKEN, TOKEN_SECRET, CONSUMER_KEY, CONSUMER_SECRET, REALM); system.debug('authHeader '+authHeader); httpRequestObject.setHeader('Authorization',authHeader); Http http = new Http(); HttpResponse httpResponse = http.send(httpRequestObject); System.debug('Status Code: '+httpResponse.getStatusCode()+', Status: '+httpResponse.getStatus()+', Body: '+httpResponse.getBody()); return httpResponse; }}
Here's the code snippet: Signature construction
public static String getAuthorizationHeader(String method, String url, String oauthToken, String oauthTokenSecret, String consumerKey, String consumerSecret, String realm) { String oauthNonce = generateNonce(); String oauthTimestamp = String.valueOf(System.currentTimeMillis() / 1000); system.debug('oauthTimestamp '+oauthTimestamp); // Construct signature base string String signatureBaseString = constructSignatureBaseString(method, url, oauthNonce, oauthTimestamp, oauthToken, consumerKey, realm); // Construct signing key String signingKey = consumerSecret +'&'+ oauthTokenSecret; // Generate signature Blob hmac = Crypto.generateMac('HmacSHA256', Blob.valueOf(signatureBaseString), Blob.valueOf(signingKey)); String signature = EncodingUtil.base64Encode(hmac); // Construct authorization header String authHeader = 'OAuth '; authHeader += 'oauth_consumer_key="'+ consumerKey +'",'; authHeader += 'oauth_nonce="'+ oauthNonce +'",'; authHeader += 'realm="'+ realm +'",'; authHeader += 'oauth_signature="'+ EncodingUtil.urlEncode(signature, 'UTF-8') +'",'; authHeader += 'oauth_signature_method="HMAC-SHA256",'; authHeader += 'oauth_timestamp="'+ oauthTimestamp +'",'; authHeader += 'oauth_token="'+ oauthToken +'",'; authHeader += 'oauth_version="1.0"'; return authHeader; } private static String generateNonce() { return EncodingUtil.convertToHex(Crypto.generateAesKey(128)).substring(0, 32); } private static String constructSignatureBaseString(String method, String url, String oauthNonce, String oauthTimestamp, String oauthToken, String consumerKey, String realm) { method = method.toUpperCase(); url = EncodingUtil.urlEncode(url, 'UTF-8'); String signatureParams = 'oauth_consumer_key='+ consumerKey +'&oauth_nonce='+ oauthNonce +'&oauth_signature_method=HMAC-SHA256'+'&oauth_timestamp='+ oauthTimestamp +'&oauth_token='+ oauthToken +'&oauth_version=1.0'; if (!String.isBlank(realm)) { signatureParams += '&realm='+ realm; } return method +'&'+ url +'&'+ EncodingUtil.urlEncode(signatureParams, 'UTF-8'); }