Can PostMan be used to test SOAP API calls? Using ...
# suitetalkapi
s
Can PostMan be used to test SOAP API calls? Using Token-Based Oauth1 authentication? I thought I had this working once but I just saw an old article(2017) that indicated that Netsuite was using an older implementation of Oauth1 that Postman had trouble with. I think I have it all set up correctly but I get the error... <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server.userException</faultcode> <faultstring>Oauth:token_expired</faultstring> <detail> <platformFaults:invalidCredentialsFault xmlns:platformFaults="urn:faults_2017_1.platform.webservices.netsuite.com"> <platformFaultscode&gt;USER ERROR&lt;/platformFaultscode> <platformFaultsmessage&gt;Oauthtoken_expired</platformFaults:message> </platformFaults:invalidCredentialsFault> <ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">partners015.prod.svale.netledger.com</ns1:hostname> </detail> </soapenv:Fault> </soapenv:Body> </soapenv:Envelope>
d
@Scot Sunnergren it's probably an issue with the Timestamp/Nonce/signature being generated incorrectly. but I imagine it would be possible
you'd have to generate the above parameters dynamically using a Pre-request script
s
I am not familiar with pre-request scripts. any samples? I thought that the authorization would generate them for me and I can see in the headers... ,oauth_timestamp="1561054179",oauth_nonce="WkG6BfC1TxW"
and they are being regenerated each time...this from a short time after the one above... ,oauth_timestamp="1561054661",oauth_nonce="vQft46rTgu7"
d
@Scot Sunnergren those need to be explicitly placed in your request XML though using dynamic variables as well
what does your request XML look like
s
Pretty straightforward sales order add <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:sales_2017_1.transactions.webservices.netsuite.com" xmlns:ns2="urn:common_2017_1.platform.webservices.netsuite.com" xmlns:ns5="ns" xmlns:ns3="urn:core_2017_1.platform.webservices.netsuite.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="urn:messages_2017_1.platform.webservices.netsuite.com"> <SOAP-ENV:Header> <applicationInfo xmlns="urn:messages_2017_1.platform.webservices.netsuite.com"> <applicationId>xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxx</applicationId> </applicationInfo> </SOAP-ENV:Header> <SOAP-ENV:Body> <platformMsg:add xmlns:platformMsg="urn:messages_2017_1.platform.webservices.netsuite.com"> <platformMsg:record externalId="114-3350054-8419488" xsi:type="ns1:SalesOrder" xmlns:ns1="urn:sales_2017_1.transactions.webservices.netsuite.com" xmlns:ns2="urn:core_2017_1.platform.webservices.netsuite.com" xmlns:ns3="urn:common_2017_1.platform.webservices.netsuite.com"> <ns1:entity internalId="2235" xsi:type="platformCore:RecordRef"/> <ns1source&gt;MFN&lt;/ns1source> <ns1orderStatus&gt; pendingFulfillment&lt;/ns1orderStatus>
we use the same using token-based authentication from code...but I wanted to set up some testing with postman
d
@Scot Sunnergren check out this HelpCenter link : /app/help/helpcenter.nl?fid=section_1534941295.html
I think you are missing the tokenPassport section, all that info needs to be placed in there for the request
s
hmmm...you may be correct there... our app access has it there... so how do I generate the nonce, timestamp, and signature in the pre-request script?
thanks for the assist
@dbarnett well... it looked good, but I still get a login error with that in place. I used PM console to check the end result xml and all looks good. so I am one step further but stuck in the mud.
d
@Scot Sunnergren are you getting a certain error in the response?
I don't have a good answer for you unfortunately though, it's just going to require some troubleshooting. if you have some other integration that you know is successfully sending TBA SuiteTalk calls, I would just recommend comparing those with your Postman ones to see if there are any noticeable differences
s
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server.userException</faultcode> <faultstring>Invalid login attempt.</faultstring> <detail> <platformFaults:invalidCredentialsFault xmlns:platformFaults="urn:faults_2017_1.platform.webservices.netsuite.com"> <platformFaultscode&gt;USER ERROR&lt;/platformFaultscode> <platformFaults:message>Invalid login attempt.</platformFaults:message> </platformFaults:invalidCredentialsFault> <ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">partners013.prod.svale.netledger.com</ns1:hostname> </detail> </soapenv:Fault> </soapenv:Body> </soapenv:Envelope>
message has been deleted
d
@Scot Sunnergren, my postman soaps have this in the header:
Copy code
<soap:Header>
    <messages:tokenPassport>
        <core:account>{{NSAccount}}</core:account>
        <core:consumerKey>{{ConsumerKey.MyService}}</core:consumerKey>
        <core:token>{{TokenKey.MyService}}</core:token>
        <core:nonce>{{nonce}}</core:nonce>
        <core:timestamp>{{timestamp}}</core:timestamp>
        <core:signature algorithm="HMAC-SHA1">{{signature}}</core:signature>
    </messages:tokenPassport>
