SOAP Request using nodejs - node.js

Hi can anyone help me out.
how to request soap web service and get the xml response.
Senario:
Using soap ui im sending wsdl url with username, password authentication and also i will send soap xml data and i gets reponse.
Same thing how to achive using nodejs or sails.
In SoapUi My soap xml request is like
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tier="http://HCSLN9191-GMS.gois.ito.unisys.com/Tier1ICLStd:Tier1ICLMB_StdDispatch">
<soapenv:Header/>
<soapenv:Body>
<tier:UnisysMB_Dispatch>
<PayLoad>SomeData</PayLoad>
</tier:UnisysMB_Dispatch>
</soapenv:Body>
</soapenv:Envelope>
And My Soap Authentication is like
$UserName : xyz & password:xyz
My wsdl url is
http://esbuatt1wm.ito.xyz.com:7001/ws/Tier1ICLStd_New:Tier1ICLMB_StdDispatch_New?WSDL
After provides this information i am getting xml response like
<ser-root:CommAck xmlns:ser-root="http://HCSLN1181-GMS.gois.ito.unisys.com/Tier1ICLStd_New:Tier1ICLMB_StdDispatch_New" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CommAck>
<MB_UUID>cbbb683d-e9b1-4d12-b0db-8006134aad27</MB_UUID>
<ServiceID>McDonalds</ServiceID>
<Acknowledge>0</Acknowledge>
<Comment>Payload does not contain the pattermatch xpath.</Comment>
</CommAck>
</ser-root:CommAck>
My Question is How to get that above xml response using node easy soap,
i am new to soap concept. can anyboud help me out to give me the proper snippet for the above senario.....

You can use this package https://www.npmjs.com/package/soap. Examples are in the same link. I have pasted below some of the contents:
Install with npm:
npm install soap
Example:
var soap = require('soap');
var url = 'http://example.com/wsdl?wsdl';
var args = {name: 'value'};
soap.createClient(url, function(err, client) {
client.MyFunction(args, function(err, result) {
console.log(result);
});
});
BasicAuthSecurity
client.setSecurity(new soap.BasicAuthSecurity('username', 'password'));

You can use Axios a promise based Nodejs package.
an Example:
const baseURL = '';
const apiKey = '';
const xmlBody = `XML body here // you can also add api key using ${apiKey} like this if needed`;
axios.post(BaseURL,xmlBody,{
headers: {
'Content-Type': 'text/xml'
}
}
).then(response => {console.log(response.data)}
).catch(err => {console.log(err)});

You can use the soap module. I had to eventually use it so documented it below in the link provided.
for username and password, if your WSDL is password protected then you would also need to set the correct wsdl_headers in the client that you would create with node-soap
check out this answer:https://stackoverflow.com/a/29036380/4157003
Additionally, You also need to set the correct security mechanism before using any service
client.setSecurity(new soap.BasicAuthSecurity('username', 'password'));
You can check this link for more info
https://codecalls.com/2020/05/17/using-soap-with-node-js/

You can use the easy-soap-request npm package.
If you want to create the SOAP header passwordDigest in nodejs,
const crypto = require('crypto');
function passwordDigest(created, nonce, pass) {
// Password_Digest = Base64 ( SHA-1 ( bytes(decode64(nonce)) + bytes(created) + bytes(password) ) )
let pd = Int8Array.from([...Int8Array.from(Buffer.from(nonce, 'base64')),
...Int8Array.from(Buffer.from(created)),
...Int8Array.from(Buffer.from(pass))]);
pd = crypto.createHash('sha1').update(pd).digest('base64');
return pd;
}
More detailed explanation on this post
https://stackoverflow.com/a/66824784/15485314

Related

strong-soap return wsdl different from soap

