Titanium SOAP Call ActionNotSupported using suds.js - web-services

I have http://192.168.15.45:8081/Taqeem.CRM.Appointments.Service.svc?wsdl service and method BookAppointment and I have also mentioned the parameters in the code and it is values.
var url = "http://192.168.15.45:8081/Taqeem.CRM.Appointments.Service.svc?wsdl";
var callparams = {
AppointmentNumber: 'APP-00000003-H042S5',
UserId: '4'
};
var suds = new SudsClient({
endpoint: url,
targetNamespace: 'http://tempuri.org'
});
try {
suds.invoke('BookAppointment', {}, function(xmlDoc) {
var ManifestXML = this.responseText;
console.log(ManifestXML);
var results = xmlDoc.documentElement.getElementsByTagName('ResultCode').text;
console.log('result'+ results);
if (results && results.length>0) {
var result = results.item(0);
label.text = '1 Euro buys you ' + results.item(0).text + ' U.S. Dollars.';
} else {
label.text = 'Oops, could not determine result of SOAP call.';
}
});
} catch(e) {
Ti.API.error('Error: ' + e);
}
I've used the suds.js and when I execute the below code. I get the error as ActionNotSupport
Complete response:
[INFO] : <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">
a:ActionNotSupported
</faultcode>
<faultstring xml:lang="en-US">
The message with Action 'http://tempuri.org/BookAppointment' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
I feel like I'm passing the wrong TargetNameSpace but I have checked in http://192.168.15.45:8081/Taqeem.CRM.Appointments.Service.svc?wsdl and its good. I request to check the above link for list of methods.
I've used the SOAP UI and it is executing perfect. I get the perfect response.

Related

API Gateway -> Lambda -> DynamoDB using Cognito. HTTP POST-> Unable to read response but returns a code 200

Scenario:
I query an HTTP POST (using Authorizer as Header parameter from Cognito).
When I try to fetch/read the query response, it triggers the error event. However, in the browser, I can see how 2 HTTP POST responses with 200 code and one of them returning the valid response. For example: if I make the request via POST man I receive the data in 1 response in a good way.
Problem:
I am unable to print the result because it launches the error event with not valid response data.
Browser images:
https://i.postimg.cc/MTMsxZjw/Screenshot-1.png
https://i.postimg.cc/3RstwMgv/Screenshot-2.png
Lambda code:
'use strict';
var AWS = require('aws-sdk'),
documentClient = new AWS.DynamoDB.DocumentClient();
exports.handler = function index(event, context, callback){
var params = {
TableName : "data-table"
};
documentClient.scan(params, function(err, data){
if(err){
callback(err, null);
}else{
console.log(JSON.stringify(data.Items));
callback(null, data.Items);
}
});
}
Client side JS code:
function requestData(pickupLocation) {
$.ajax({
type: 'POST',
url: _config.api.invokeUrl,
headers: {
Authorization: authToken,
},
data: "{}",
cache: false,
success: completeRequest,
error: errorRequest
});
}
function completeRequest(response) {
alert("hello");
alert(response.d);
}
function errorRequest(response) {
alert("hello1");
alert(response.status + ' ' + response.statusText);
}
According to further clarification based on the comments, this looks like API gateway has CORS disabled or enabled with incorrect header value returns.
The solution is to re-enable CORS through API gateway and in the advanced options add Access-Control-Allow-Origin to the header response (if not already on by default).
If you're proxying the response, you need to follow a specific format as described here
'use strict';
console.log('Loading hello world function');
exports.handler = async (event) => {
let name = "you";
let city = 'World';
let time = 'day';
let day = '';
let responseCode = 200;
console.log("request: " + JSON.stringify(event));
// This is a simple illustration of app-specific logic to return the response.
// Although only 'event.queryStringParameters' are used here, other request data,
// such as 'event.headers', 'event.pathParameters', 'event.body', 'event.stageVariables',
// and 'event.requestContext' can be used to determine what response to return.
//
if (event.queryStringParameters && event.queryStringParameters.name) {
console.log("Received name: " + event.queryStringParameters.name);
name = event.queryStringParameters.name;
}
if (event.pathParameters && event.pathParameters.proxy) {
console.log("Received proxy: " + event.pathParameters.proxy);
city = event.pathParameters.proxy;
}
if (event.headers && event.headers['day']) {
console.log("Received day: " + event.headers.day);
day = event.headers.day;
}
if (event.body) {
let body = JSON.parse(event.body)
if (body.time)
time = body.time;
}
let greeting = `Good ${time}, ${name} of ${city}. `;
if (day) greeting += `Happy ${day}!`;
let responseBody = {
message: greeting,
input: event
};
// The output from a Lambda proxy integration must be
// of the following JSON object. The 'headers' property
// is for custom response headers in addition to standard
// ones. The 'body' property must be a JSON string. For
// base64-encoded payload, you must also set the 'isBase64Encoded'
// property to 'true'.
let response = {
statusCode: responseCode,
headers: {
"x-custom-header" : "my custom header value"
},
body: JSON.stringify(responseBody)
};
console.log("response: " + JSON.stringify(response))
return response;
};
If you are using chrome you probably need the cors plugin .

