parsing soap response using Cypress - soap

Facing issues while parsing this response using cypress,
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header/>
<soapenv:Body>
<p385:summaryOutputArray xmlns:p385="http://dataobject.simulation.com">
<p385:userName>MS</p385:userName>
</p385:summaryOutputArray>
</soapenv:Body>
</soapenv:Envelope>
Using Cypress How to read userName TAG? I can see in the log that whole xml is printed but can't get to the particular tag. Also, while using the function to get to the particular tag to get the value, I am getting null property
Firstly I used this. This is giving error. property reading null
const parser = new DOMParser();
const xmlDOM = parser.parseFromString(quoteResp, 'text/xml');
cy.log('xmlDOM ' + quoteResp.);
cy.wrap(Cypress.$(quoteResp)).then(quoteResp => {
const txt = quoteResp.filter('Body').find('p385:userName').text();
cy.log('value:' + txt);
});
Using this I can see the whole response in logs
then(quoteResp => {cy.log('xmlDOM ' + quoteResp.body);

It's not necessary to wrap the response, just query the xmlDOM like this
const xmlDOM = parser.parseFromString(quoteResp, 'application/xml');
const userName = xmlDOM.querySelector('userName').textContent
expect(userName).to.eq('MS')

Related

Google Apps Script SOAP response is encoded. How/where to add base64decode to see the response as xml

Below is my working Google apps script SOAP API envelop call. It works to connect ok and as you can see below it returns a response, but my response is encoded. How/where to add a bit to do a Base64decode to see the XML that is returned instead of the string of characters? I am totally new to SOAP API and still a newbie to apps script too. Thanks!
function getData() {
var webservice = ‘https://someplace.com/services/stuff/’;
var xml = '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://someurlhere.com">'
+ '<soapenv:Header/>'
+ '<soapenv:Body>'
+ '<ser:getReportXML soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> '
+ '<in0 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + userid + '</in0> '
+ '<in1 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + password + '</in1> '
+ '<in2 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + startDate + '</in2> '
+ '<in3 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + endDate + '</in3> '
+ '</ser:getReportXML> '
+ '</soapenv:Body>'
+' </soapenv:Envelope>'
var options = {
headers: {"SOAPAction" :"https://someplace.com/services/stuff/"},
method: "post",
contentType: "text/xml",
payload: xml,
muteHttpExceptions: true,
};
var serviceaddress = webservice;
var response = UrlFetchApp.fetch(serviceaddress, options);
Logger.log(response);
};
It returns an encoded string in the response, but I want to see the actual XML results:
[19-01-31 11:46:02:122 PST] <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><ns1:getReportXMLResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1=" http://someurlhere.com "><getReportXMLReturn xsi:type="soapenc:base64Binary" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">WMui8xyxcPQXmZgSerdPd94bwWxGsAMgdmVyc2lvbj0iFRxlTSerdgiPz4NCg0KPQFET0NUW
I am trying to get the response output to look like xml and not a string of characters
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ETRANS PUBLIC "-//Something//ethings DTD//EN" "https://www.url.com/dtd/ethings_1_0.dtd">
<ETRANS>
<USER ID="AABB1122" USER_NAME="Smith, John" DATE="2019-02-01 09:41:45" DEPT_ID=""/>
</ETRANS>
So I figured out that my response does have the encoded body of the XML, but it also has all these extra bits in the response before the actual encoded data, so the decoder fails as it doesn't know what to do with this bit shown here at the beginning of the response
[19-01-31 11:46:02:122 PST] <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><ns1:getReportXMLResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1=" http://someurlhere.com "><getReportXMLReturn xsi:type="soapenc:base64Binary" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
and a few more bits at the bottom that are like some closing of the above bits. Is there something I need to pass in my request to have the SOAP request only return the character string and not these extra bits that look like it is putting the "envelope" around the encoded data it is sending back?
I finally figured this out. I don't know if there is a "better" way to do this, but if you see what I did maybe you might share that "better" way. So I added the "NEW BIT" lines below. I had to get rid of the SOAP Envelop in order to decode the base64 bit. The only way I could figure out in Google Apps Script was to save the response as a file as that seemed to "magically" take the SOAP away. So then I had to get the base64 bit that was left that was in the MyTestFile file I created into a text string and decode/convert that and it created the xml I was looking for. I hope this can help someone else out.
function getData() {
var webservice = ‘https://someplace.com/services/stuff/’;
var newDocName = 'MyTestFile'
var xml = '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://someurlhere.com">'
+ '<soapenv:Header/>'
+ '<soapenv:Body>'
+ '<ser:getReportXML soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> '
+ '<in0 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + userid + '</in0> '
+ '<in1 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + password + '</in1> '
+ '<in2 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + startDate + '</in2> '
+ '<in3 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">' + endDate + '</in3> '
+ '</ser:getReportXML> '
+ '</soapenv:Body>'
+' </soapenv:Envelope>'
var options = {
headers: {"SOAPAction" :""},
method: "post",
contentType: "text/xml",
payload: xml,
muteHttpExceptions: true,
};
var serviceaddress = webservice;
var response = UrlFetchApp.fetch(serviceaddress, options).getContentText();
//Logger.log(response);
//NEW BIT BEGINS HERE THAT DECODED THE RESPONSE
var blob = DriveApp.createFile('dummy',response, 'text/html').getBlob();
var resource = {
title: newDocName,
convert: true,
mimeType: 'application/vnd.google-apps.file'
};
var file = Drive.Files.insert(resource,blob);
var doc = DocumentApp.openById(file.id);
var text = doc.getBody().getText();
var decoded = Utilities.base64Decode(text,Utilities.Charset.UTF_8); // This was a byte array
var decodedstr = Utilities.newBlob(decoded).getDataAsString() // This was the xml I was looking for
Logger.log(decodedstr);
//NEW BIT ENDS HERE
};

Call soap web-service in mobilefirst hybrid app

I'm attempting to call SOAP Web-Service in hybrid app. How should I form SOAP message correctly if the back-end service displays the next error in log:
Caused by: com.ibm.websphere.security.WSSecurityException: Exception
org.apache.axis2.AxisFault: CWWSS7509W: The received SOAP request
message is rejected becasue it does not correctly specify SOAP action
and WS-Addressing action while there is at least one PolicySet
attachment at operation level of the
TestServiceService.TestServicePort service. ocurred while running
action:
com.ibm.ws.wssecurity.handler.WSSecurityConsumerHandler$1#9b5addf6 at
com.ibm.ws.security.context.ContextImpl.runWith(ContextImpl.java:394)
at
com.ibm.ws.wssecurity.platform.websphere.auth.WSSContextImpl.runWith(WSSContextImpl.java:65)
... 35 more
This is content of js file in adapter
function getToken(){
var token = WL.Server.getActiveUser().attributes.LtpaToken;
var fulltoken = "LtpaToken2=" + token;
return fulltoken;
}
function callService(){
WL.Logger.warn("INSIDE callService "+getToken());
var path="checkauth/TestServiceService";
var request=
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:q0="http://provider.ws/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<q0:callService />
</soapenv:Body>
</soapenv:Envelope>;
var input = {
method : 'post',
returnedContentType : 'xml',
path : path,
body: {
content: request.toString(),
contentType: 'text/xml; charset=utf-8',
},
headers: {"Cookie": getToken()}
};
var result= WL.Server.invokeHttp(input);
return result;
}
This is SOAP Envelope which was displayed via TCP/IP Monitor:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<s:Security xmlns:s="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:w2="http://www.ibm.com/websphere/appserver/tokentype" soapenv:mustUnderstand="1">
<u:Timestamp>
<u:Created>2015-08-10T13:18:56.644Z</u:Created>
</u:Timestamp>
<s:BinarySecurityToken ValueType="w2:LTPAv2" u:Id="ltpa_20">dt8G5gZ9PpZ/Ea5oXr6EQd8dpmfXKiqeXiShPlpSWntK59hUzyoDNX9TKq1nFLfxUEJyJdjMxoG7EVxw8Q1zhyZdYhTXnsMkNVqScvSsPpX7ln/ad+/WAHqaaFymD8XtVEsjOlezQDarPaUmnKAQRUSrLkRnL5B1MoCclTe129Oojg8o+hACgDKjuvPnvL8jaf45wNiou6Il5ZOayBcoHpNehI7i2hADa4fTKzX/T69OPnsZOyWYrNosdezNd24b61vs85k2YK26rLTp5dkEp8f3mwKZBwOOK4z1wQdiAXJf6kQvzR22SfFitbJA5MStlBcovHAvB5T+J5Ip80/kI5BPa2ogoufd9HZAdKTNII8cHpHBN2Ub/+atzg1L7EhIWuzO1BPI62KoU/hPqAHn3uGCGrbIILesKx0TPvlgmU4Bg54H9prC0I8hgXbO1HLuz4M5DNE5ASFbH0W3LJ/UU7BGXJs6iJmfAfJtQ+ip5ZFHlLItZA+ca2LkVWmyD/xKVxyxHE1uDz8zV/CfV9Km0T+8FTA0Cfi/PIb5KiAagdrmqtw6GuJDbSCsC3sdh21G/cA3Y0p/f+rhDw8m/e17y1cEuq9HOBharwn7ET3wO30V4D4rGoLhd4QsN6X1z89gZmZVaI6J9urpPAEiSndmyQ==</s:BinarySecurityToken>
</s:Security>
<wsa:To>http://X.X.X.X:9082/checkauth/TestServiceService</wsa:To>
<wsa:MessageID>urn:uuid:5d1f8656-5550-40d2-9f39-c58f57279489</wsa:MessageID>
<wsa:Action>http://provider.ws/TestServiceDelegate/callServiceRequest</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<ns2:callService xmlns:ns2="http://provider.ws/"/>
</soapenv:Body></soapenv:Envelope>
The body consists of a single line, and this makes the scenario a peculiar one, as well as raises a question is this is meant to work at all.
I can suggest two things:
You can attempt to parse your WSDL file with the SOAPUI application; it should show you how the SOAP envelope is supposed to look like
Use the Service Discovery feature in MobileFirst Studio that can generate the adapter for you with a ready SOAP envelope. Read more how to use this feature, here: http://www-01.ibm.com/support/knowledgecenter/SSHS8R_7.0.0/com.ibm.worklight.dev.doc/dev/c_using_service_discovery_wizard_to_explore_backend-services.html

Mock response with repetitions in soapui

I'm trying to do mock response based on the request.
With a request like that:
<soapenv:Body>
<con:person>
<person>
<name>John</name>
<age>18</age>
</person>
</con:person>
</soapenv:Body>
and a reponse like that
<soapenv:Body>
<con:result>
<person>
<name>?</name>
<age>?</age>
<country>?</country>
<city>?</city>
</person>
</con:result>
</soapenv:Body>
I can use elements from the request to take what i want in database and create the response.
But when i have a request with many person like that
<soapenv:Body>
<con:person>
<person>
<name>John</name>
<age>18</age>
</person>
<person>
<name>Doe</name>
<age>50</age>
</person>
</con:person>
</soapenv:Body>
I don't know how i can take all data from the request and how i can use them to create a response like that:
<soapenv:Body>
<con:result>
<person>
<name>John</name>
<age>18</age>
<country>France</country>
<city>Paris</city>
</person>
<person>
<name>Doe</name>
<age>50</age>
<country>Spain</country>
<city>Madrid</city>
</person>
</con:result>
</soapenv:Body>
With the same number of person in the request and in the response.
I hope i was clear and i thank you for your answers.
I managed to do something similar. First, I defined my mock response object as:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stac="stackOverflow.question">
<soapenv:Header/>
<soapenv:Body>
<stac:result>
${personElements}
</stac:result>
</soapenv:Body>
</soapenv:Envelope>
I then created the content for ${personElements} using this Groovy script:
import groovy.xml.MarkupBuilder
// An array from which county and city will be drawn randomly
def countryArray = [["Australia", "Perth"],
["Spain", "Madrid"],
["England","London"],
["Brazil", "Rio"]]
def random = new Random()
// create XmlHolder for request content
def holder = new com.eviware.soapui.support.XmlHolder( mockRequest.requestContent )
// Get the name and age values from the request
def requestItems = holder.getNodeValues( "//*:person/*:person/descendant::*")
def writer = new StringWriter()
def personElements = new MarkupBuilder(writer)
// Build the response elements
for (int index = 0; index < requestItems.size() - 1; index += 2) {
personElements.'stac:person'() {
'stac:name'(requestItems[index])
'stac:age'(requestItems[index+1])
// Choose a random county and city from the array
def randomIndex = random.nextInt(countryArray.size())
'stac:country'(countryArray[randomIndex][0])
'stac:city'(countryArray[randomIndex][1])
}
}
// Add the newly created elements to the response
context.personElements = writer.toString()
This gave me a response like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stac="stackOverflow.question">
<soapenv:Header/>
<soapenv:Body>
<stac:result>
<stac:person>
<stac:name>Dolly Bonkers</stac:name>
<stac:age>42</stac:age>
<stac:country>Brazil</stac:country>
<stac:city>Rio</stac:city>
</stac:person>
<stac:person>
<stac:name>Mary Poppins</stac:name>
<stac:age>82</stac:age>
<stac:country>England</stac:country>
<stac:city>London</stac:city>
</stac:person>
<stac:person>
<stac:name>Bilbo Baggins</stac:name>
<stac:age>102</stac:age>
<stac:country>Australia</stac:country>
<stac:city>Perth</stac:city>
</stac:person>
<stac:person>
<stac:name>Johnny Hardcase</stac:name>
<stac:age>22</stac:age>
<stac:country>Spain</stac:country>
<stac:city>Madrid</stac:city>
</stac:person>
</stac:result>
</soapenv:Body>
</soapenv:Envelope>
The script just takes random city and country values from a small array but you could come up with something better if you wanted consistent responses for certain names.

Authentication Issue with eBatNS Trading API trying to get SessionID

I'm trying to get a session ID using the eBatNS SOAP API.
The function which makes the call is pretty simple, but always returns an Authentication error. You can see the function below
public function get_ebay_session()
{
error_reporting(0);
$ruName = "Forward_Thinker-ForwardT-57fe-4-rybapdi";
$sessionID = "";
//Connect to eBay and get a list of all products
require_once 'eBay/EbatNs/EbatNs_ServiceProxy.php';
require_once 'eBay/EbatNs/GetSessionIDRequestType.php';
require_once 'eBay/EbatNs/EbatNs_Logger.php';
//Get a SessionID
$session = new EbatNs_Session('eBay/config/ebay.config.php');
print_r($session);
echo "<hr>";
$cs = new EbatNs_ServiceProxy($session);
$cs->attachLogger(new EbatNs_Logger(false, 'stdout', true, false));
print_r($cs);
echo "<hr>";
$req = new GetSessionIDRequestType();
$req->setRuName($ruName);
print_r($req);
echo "<hr>";
$result = $cs->GetSessionID($req);
$sessionID = $result->SessionID;
print_r($result);
echo "<hr>";
session_start();
$_SESSION['eBaySessionID'] = $sessionID;
$return = $ruName."\n".$sessionID;
$this->set(compact('return'));
}
As you can see I have attached a logger. The logger shows that this is the request being made.
<?xml version="1.0" encoding="utf-8"?><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/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns="urn:ebay:apis:eBLBaseComponents" ><soap:Header><RequesterCredentials><eBayAuthToken>AgAAAA**AQAAAA**aAAAAA**wS7oUQ**nY+sHZ2PrBmdj6wVnY+sEZ2PrA2dj6wHloSkD5aGog+dj6x9nY+seQ**It4BAA**AAMAAA**CB7yrHTyG3kQbA6KOwf0ZO2MqyPs/Dfn5u5r8ZDVGeWNvB</eBayAuthToken><Credentials><AppId>ForwardT-57fe-41ea-b90e-52fd0b541b88</AppId><DevId>5eefba38-e226-4876-9ada-d8743f571aeb</DevId><AuthCert>b57984cb-ba9c-430c-a8fc-c08f9ac46e75</AuthCert></Credentials></RequesterCredentials></soap:Header><soap:Body><GetSessionIDRequest><Version><![CDATA[815]]></Version><RuName><![CDATA[Forward_Thinker-ForwardT-57fe-4-rybapdi]]></RuName></GetSessionIDRequest></soap:Body></soap:Envelope>
And that this is the response being returned:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode xmlns:ns1="http://xml.apache.org/axis/">ns1:FailedCheck</faultcode>
<faultstring>Authorisation token is invalid.</faultstring>
<faultactor>http://www.ebay.com/ws/websvc/eBayAPI</faultactor>
<detail>
<FaultDetail>
<ErrorCode>931</ErrorCode>
<Severity>Error</Severity>
<DetailedMessage>Validation of the authentication token in API request failed.</DetailedMessage>
</FaultDetail>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
My ebay.config.php file has all the correct keys and, as far as I can tell, all of the correct information. Does anyone have any tips for resolution?
Danny
This issue was caused by the eBatNS API sending a token from a previous request in the request to get a new token. This isn't supported by ebay.
This is resolved by setting the token mode on the session to 0 or false.
$session->setTokenMode(0)

savon soap attributes

Am trying to query netsuite api for currencies. The following soap request works for me in SOAP UI client. But i am having a hard time trying to get the same working with ruby's savon gem version 0.9.7.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:messages_2012_2.platform.webservices.netsuite.com" xmlns:urn1="urn:core_2012_2.platform.webservices.netsuite.com">
<soapenv:Header>
<urn:passport>
<urn1:email>xxx#abc.com</urn1:email>
<urn1:password>xxx</urn1:password>
<urn1:account>xxx</urn1:account>
</urn:passport>
</soapenv:Header>
<soapenv:Body>
<urn:getAll>
<urn:record recordType="currency"/>
</urn:getAll>
</soapenv:Body>
</soapenv:Envelope>
Basically i am not able to set the attribute on the urn:record element. The following is not working:
response = client.request :urn, :get_all do
soap.body = { "urn:record" => { :attributes! => { "recordType" => "currency" } } }
end
Please advise.
As explained on http://savonrb.com the key in the attributes! hash has to match the XML tag. You want to write something like this:
response = client.request :urn, :get_all do
soap.body = {'urn:record'=>'',
:attributes!=>{'urn:record'=>{'recordType'=>'currency'}}
}
end
Please let us know whether this solves it for you.
Double-check the raw soap request. :get_all may need to be "getAll" to have savon take you literally; it may be changing it to GetAll
In new versioin of savon you can place :attributes in the local context for the operation tag:
#interaction_client.call(:retrieve_interaction, message: message_hash, :attributes => { 'attachmentInfo' => include_attachments.to_s })
In this case, the attachmentInfo attribute will be placed into the main operation tag linked with operation, in this example this would be the ns:RetrieveInteractionRequest tag.
Please note that the syntax does not contains the exclamation mark.