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

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!

Related

Validate Request Body variables through Swagger and Express

I am currently using Swagger (2.0) on Node.js. My YAML file validates correctly and the requests are going through. My particular call has a request body using the following format -
{
"postalCode": "invalidpostalcode",
"phone": "invalidnumber",
"website": "invalidwebsite"
}
I would like to validate each body variable before continuing to the next piece of code. To accomplish validating the data I would like to use validator.js.
Now my basic validation code looks something like that -
if(!validator.isURL(req.body.website)){
var tmp = {
"message": req.__('error.url', {
field: req.body.website
})
}
res.status(400).json(tmp);
return;
}
if(!validator.isPostalCode(req.body.postalCode,'any')){
var tmp = {
"message": req.__('error.postalCode', {
field: req.body.postalCode
})
}
res.status(400).json(tmp);
return;
}
Is there there any better way to validate data sent in through the API that would require less code? For example by using a function to control the majority of the logic?
while this is one example of the endpoint I will have some in the future that will require upwards of 20 body parameters.
I have tried create a function that will return the response code. However, that returns an error Cannot set headers after they are sent to the client.

How to make a shipping request to chronopost using soap and nodejs

I've had trouble getting to make a simple request with node-soap and chronopost (shipping platform) soap api.
the first thing I did was to follow the basic node-soap example but it just fails miserably without any real USEFUL error from chronopost.
Here's what I have:
const soap = require('soap')
const client = await soap.createClientAsync(
'https://ws.chronopost.fr/shipping-cxf/ShippingServiceWS?wsdl'
)
client.shippingV6(...somedata, (err, result) => {
if (err) {
return handleErr(); // it always fails
}
handleResult();
})
After multiple attempt it seems like chronopost api uses special root attributes (who knows why) and you need to craft the options on node-soap that actually fit their needs (yay..)
Here's what works for me
const createClientShippingServiceWS = async () => {
const wsdlOptions = {
envelopeKey: 'soapenv',
overrideRootElement: {
namespace: 'cxf',
xmlnsAttributes: [
{
name: 'xmlns:cxf',
value: 'http://cxf.shipping.soap.chronopost.fr/'
}
]
}
}
return await soap.createClientAsync(
'https://ws.chronopost.fr/shipping-cxf/ShippingServiceWS?wsdl',
wsdlOptions
)
}
Also what's the point of getting the wsdl if node-soap can't event figure how to make the response??
Thanks chronopost for being stuck in 2008

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.

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 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