I am having a bit of an issue, and I hope someone may be able to help. Our company is switching from npm soap library to strong-soap for internal reasons. We are interfacing with an old server (soap 1.1) that we prefer not to modify. We can set up the client perfectly with the soap library; however, with strong-soap, it appears we get some questionable wsdl returned. If we call describe on the soap client we get all the proper ins and outs. However, if we do a describe on the strong-soap we get the return function with a slew of xml. I think the wsdl description coming back for the strong-soap must not be proper. I am wondering if strong-soap supports version 1.1.
If we call a method in the implementation of strong-soap, we get an error message “missing required input parameter”, which makes sense because the data returned from describe lists a giagantic xml description for the parameters. This is the reason I do not think the strong-soap supports an earlier version of soap.
For the soap libary
`
const authorization = `Basic ${base64.encode(`${userId}:${password}`)}`
const wsdlOptions = createWsdlOptions(authorization)
client = await soap.createClientAsync(url, wsdlOptions)
client.addHttpHeader('Authorization', authorization)
client.setEndpoint(url)
client.on('soapError', (e, _eid) => {
error(`SOAP client error: ${e.message}`)
})
`
For the strong-soap libary
`
return new Promise((resolve, reject) => {
const authorization = `Basic ${base64.encode(`${userId}:${password}`)}`
const wsdlOptions = createWsdlOptions(authorization)
soap.createClient(url, wsdlOptions, (err, c) => {
if (err) {
reject(err)
}
that.client = c
that.client.setSecurity(new soap.BasicAuthSecurity(userId, password))
that.client.setEndpoint(url)
that.client.on('soapError', (e, _eid) => {
error(`SOAP client error: ${e.message}`)
})
resolve(c)
})
})
`
If I try a describe on the client
`
const description = client.describe()
console.log(JSON.stringify(description.CClmStatusWF.BasicHttpBinding_IClmStatusWF.readMyData)))
`
On the soap client i get
{"input":{"p_sXMLParam":"xs:string"},"output":{"readMyDataResult":"xs:string"}}
However on the srong-soap I get a huge of xml file

validateRequest method in Node.js Twilio client library not validating request while running in AWS Lambda

I am trying to validate that an http POST request to an AWS Lamdbda function URL from a Twilio HTTP Request widget inside a Twilio Studio flow truly originated from Twilio. I am using the Node.js Twilio client library, which provides the validateRequest method to accomplish what I am after. The content-type header in the Twilio Studio flows HTTP Request widget is set to application/json
The problem is that I am passing in the "x-twilio-signature" header, the url, twilio auth token, and POST params to the validateRequest method and it always returns false. Below is the code snippet used to try and accomplish this.
const authToken = process.env.twilio_auth_token
const sid = process.env.twilio_account_sid
const client = require('twilio')
exports.handler = (event) =>
{
let twilioSignature = event.headers['x-twilio-signature']
let requestBody = event.body
let requestUrl = 'https://my-function-url.io/'
let requestIsValid = client.validateRequest(authToken, twilioSignature, requestUrl, requestBody)
if(requestIsValid){
console.log('valid request')
} else {
console.log('invalid request')
}
}
Seems like someone else had a similar issue in the past. I copied parts of the answer here:
The issue here is that query string parameters are treated differently to POST body parameters when generating the signature.
Notably part 3 of the steps used to generate the request signature says:
If your request is a POST, Twilio takes all the POST fields, sorts them by alphabetically by their name, and concatenates the parameter name and value to the end of the URL (with no delimiter).

Connecting to a web service using SOAP

