Connecting to a web service using SOAP - node.js

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.

Related

Node.js Soap method params parsed as string instead of related object

I'm using node-soap to consume a WebService. I've used this library and consumed this service many times before, but this time I'm having the following situation.
I create the client using the WSDL that contains the methods, inputs etc:
const soap = require("soap");
const url = "https://servintp.latinoseguros.com.mx:8071/wsCotizadorAutos/cotizador/CotizadorLatino.svc?wsdl";
soap.createClient(url, {}, (error, client) => {
if (error) {
callback(error);
} else {
const describe = client.describe()["CotizadorLatino"]["BasicHttpBinding_ICotizadorLatino"];
console.log(describe["ObtenerMarcas"])
}
});
The request is successful and the client is created, but when I describe the method "ObtenerMarcas" I receive the following object:
{
input: { datos: 'q17:DatosRequeridos' },
output: { ObtenerMarcasResult: 'q18:ListMarca' }
}
Whose only input param shows as only a String, while it should be an object whith different objects and attributes.
When using Soap Client and inputing the exact same WSDL endpoint, the method is described as it should, with all the children and attributes that are expected to be passed:
Soap Client Screenshot
Which makes me believe that this has something to do with the client configuration or probably something very basic that I'm not taking into account.
Can anybody point me on what I'm doing wrong?
Thanks!

How to map SOAP request with SOAP response using node-soap

I use node-soap to manage SOAP requests/responses on server side. I'm using server.log function to log requests and responses and I need to somehow map them (connect) to know which request caused a certain response.
See the code sample:
function log(type, data) {
let logId = '';
if (type === 'received') {
// On received I need to generate logId
logId = generateLogId();
console.log(logId, data);
}
if (type === 'replied') {
// On replied I need to get the logId that was generated on the matching request
logId = getLogId();
console.log(logId, data);
}
}
I've tried using node's continuation-local-storage, but without much success.
Help me, Obi-Wan Kenobi. You're my only hope.

Trouble understanding how to craft a SOAP request

I have to download something from a webservice via SOAP interface. The documentation for the interface is rather sparse so I have trouble understanding how to request from it.
This is the .wsdl specification.
This is the .xsd one.
The idea is:
Logging in to get session key (I did this successfully)
Using the session key to request available data (where I am having problems)
Using this key to request specific data
Logging out again
I am successfully getting the session key and using it with the request for the databox. Unfortunately, I'm only ever getting HTTP 404 as a response and I don't know how to find the problem since 404 also shows up when the session key is wrong ("asdfg" for example).
This is the XML I am sending:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getDatabox xmlns="https://finanzonline.bmf.gv.at/fon/ws/databox">
<tid>${tid}</tid>
<benid>${benid}</benid>
<id>${sessionToken}</id>
<erltyp>${erltyp}</erltyp>
<ts_zust_von>20-08-2017</ts_zust_von>
<ts_zust_bis>25-08-2017</ts_zust_bis>
</getDatabox>
</soap:Body>
</soap:Envelope>
This is the method I am using (I removed some ugliness from it, like the xmlDatabox which is initialized in the method for example):
function getDataBox(sessionToken, erltyp) {
return new Promise((resolve, reject) => {
var body = [];
var https = require("https");
var req = https.request(optionsDatabox, res => {
res.setEncoding("utf8");
res.on("data", chunk => {
console.log("daty");
console.log(chunk);
body.push(chunk);
});
res.on("end", () => {
console.log("STATUSCODE: " + res.statusCode);
resolve(body.join(""));
});
res.on("error", err => {
reject(err);
});
});
req.write(xmlDatabox);
req.end();
});
}
Now everything is sent as it should be sent. Also, the method and xml are (except for the important stuff) the same for getDatabox() and loginRequest() (which works). The only response is HTTPS 404.
How do I find what is wrong?
How do I prevent this frustration next time? (e.g. by knowing immediately what methods should be used)
EDIT: I'm not using the soap module because I had no success with it.
Okay..
I used SoapUI to find out how the request should look like, since I didn't know much about the .wsld and .xsd formats.
SoapUI reads those two files and creates the appropriate xml for it, which you just have to fill out. It also shows you the URL to which you have to send your request, which I didn't know at first either.

SOAP Request using nodejs

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

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