I am working with an API that has two different URLs for specific types of functions. The first, is a transactional API that supports either JSON or SOAP requests. I have called all of the functions I need within this API using exclusively JSON calls and everything appears to be working perfectly fine.
The second is a reporting API used to locate and/or download reports. This API works exclusively with SOAP. I have not been able to get any function in this API working properly. I have attempted to contact the company's support group, but they do not have anybody who can assist me with API calls in ColdFusion. I have attempted two different ways to interface with this API and get access to the functions and have come up empty. Below are my examples and as much information as I can provide; our service provider's API and associated documentation are confidental, but I can answer some questions related to specific things that have to do with my code.
Way 1: Creating a webservice object.
The first way I tried to create this SOAP call was through a webservice object. Using the metadata exchange point URL, I passed it into the createObject function like this:
<cfset argStruct = structNew() />
<cfset argStruct['username'] = 'myusername' />
<cfset argStruct['password'] = 'mypassword' />
<cfset testSvc = createObject('webservice','https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/mex',argStruct) />
When I run this code, I get the following error message:
Cannot generate stub objects for web service invocation. Name: https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/mex. WSDL: https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/mex. javax.wsdl.WSDLException: WSDLException (at /wsdl:definitions/wsdl:import): faultCode=OTHER_ERROR: Unable to resolve imported document at 'https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/mex?wsdl=wsdl1', relative to 'brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/': java.io.IOException: Server returned HTTP response code: 401 for URL: https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/mex?wsdl=wsdl1
Since 401 errors are typically bad authorizations, I double-checked the address by calling the URL directly in the browser, where I was prompted with a UN/PW. I entered in my values, and was allowed to access the URL, recieving this XML in return:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="ReportingAPI" targetNamespace="https://https://brandnameapi.serviceprovider.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:tns="https://https://brandnameapi.serviceprovider.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:i0="https://https://brandnameapi.serviceprovider.com/ReportingAPI/soapBinding" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<wsdl:import namespace="https://https://brandnameapi.serviceprovider.com/ReportingAPI/soapBinding" location="https://https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/mex?wsdl=wsdl1"/>
<wsdl:types/>
<wsdl:service name="ReportingAPI">
<wsdl:port name="BasicHttpBinding_IReportingAPI" binding="i0:BasicHttpBinding_IReportingAPI">
<soap:address location="https://https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/soap"/>
</wsdl:port>
</wsdl:service>
This is about as far as I've gotten. When I call the URL with my browser and pass the authentication information, I'm allowed to access the XML. When I try to do so with ColdFusion, I get 401 errors.
Way 2: cfhttp request calls
When I switched to using cfhttp, I seemed to get a little further. When I use this:
<cfhttp url="https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/mex"
username="myusername" password="mypassword" method="get" result="httpResponse"
timeout="300">
</cfhttp>
httpResponse return appropriate page information, and httpResponse.filecontent returns the same XML I recieved when I called it directly in my browser.
Going one step further, I took the SOAP URL and attempted to call a function in the API that returns a list of available report files. I used the same known-working process I used for all of my JSON calls in the transaction API:
<cfhttp url="https://brandnameapi.sandbox.serviceprovider.com/vernum/ReportingAPI.svc/soap/queryAvailableReportFiles"
username="myusername" password="mypassword" method="post"
result="httpResponse" timeout="300">
<cfhttpparam type="formfield" name="typeOfReport" value="DailyCSVFile" />
</cfhttp>
When I run this code, I get a status code of 415 and an error of, 'Cannot process the message because the content type 'application/x-www-form-urlencoded' was not the expected type 'multipart/related; type="application/xop+xml"'
When I add this line between my cfhttps:
<cfhttpparam type="header" name="Content-Type" value='multipart/related; type="application/xop+xml"' />
I get the same error as directly above, but the status code changes to 400. I have not included everything I've tried to do, only where I'm at right now. I will answer as many questions as I can and will reperform steps as directed to find a solution to this problem.
Update: As requested, I have changed the cfhttp call to attempt to pass XML instead of a form field. My XML code is ripped directly from the API documentation that has an example of a raw data for a request from the API for a different function:
<cfsavecontent variable="soapBody">
<cfoutput>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<queryAvailableReportFiles
xmlns="https://brandnameapi.sandbox.serviceprovider.com/contract">
<fileName>DailyCSVFile</fileName>
</queryAvailableReportFiles>
</s:Body>
</s:Envelope>
</cfoutput>
</cfsavecontent>
<cfhttp url="https://prismproapi.sandbox.koretelematics.com/4/ReportingAPI.svc/soap/queryAvailableReportFiles" username="vfapi" password="bPzqQyK3" method="post" result="httpResponse" timeout="300">
<cfhttpparam type="xml" value="#trim(soapBody)#" />
</cfhttp>
To be fair, I have no idea if I'm doing that right. The error message that returns from it is, "The message with To https://prismproapi.sandbox.koretelematics.com/4/ReportingAPI.svc/soap/queryAvailableReportFiles cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree." I also get a 500 error.
cfhttp
to make my web service calls. I believe it gives you more control over the configuration aspects needed for most web services. Is the reporting web service expecting XML content? – Miguel-Fcfhttp
call. But you will need to know what the service is wanting in order to do that. – Miguel-F