signing SOAP XML using node-js using private key

Am trying to sign the XML using my private key, and using SOAP UI
it gives the proper success response.
to generate the request am using below code
var Authorization = 'Basic ' + new Buffer((sapConfig.sap.username + ':' + sapConfig.sap.password) || '').toString('base64');
soap.createClient(__dirname + '/wsdl/SI_CARWORKZ_Customer_Sen_Sync.wsdl', wsdlOptions, function (err, client) {
client.setSecurity(new soap.WSSecurityCert(privateKey, publicKey, password, 'utf8'));
//client.setSecurity(new soap.ClientSSLSecurity(privateKey, publicKey, ca));
client.SI_CARWORKZ_Customer_Sen_Sync(details, sslOptions, function(err, result, raw, soapHeader) {
console.log('%j', result);
if(_.has(result, "ResponseData") && !_.isEmpty(result.ResponseData.Item)){
var status = _.pluck(result.ResponseData.Item, "Status");
if(status.indexOf('E') != -1){
return callback({status: "error", data: result});
}else{
// insert the user in mongodb
sapLogs.insertCustomers(details.HEADER, function(result){
console.log("customer added");
return callback({status: "success", data: details});
})
}
}else{
return callback({status: "error", data: [], message: "something went wrong." })
}
}, {"Authorization": Authorization});
});
But when am sending the signed xml data using the script it shows me error
Error while valdiating the digital signature. The error was java.lang.NullPointerException while trying to invoke the method com.sap.security.core.ws.wss.tokens.securitytoken.BinarySecurityToken.getSecurityToken()
Is there any issue with my public key or private key?
I have exported them from jks file which is used in SOAP UI.

Getting error: "Unexpected wrapper element found" when trying to call a webservice function where webservice uses WSSecurityCert

I am using meteor.js. I am trying to call a function of a webservice that uses WSSecurityCert.
I created a signed key pair using openssl and sent the public key to the sever administrator so that they include it in their keystore, which they say they did. They also sent me their public key but I don't know where to include it in my code or application.
My code is as follows:
if (Meteor.isServer) {
Meteor.methods({
getVouchers: function(){
var fs = Npm.require('fs');
var soap = Npm.require('soap');
Npm.require('ursa');
var base = process.env.PWD;
var publicKey = fs.readFileSync(base + "/cert.pem", "utf8");
var privateKey = fs.readFileSync(base + "/key.pem", "utf8");
var password = "myPassPhrase";
var url = 'http://www.smartcallesb.co.za:8091/SmartcallServices2/SmartloadService?wsdl';
try
{
var wsSecurity = new soap.WSSecurityCert(privateKey, publicKey, password, 'utf8');
var client = Soap.createClient(url);
client.setSecurity(wsSecurity);
//var result = client.SmartloadService.SmartloadServicePort.getDealerBalance(); //getAllNetworks
var result = client.getDealerBalance();
console.log(result)
}
catch (err)
{
console.log(err)
}
console.log("reached end")
}
});}
When it is run I get the following error:
{ [Error: Soap method call failed [soap-method]]
error: 'soap-method',
reason: 'Soap method call failed',
reason: 'Soap method call failed',
details:
{ [Error: soap:Client: Unexpected wrapper element getDealerBalance found.
Expected {http://www.smartcall.co.za/2010/12/service}getDealerBalance.]
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy requirement
/200702}AsymmetricBinding: The transform algorithms do not match the
requirement.....
Could this be because the host public key that the server admin sent to me is not included in my application, and if so where do I include it? Or otherwise, how do I fix/correct this?

How to replace response body in WSO2 API Manager 1.10.0 Custom Handler

I have written a CustomHandler which verifies if there is a specific key in the request. If the key is missing, handler should send back response to the client with the text saying that the key is missing. When a get request is sent to the server without key in the header, server responds back to the client with the modified payload. But, when a post request is sent to server, it sends back the original payload sent by the client. Below is the code that sends back response to the client with modified payload.
private void handleAuthenticationFailure(MessageContext messageContext, APISecurityException e){
SOAPBody body = messageContext.getEnvelope().getBody();
for (Iterator itr = body.getChildElements(); itr.hasNext();) {
OMElement child = (OMElement) itr.next();
child.detach();
}
org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).
getAxis2MessageContext();
axis2MC.setProperty(Constants.Configuration.CONTENT_TYPE, "application/xml");
axis2MC.removeProperty("NO_ENTITY_BODY");
axis2MC.setProperty("HTTP_SC", HttpStatus.SC_UNAUTHORIZED);
messageContext.setResponse(true);
messageContext.setProperty("RESPONSE", "true");
messageContext.setTo(null);
messageContext.getEnvelope().getBody().addChild(getFaultPayload(e));
Axis2Sender.sendBack(messageContext);
}
private OMElement getFaultPayload(APISecurityException e) {
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace ns = fac.createOMNamespace(APISecurityConstants.API_SECURITY_NS,
APISecurityConstants.API_SECURITY_NS_PREFIX);
OMElement payload = fac.createOMElement("fault", ns);
OMElement errorCode = fac.createOMElement("code", ns);
errorCode.setText(String.valueOf(e.getErrorCode()));
OMElement errorMessage = fac.createOMElement("message", ns);
errorMessage.setText("Missing Credentials");
OMElement errorDetail = fac.createOMElement("description", ns);
errorDetail.setText(e.getMessage());
payload.addChild(errorCode);
payload.addChild(errorMessage);
payload.addChild(errorDetail);
return payload;
}
Am I missing something ? How do I drop the original payload of the post request and send back the modified payload ? Thanks for any help.
We had a similar requirement: replacing an arbitrary string within the body payload of an HTTP response. We achieved this through custom mediation, but the approach should be equally valid through a handler.
We avoided using XML parsing, construction, and injection by using synapse JsonUtil (org.apache.synapse.commons.json.JsonUtil), specifically String jsonResponse = JsonUtil.jsonPayloadToString(axis2) to read the payload body and JsonUtil.newJsonPayload(axis2, jsonResponse, true, true) to write.
If you require the payload to be in XML, you'll want to look at Utils.setFaultPayload and Utils.sendFault, which can be found in their org.wso2.carbon.apimgt.gateway.handlers package at https://github.com/wso2/carbon-apimgt/blob/master/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java.
public static void setFaultPayload(MessageContext messageContext, OMElement payload) {
org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).
getAxis2MessageContext();
JsonUtil.removeJsonPayload(axis2MC);
messageContext.getEnvelope().getBody().addChild(payload);
Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
String acceptType = (String) headers.get(HttpHeaders.ACCEPT);
//If an Accept header has been provided.
if(!StringUtils.isEmpty(acceptType) && !"*/*".equals(acceptType)){
axis2MC.setProperty(Constants.Configuration.MESSAGE_TYPE, acceptType);
}
}
public static void sendFault(MessageContext messageContext, int status) {
org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).
getAxis2MessageContext();
axis2MC.setProperty(NhttpConstants.HTTP_SC, status);
messageContext.setResponse(true);
messageContext.setProperty("RESPONSE", "true");
messageContext.setTo(null);
axis2MC.removeProperty("NO_ENTITY_BODY");
// Always remove the ContentType - Let the formatter do its thing
axis2MC.removeProperty(Constants.Configuration.CONTENT_TYPE);
Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
if (headers != null) {
headers.remove(HttpHeaders.AUTHORIZATION);
headers.remove(HttpHeaders.AUTHORIZATION);
headers.remove(HttpHeaders.HOST);
}
Axis2Sender.sendBack(messageContext);
}