</soap:Header>
And i use the same pre-request script, from that gist linked above
b
if this is the first time you've used an integration, you should make sure the integration record is setup to allow tba
s
@dbaghdanov - yes... you can see those all in my header...the one difference is that the code that I found online, for some reason had a "1" after the signature but it seems to make no difference whether I include that or not. I am not sure above what the .myservice is where you are pulling in your variables but I have confirmed that what is in my sample above is correct.
@battk - not my first TBA integration. We have it up and running in a number of integrations and this specific set of credentials is in use with a php app that is posting to the same sandbox. Just trying to get it to work with Postman
d
@Scot Sunnergren, in postman you can setup environment variables, that's all those
{{TokenKey.MyService}}
is, it just holds the token key values. I didn't see a
<tokenPassport>
in your sample.
b
it is kinda hard to read raw like that. it might help to show what your request looks like formatted
s
I reformatted it to make it easier to read...
d
why is there a "1" at the end of your signature? it should end in a "="
OH
there's a typo in the gist
the gist has:
Copy code
<ns1:signature algorithm="HMAC-SHA1">{{signature}}1</ns1:signature>
but that:
{{signature}}1
is in error, it should just be:
Copy code
<ns1:signature algorithm="HMAC-SHA1">{{signature}}</ns1:signature>
s
same result...
Copy code
<SOAP-ENV:Header>
		<ns5:tokenPassport >
			<ns3:account>1234567_SB1</ns3:account>
			<ns3:consumerKey>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</ns3:consumerKey>
			<ns3:token>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</ns3:token>
			<ns3:nonce>ac5390e72f1126e8c144</ns3:nonce>
			<ns3:timestamp>1561138990</ns3:timestamp>
			<ns3:signature algorithm="HMAC-SHA1">hexRQbAQxxxxxxxxxxxxE96w=</ns3:signature>
		</ns5:tokenPassport>
	</SOAP-ENV:Header>
	<SOAP-ENV:Body>
Copy code
<soapenv:Body>
        <soapenv:Fault>
            <faultcode>soapenv:Server.userException</faultcode>
            <faultstring>Invalid login attempt.</faultstring>
            <detail>
                <platformFaults:invalidCredentialsFault xmlns:platformFaults="urn:<http://faults_2017_1.platform.webservices.netsuite.com|faults_2017_1.platform.webservices.netsuite.com>">
                    <platformFaults:code>USER_ERROR</platformFaults:code>
                    <platformFaults:message>Invalid login attempt.</platformFaults:message>
                </platformFaults:invalidCredentialsFault>
                <ns1:hostname xmlns:ns1="<http://xml.apache.org/axis/>">partners013.prod.svale.netledger.com</ns1:hostname>
            </detail>
        </soapenv:Fault>
@dbaghdanov...can you send me your pre-request script in case there is something else that has been corrupted in the original?
d
Sure:
Copy code
let account = pm.environment.get("NSAccount");
let consumerKey = pm.environment.get("ConsumerKey");
let consumerSecret = pm.environment.get("ConsumerSecret");
let tokenId = pm.environment.get("TokenKey");
let tokenSecret = pm.environment.get("TokenSecret");
let timestamp = new Date().getTime().toString().substring(0,10);
let nonce = CryptoJS.lib.WordArray.random(10).toString();
let baseString = `${account}&${consumerKey}&${tokenId}&${nonce}&${timestamp}`;
let key = `${consumerSecret}&${tokenSecret}`;
let signature = CryptoJS.HmacSHA1(baseString, key).toString(CryptoJS.enc.Base64);