I am currently working on a node based application trying to make a request to a SOAP based service. I am making use of the node-soap module to work through this.
https://github.com/vpulim/node-soap
Currently i have the following implementation
var soap = require('soap');
var url = 'http:/xxxx/xxxx/xxxx?WSDL';
var appKey = 'ABYRCEE';
var xml = {
appKey: appKey,
mac: 'xxxxxxxx'
}
soap.createClient(url, function(err, client){
//console.log('Client:', client);
client.getAllDocsisVideoInfo(xml, function(err, result){
if(err){
console.log(err);
}
});
});
For the service to respond, i have a sample request in xml format, as the following
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:doc="http://xxx.xxx.com">
<soapenv:Header/>
<soapenv:Body>
<doc:getAllDocsisVideoInfo>
<appKey>"appKey"</appKey>
<mac>xxxxxxx</mac>
</doc:getAllDocsisVideoInfo>
</soapenv:Body>
</soapenv:Envelope>
As you can see from the above that i have to pass in appKey and mac values and upon a successful request this will send back successful response in xml format with the appropriate response.
I am able to see client object return back with the appropriate functions, but upon calling the client.getAllDocsisVideoInfo(....), i seem to see the following error
S:Client: Cannot find dispatch method for {}getAllDocsisVideoInfo
I am not sure of the why? Is it because of the way i am passing in the xml object, how do i pass in the sample request?
Looking at the node-soap api:
https://www.npmjs.com/package/soap
It looks like you have to call the function in the following manner:
client.getAllDocsisVideoInfo(xml, function(err, result, raw, soapHeader){
})
If you want to call it like you had it in your code, then I think you need to use the following:
Copy and paste from the API...
client.MyService.MyPort.MyFunction({name: 'value'}, function(err, result) {
// result is a javascript object
})
So after spending hours on this and banging my head, i was able to get a successful response by overriding the namespace prefix, by removing the namespace prefix.
For example, the following object needed to be passed as
var xml = {
':appKey': appKey,
':mac': 'xxxxxxxx'
}
Instead
var xml = {
appKey: appKey,
mac: 'xxxxxxxx'
}
This piece of the node-soap documentation [https://github.com/vpulim/node-soap#overriding-the-namespace-prefix][1] helped in figuring out the issue.

Node.js soap request remove namespace from argument

I am unable to send the correct argument to the service.
Code used:
var soap = require('soap');
var url = 'http://example.com';
soap.WSDL.prototype.ignoredNamespaces = ['targetNamespace', 'typedNamespace'];
var args = {'name':'test'};
soap.createClient(url, function(err, client) {
client.Hello(args, function(err,result,res){
console.log(result);
console.log(client.lastRequest);
});
});
The Hello-function should return string "Hello test !". However, I get:
'Hello null !'
The request being sent is:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ....><soap:Body>
<tns:Hello xmlns:tns="http://example/">
<tns:name>test</tns:name>
</tns:Hello></soap:Body></soap:Envelope>
where
test
is the interesting part. The service is expecting
<name>test</name>
without namespace (i tested this with http://www.soapclient.com/)
So, the question is: how do I send the request argument without tns attached? (tns:name => name) Thanks!
The correct way to override namespace is to send the parameters like this:
var params = { ':name' : 'test' }
It's in documentation: Overriding the namespace prefix
In your code instead of passing argument as
var args = {'name':'test'};
try
var args = {arg0: 'testName'};
I am not an expert but it worked for me to pass an argument from node.js while invoking SOAP client.

Node.js SOAP Call with Complex Types

I am currently attempting to use node-soap (https://github.com/milewise/node-soap) to make calls to Authorize.net's SOAP server. However, I cannot seem to get my client code pass the proper parameters. I know that the function is calling the server since I get a server error response.
When I examine the WSDL, I notice that the server call requires ComplexType parameters. Is there a way to create the ComplexTypes that I need or can I just use Javascript objects? Here is my current code:
var soap = require('soap');
var url = 'https://api.authorize.net/soap/v1/Service.asmx?WSDL';
soap.createClient(url, function(err, client) {
var args = {
merchantAuthentication: {
name: '285tUPuS',
transactionKey: '58JKJ4T95uee75wd'
}
};
client.Service.ServiceSoap12.GetTransactionDetails(args,
function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result.GetTransactionDetailsResult[0].messages);
}
});
});
The node-soap module is converting your JavaScript object to XML before sending the transaction to the server. It wraps the request in an xml element as outlined by the wsdl. Here is an example of what might be produced by node-soap when passing the object you provided (important to note the outer element is created by the node-soap module according to the wsdl):
This example is using the wsdl for the CyberSource API
<data:requestMessage xmlns:data="urn:schemas-cybersource-com:transaction-data-1.93" xmlns="urn:schemas-cybersource-com:transaction-data-1.93">
<data:merchantAuthentication>
<data:name>285tUPuS</data:name>
<data:transactionKey>58JKJ4T95uee75wd</data:transactionKey>
</data:merchantAuthentication>
</data:requestMessage>
Also, I don’t know exactly how the Authorize.net api works, but it sounds like you might want to check out using username token authentication if necessary:
client.setSecurity(new soap.WSSecurity('username’, ‘password’));

Resources