Customize SOAP request send from Windows 8 application

I am consuming a WSDL in a Windows 8 app. I need to customize the SOAP request like
New SOAP Request:
</ns0:Header>
<ns0:Body>
<ns0:Request xmlns:ns0="http://www.ABC.co.il/2004/01/RetrieveEntityDetails/EntityDetailsRequest">
</ns0:Request></ns0:Body></ns0:Envelope>
Current SOAP Request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
</s:Header>
<s:Body>
<RetrieveEntityDetailsXPOP_XmlRequest xmlns="http://tempuri.org/">
<RetrieveEntityDetailsXPOP_Xml xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<requestDoc>
</requestDoc>
</RetrieveEntityDetailsXPOP_Xml>
</RetrieveEntityDetailsXPOP_XmlRequest>
</s:Body>
</s:Envelope>
How will I change the namespace and set a request tag inside the body tag.
Code:
Client = new EAI_RetrieveEntityDetailsXP_ServiceSoapClient();
Client.RetrieveEntityDetailsXPOP_XmlCompleted += Client_RetrieveEntityDetailsXPOP_XmlCompleted;
XElement requestData = GetRequestData();
using (new OperationContextScope(Client.InnerChannel))
{
// Create a custom soap header
var msgHeader = MessageHeader.CreateHeader("myCustomHeader", string.Empty, "myValue");
// Add the header into request message
OperationContext.Current.OutgoingMessageHeaders.Add(msgHeader);
Client.RetrieveEntityDetailsXPOP_XmlAsync(requestData);
}
I have actually used HttpCleint to call this service by using following code. Using this we can generate the SOAP request as desired.
string soapString = ConstructSoapRequest();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("SOAPAction", SOAPActionUri);
var content = new StringContent(soapString, Encoding.UTF8, "text/xml");
using (var response = await client.PostAsync(Uri, content))
{
var soapResponse = await response.Content.ReadAsStringAsync();
return soapResponse;
}
}
private string ConstructSoapRequest()
{
return String.Format(#"<ns0:Envelope xmlns:ns0='http://www.cellcom.co.il/2004/01/std-headers'>
<ns0:Header>
</ns0:Header>
<ns0:Body>
<ns0:Request xmlns:ns0='http://www.cellcom.co.il/2004/01/RetrieveEntityDetails/EntityDetailsRequest'>
</ns0:Request></ns0:Body></ns0:Envelope>", 100);
}