pm.environment.set("signature", signature);
pm.environment.set("nonce", nonce);
pm.environment.set("timestamp", timestamp);
And you've setup your environment variables and everything?
s
I have my credentials in my environment but it looks like the signature/nonce/timestamp get created on the fly because they do show in the post
do you have those set in the environment?
maybe I am pulling something that I did not set.
d
timestamp, nonce, and signature will be generated on the fly, in the pre-request script. After I click send, you can see the environment variables updated You have Authorization turned off right?
s
I noticed that between the last run and the previous, the data in nonce and timestamp have changed but not the data in signature. it has stayed the same as the previous.
d
in the pre-request script:
pm.environment.set("signature", signature);
should be updating the environment variable each time
s
I deleted those three variables from the environment and ran it again
it re-created them but the signature was re-created as the exact same as all of the previous attempts
d
well that's weird, can you post your pre-request script? and maybe the soap:header from the Body?
s
ok... got it to work... too much trying a bunch of different stuff and not reverting back afterwards.... a couple of misplaced quotes... in the signature generation.
👍 1
💯 1
@dbaghdanov 👍 Thanks SO much!!!
d
np, glad you got it to work 😄
d
@Scot Sunnergren for sake of completion and my future reference, could you post your final <soap:Envelop .... to </soap:Header> section from your SOAP Xml Postman body? thanks
s
I can but the solution is more than that. That portion would only hold the variable embeds... The link I found through google... https://gist.github.com/michoelchaikin/2a4916e0917aa0f79b8eb9d7fe275363 ...has all the instructions. Except we found that somehow the number "1" was added in the reference code
d
yah I saw that, but I was curious about if that statement about the extra 1 after the signature was an issue or not
also I tried all the same things with my version but I am getting a different error 🙂 lol
s
It most likely was.
but I tried so many other things that when I got around to removing that, something else was broken.
following those instructions and removing the "1" should be the entirety of the solution
what error are you getting?
d
do you have applicationInfo : applicationId set in your header? I am trying to run a search operation with mine and am getting a "User_error : ambiguous authentication"
b
dont set the applicationId
thats for regular passport
d
and then if I comment out the applicationId portion, I am just getting invalidLogin so was just curious what yours looked like
@battk gotcha, good to know. I'll keep messing around with it then
s
I had that when I left the application section in from my userid/password section. application is not required with TBA
Copy code
<SOAP-ENV:Header>
        <ns5:tokenPassport  >
            <ns3:account>{{account}}</ns3:account>
            <ns3:consumerKey>{{consumerKey}}</ns3:consumerKey>
            <ns3:token>{{tokenId}}</ns3:token>
            <ns3:nonce>{{nonce}}</ns3:nonce>
            <ns3:timestamp>{{timestamp}}</ns3:timestamp>
            <ns3:signature algorithm="HMAC-SHA1">{{signature}}</ns3:signature>
        </ns5:tokenPassport>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns4:add>
and...
Copy code
let account = pm.environment.get("account");
let consumerKey = pm.environment.get("consumerKey");
let consumerSecret = pm.environment.get("consumerSecret");
let tokenId = pm.environment.get("tokenId");
let tokenSecret = pm.environment.get("tokenSecret");
    
let timestamp = new Date().getTime().toString().substring(0,10);
let nonce = CryptoJS.lib.WordArray.random(10).toString();
let baseString = `${account}&${consumerKey}&${tokenId}&${nonce}&${timestamp}`;
let key = `${consumerSecret}&${tokenSecret}`;
let signature = CryptoJS.HmacSHA1(baseString, key).toString(CryptoJS.enc.Base64);


pm.environment.set("signature", signature);
pm.environment.set("nonce", nonce);
pm.environment.set("timestamp", timestamp);
message has been deleted
lol...looks like the Mueller report...
😂 2
those should be all the components. note that your soap envelope will establish labels for different components and those will need to match what you put in your header...
b
you might also want to check that the integration records allows TBA
s
...oh...and your authorization type should be set to No Auth since you are basically doing all of the Oauth 1 work in the pre-script
..and my "Body" is set to Raw (XML (text/xml))
d
....finally figured it out 🤯 I was using Collection variables, not Environment variables. In this case, simply replace all the get variable calls with pm.variables.get("var_name");
👍 2
125 Views