I'm currently working on a project, which requires flight status information from OAG's On-Demand Flight Status information service (WSDL).
I can test the service with SOAPui. Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.oag.com">
<soapenv:Header/>
<soapenv:Body>
<ws:Authenticate>
<ws:UserId>test</ws:UserId>
<ws:Password>test</ws:Password>
</ws:Authenticate>
</soapenv:Body>
</soapenv:Envelope>
Response (using proper username / password):
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<AuthenticateResponse xmlns="http://ws.oag.com">
<AuthenticateResult>1</AuthenticateResult>
<SecurityToken xsi:type="xsd:string"><![CDATA[<OAGToken><Username>********</Username><IssueDateTime>2015-11-05T07:12:17</IssueDateTime><ExpiryDateTime>2015-11-06T07:12:17</ExpiryDateTime><CustomerNo>********</CustomerNo><Signature>***************************</Signature></OAGToken>]]></SecurityToken>
</AuthenticateResponse>
</soap:Body>
</soap:Envelope>
I'm both interested in the AuthenticateResult value and embedded XML part within SecurityToken.
The WSDL lacks XML element types in two spots at element SecurityToken. To be able to generate apex from the WSDL, I made these elements type string (also tested token).
After calling the webservice with the generated apex, the value of SecurityToken does not contain the full CDATA contents, but a concatenation of all XML values within the CDATA embedded XML.
So I decided to manually call the service with HTTPRequest.
Code:
public class fc_OAGFS_OnDemand_Client {
// TODO: Place in custom setting
private static final String username = 'test';
private static final String password = 'test';
private static final String authenticateEndPoint = 'https://secure.oag.com/ws_oag_com/oagflightstatusinformation.asmx';
public static void authenticate() {
String payLoad = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.oag.com"><soapenv:Header/><soapenv:Body><ws:Authenticate><ws:UserId>'+username+'</ws:UserId><ws:Password>'+password+'</ws:Password></ws:Authenticate></soapenv:Body></soapenv:Envelope>';
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setHeader('Content-Type','text/xml;charset=UTF-8');
req.setHeader('SOAPAction', ''); // Empty as in SOAPui
req.setEndpoint(authenticateEndPoint);
req.setHeader('Content-Length',String.valueOf(payLoad.length()));
req.setBody(payLoad);
HttpResponse res = h.send(req);
System.debug('>>> Answer String '+res.getBody());
System.debug('>>> Answer XML Document '+res.getBodyDocument().toXmlString());
System.debug('>>> Answer BLOB '+res.getBodyAsBlob().toString());
}
}
Interesting part of debug log:
14:22:42.956 (3956667815)|USER_DEBUG|[47]|DEBUG|>>> Answer String 1<OAGToken><Username>********</Username><IssueDateTime>2015-11-05T07:22:42</IssueDateTime><ExpiryDateTime>2015-11-06T07:22:42</ExpiryDateTime><CustomerNo>********</CustomerNo><Signature>*********************************************</Signature></OAGToken>
14:22:42.957 (3957449646)|USER_DEBUG|[48]|DEBUG|>>> Answer XML Document 1<OAGToken><Username>********</Username><IssueDateTime>2015-11-05T07:22:42</IssueDateTime><ExpiryDateTime>2015-11-06T07:22:42</ExpiryDateTime><CustomerNo>********</CustomerNo><Signature>*********************************************</Signature></OAGToken>
14:22:42.957 (3957601751)|USER_DEBUG|[49]|DEBUG|>>> Answer BLOB 1<OAGToken><Username>********</Username><IssueDateTime>2015-11-05T07:22:42</IssueDateTime><ExpiryDateTime>2015-11-06T07:22:42</ExpiryDateTime><CustomerNo>********</CustomerNo><Signature>*********************************************</Signature></OAGToken>
As above log shows, only a mangled part of the response from OAG's service is returned. Salesforce performs some processing / interpretation.
How can I receive the complete response, including SOAP envelope?
Best Answer
I tried replicating your issue, using both WebServiceCallout.invoke and HttpRequest. This was somewhat limited as I didn't have valid credentials to the web service. I've applied for a trial account, so I'll see what comes of that.
As you mentioned in the question, I needed to add a type attribute in the WSDL for the two elements named SecurityToken that were missing the value.
From there I could use Wsdl2Apex to generate the required Apex classes (OK, I actually used the FuseIT SFDC Explorer Wsdl2Apex implementation, but the result should be the same. Disclose, this is a free tool from my current employer).
Using the following anonymous Apex it appeared to process fine (aside from the invalid credentials).
I also tried generating the equivalent HttpRequest. Again, no immediate issue processing the response into an AuthenticateResponse_element.
I then tried making a test case and HttpCalloutMock implementation that returned the same response that you get from SoapUI.
Mock
Test
That test gives a positive response.
A couple of thoughts:
req.setHeader('SOAPAction', ''); // Empty as in SOAPui
toreq.setHeader('SOAPAction', 'blank'); // Empty as in SOAPui
See Missing SOAP action header