How can I add "namespace" to request in node soap - node.js

I created web service object from wsdl file and call it like in below. I also print result. this code does not work. web server returns error. because, request has not namespace.
soap.createClient(__dirname + '/wsdl/getCustomerDetails.wsdl', function(err, client) {
.
.
var params= {"custId":"123"};
client.getCustomerDetails.getCustomerDetailsPort.getCustomerDetails(params,function(err,result){
console.log("lastRequest:"+client.lastRequest);
if (err != null)
console.log("error:"+JSON.stringfy(error));
});
}
here what I see in the last request
<soap:... xmlns:tns="http://example.com/api/getCustomerDetails/V01" >
....
<soap:Body>
<getCustomerDetailsRequest>
<custId>123</custId>
</getCustomerDetailsRequest>
</soap:Body>...
but it has to be
<soap:... xmlns:tns="http://example.com/api/getCustomerDetails/V01" >
....
<soap:Body>
<tns:getCustomerDetailsRequest>
<tns:custId>123</tns:custId>
</tns:getCustomerDetailsRequest>
</soap:Body>...
as you see, soap module does not add tns namespace to the request. I tried var params= {"tns:custId":"123"};, it adds namespace to the parameter, but still it does not add namespace to the request, getCustomerDetailsRequest. because of that, I get Unexpected element getCustomerDetailsRequest found. Expected {http://example.com/api/getCustomerDetails/V01}getCustomerDetailsRequest.
how can I force to add this namespace to the method itself ?

I found how I can do that. I think it does not work in default because of a bug in "soap" module. In default, it does not add namespace to the request body. "soap" uses "tns" in default as namespace. there is an option in wsdlOptions. it is overrideRootElement. If you try to override overrideRootElement with tns, it does not add tns to the request body. You have to use different namespace in overrideRootElement. Here my solution,
I first create my wsdlOptions object.
var wsdlOptions = {
"overrideRootElement": {
"namespace": "myns",
"xmlnsAttributes": [{
"name": "xmlns:myns",
"value": "http://example.com/api/getCustomerDetails/V01"
}]
}
};
and then use it when I create soap client,
soap.createClient(__dirname + '/wsdl/getCustomerDetails.wsdl',wsdlOptions, function(err, client) {
.
.
.
}
);
It makes request body uses myns as namespace of root element. Now, I have to modify parameters' namespace, so I defined parameters as
var params= {"myns:custId":"123"};
now, It creates request as
<soap:... xmlns:tns="http://example.com/api/getCustomerDetails/V01" >
....
<soap:Body>
<myns:getCustomerDetailsRequest xmlns:myns="http://example.com/api/getCustomerDetails/V01">
<myns:custId>123</tns:custId>
</myns:getCustomerDetailsRequest>
</soap:Body>...
and, now webserver accepts it.
keep in mind, even tns is defined in the root, it is not added to the request body automatically. Also, if you try to override it in wsdlOptions by tns again, it still does not work. You have to use different value as namespace, like myns

I dwelt sometime on this problem until I saw that the lib get the namespaces from the parsed WSDL (this.wsdl.xmlnsInEnvelope)
xml = '<?xml version="1.0" encoding="utf-8"?>' +
'<' + envelopeKey + ':Envelope ' +
xmlnsSoap + ' ' +
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
encoding +
this.wsdl.xmlnsInEnvelope + '>' +
Then I saved the WSDL inside my project (loading from there) and inserted the namespace I wanted. That worked for me.

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!

Consume WCF service using Node.js

I am consuming my WCF service using Node.js. I am using WCF.js package.
I am able to communicate with the service but not able to fetch data.
I am getting the response action method in response.
I have tried WCF.js package.
Following is the code that i tried
var result;
var BasicHttpBinding = require('wcf.js').BasicHttpBinding
, Proxy = require('wcf.js').Proxy
, binding = new BasicHttpBinding()
, proxy = new Proxy(binding, " http://domain:port/myservice.svc")
, message = '<Envelope xmlns=' +
'"http://schemas.xmlsoap.org/soap/envelope/">' +
'<Header />' +
'<Body>' +
'<GetConnections xmlns="http://tempuri.org/"/>' +
'</Body>' +
'</Envelope>'
proxy.send(message, "http://tempuri.org/IMyInterface/GetConnections", function(result, ctx) {
console.log(result)
});
I am getting following response
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="ba0b223b-a823-47ff-826d-467d595f0bc7"
xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">47ff68ec-2083-417f-b29d-52571c4cd153
</ActivityId>
</s:Header>
<s:Body>
<GetConnectionsResponse xmlns="http://tempuri.org/">
<GetConnectionsResult xmlns:a="http://schemas.datacontract.org/2004/07/vRanger.API.Types.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
</GetConnectionsResponse>
</s:Body>
</s:Envelope>
I want the data to be returned.
Can anyone help me with this.
I didn’t get your point, this xml response is the returned result. What is the data? If you want to parse XML document, we could use the below JavaScript DOMParser.
Parse XML using JavaScript
https://developer.mozilla.org/en-US/docs/Web/Guide/Parsing_and_serializing_XML
In addition, it seems that the result is empty in the GetConnectinResult node.
<GetConnectionsResult xmlns:a="http://schemas.datacontract.org/2004/07/vRanger.API.Types.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
If the GetConnections method has the returned result, there might be some parameters in the method signature. Thereby we need to add the value of the parameter.
"<GetConnections xmlns='http://tempuri.org/'>" +
"<value>123</value>" +
"</GetConnections>" +
At last, I do not see the library's support for complex data types, where the result returned is a custom object.
https://github.com/yaronn/wcf.js
Please try the below link.
How to consume WCF soap web service in node.js

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