ColdFusion11 SOAP Action Error - soap

I'm very new to SOAP, but I've looked all over and can't seem to get an answer for this. I think it has to do with the SOAPAction in the <cfhttpparam> tag but I'm not sure what the syntax is. Whatever I put in produces the following error:
The message with Action 'http://InvoiceCollector.hypur.com/PostInvoice' 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).
My SOAP body looks like this:
<cfsavecontent variable="SOAPBody">
<cfoutput>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:dat="http://schemas.datacontract.org/2004/07/DataTransferObjects">
<soapenv:Header/>
<soapenv:Body>
<tem:PostInvoice>
<tem:PoSToken>"XXXXX"</tem:PoSToken>
<tem:MerchantToken>"XXXXX"</tem:MerchantToken>
<tem:Invoice>
<dat:Cash>1</dat:Cash>
<dat:Change>1</dat:Change>
<dat:CreatedBy>"Me"</dat:CreatedBy>
<dat:CurrencyCode>"usd"</dat:CurrencyCode>
<dat:DiscountAmount>1</dat:DiscountAmount>
<dat:DiscountPercent>1</dat:DiscountPercent>
<dat:DueDate>2015-08-13T12:00:00</dat:DueDate>
<dat:InvoiceDate>2015-08-13T12:00:00</dat:InvoiceDate>
<dat:InvoiceItems>
<dat:InvoiceItemDTO>
<dat:Description>"Desc"</dat:Description>
<dat:DiscountAmount>1</dat:DiscountAmount>
<dat:DiscountPercent>1</dat:DiscountPercent>
<dat:Name>"Adam"</dat:Name>
<dat:Quantity>1</dat:Quantity>
<dat:Unit>"lb"</dat:Unit>
<dat:UnitPrice>1</dat:UnitPrice>
</dat:InvoiceItemDTO>
</dat:InvoiceItems>
<dat:InvoiceNumber>123</dat:InvoiceNumber>
<dat:InvoiceTax>1</dat:InvoiceTax>
<dat:IsTaxCalculatedAfterDiscount>false</dat:IsTaxCalculatedAfterDiscount>
<dat:MerchantMemo>"Memo"</dat:MerchantMemo>
<dat:Note>"Note"</dat:Note>
<dat:PaidDate>2015-08-13T12:00:00</dat:PaidDate>
<dat:PoSID>2</dat:PoSID>
<dat:PoSName>1</dat:PoSName>
<dat:Status>1</dat:Status>
<dat:SubTotal>1</dat:SubTotal>
<dat:TaxInclusive>1</dat:TaxInclusive>
<dat:Total>1</dat:Total>
</tem:Invoice>
</tem:PostInvoice>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
which I've tested in soapUI and it connects with the website but has weird issues (it throws an enum error with any <status> values, but if I comment it out then it connects and returns error messages for invalid PoSToken and MerchantTokens, but after I enter those correctly, it doesn't return any data at all.)
I then grab the expected information with the following code:
<cfhttp url="https://devapi.hypur.com/InvoiceCollector/InvoiceCollector.svc?wsdl" method="post" result="httpResponse">
<cfhttpparam type="header" name="SOAPAction" value="http://InvoiceCollector.hypur.com/PostInvoice"/>
<cfhttpparam type="header" name="accept-encoding" value="no-compression"/>
<cfhttpparam type="xml" value="#trim(SOAPBody)#" />
<cfdump var="#soapResponse#">
And it doesn't matter what I put as the value in the
<cfhttpparam type="header" name="SOAPAction" value="http://InvoiceCollector.hypur.com/PostInvoice"/>
tag it always throws the same error.
Any help would be appreciated. Thank you in advance.

So, I ended up using the SOAPAction provided in soapUI (It's under the Raw HTML tab for the outgoing xml) and changed the Status value to Paid and got it working.
So the ColdFusion looks like this:
<cfhttp url="https://devapi.hypur.com/InvoiceCollector/InvoiceCollector.svc" method="post" result="httpResponse">
<cfhttpparam type="header" name="SOAPAction" value="http://tempuri.org/IInvoiceCollector/PostInvoice"/>
<cfhttpparam type="xml" value="#trim(SOAPBody)#" />
Just in case anyone else runs into this problem.

Related

Creating a comment that gets displayed in generated request? WSDL SOAP xml

Im in the process of writing a wsdl file for an existing system. I'd like to add comments to generated requests.
For instance this:
<xsd:simpleType name="coffeetype">
<xsd:restriction base="xsd:integer">
<!--0=likescoffee,1=doesnotlikecoffe-->
<xsd:enumeration value="0" />
<xsd:enumeration value="1" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="CoffeeRequestInput" nillable="false" type="tns:coffeetype" />
Should look like this in the generated request: (eg. when loading the WSDL in SoapUI)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="https://example.com/some.wsdl">
<soapenv:Header/>
<soapenv:Body>
<!--0=likescoffee,1=doesnotlikecoffe-->
<wsdl:CoffeeRequestInput>0</wsdl:CoffeeRequestInput>
</soapenv:Body>
</soapenv:Envelope>
I was able to see these comments when opening the WSDL but not when generating a request from that WSDL.
Already looked into annotations but I wasn't able to use them to create the result I wanted. (Probably an error on my side)
In short you cannot create documentation in requests as you would like to. However you can generate documentation from your WSDL that can be be very useful. By using the "xsd:documentation" tag you can add documentation directly to the elements.
For example
<xsd:simpleType name="coffeetype">
<xsd:restriction base="xsd:integer">
<xsd:enumeration value="0" />
<xsd:enumeration value="1" />
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="CoffeeRequestInput" nillable="false" type="tns:coffeetype">
<xsd:annotation>
<xsd:documentation>
This object is the CoffeeRequestInput object is an Enumeration which can be used to determine is the user sending the request likes coffee or not.
Valid values for the enumeration is as follows:
0 = like coffee
1 = does not like coffee (probably a user not a programmer making a request).
Some other things that you need to document goes here.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
You can then use software such as Altova StyleForce, LiquidXML and OxyGen to generate PDF, Word documents or HTML pages which shows the SOAP services and operations with all your comments included.
If you feel up to it you can write your own XLST to transform your WSDL and XSD's into a neat HTML page which documents you interfaces as well. The best part about this is that when you update the WSDL with new operations and so on that the documentation is updated as well.

Does ColdFusion support REST API URIs with a dynamic token in the middle of the URI?

I've been playing with ColdFusion 11's REST API support and am wondering if it's possible to have it support a URI with a dynamic token in the middle of the URI instead of only at the end. That is, it very easily supports URIs like:
/rest/users/12345
where the 12345 is dynamic (in this case, the user's userID). But I haven't been able to find a way (without a tremendous amount of URI hacking) to support URIs like:
/rest/users/12345/emailAddresses
So, is it possible to do this in ColdFusion (11 or 2016)? If not, is it supported in Taffy (I didn't see where it is but I could be wrong)?
TIA
It's been a while and I wanted to provide the answer in case anyone else has this same question...
ColdFusion, when defining a CFC for a REST endpoint, allows you to specify wildcards/variable names in the restpath attribute to both the <cfcomponent> and <cffunction> tags. You would then define <cfargument> tags for each one of these variables so that you can access them within your function. For example:
<cfcomponent rest="true" restpath="/users/{userId}/pets" ... >
<cffunction name="getPets" access="remote" httpMethod="GET">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/ --->
<!--- do stuff using the arguments.userId (123) variables --->
</cffunction>
<cffunction name="getPet" access="remote" httpMethod="GET" restpath="{petId}">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<cfargument name="petId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/456/ --->
<!--- do stuff using the arguments.userId (123) and/or arguments.petId (456) variables --->
</cffunction>
</cfcomponent>
The keys here are using the restpath attribute with the variable defined as a variable name in curly braces and then defining those variables as arguments to the function with a restargsource attribute set to "Path".
I hope this helps.

Payflow Link Secure Token not returning token due to Result=4 (and who knows what else?)

Am trying to move from legacy Payflow Link using hosted pages to using their secure token method (still PayFlow Link) using ColdFusion and have hit a wall. I think I I have been thru all the stuff here on Stack, and tried all of it, still no joy - sooo.
I created a form, just simple HTML and it works as expected
<cfscript>
variables.pfl_user="suppressed";
variables.pfl_vendor = "suppressed";
variables.pfl_partner = "PayPal";
variables.pfl_pwd = "suppressed";
variables.pfl_host_addr = "https://payflowlink.paypal.com";
//variables.pfl_gettoken_host_addr = "https://pilot-payflowpro.paypal.com";
variables.pfl_gettoken_host_addr = "https://payflowpro.paypal.com";
</cfscript>
<cfoutput>
<form method="post" action="#variables.pfl_gettoken_host_addr#">
<input type="text" name="USER" value="#variables.pfl_user#" />
<input type="text" name="VENDOR" value="#variables.pfl_vendor#" />
<input type="text" name="PARTNER" value="#variables.pfl_partner#" />
<input type="text" name="PWD" value="#variables.pfl_pwd#" />
<input type="text" name="CREATESECURETOKEN" value="Y" />
<input type="text" name="SECURETOKENID" value="#key#" />
<input type="text" name="TRXTYPE" value="S" />
<input type="text" name="AMT" value="24.95" />
<input type="text" name="CURRENCY" value="USD" />
<input type="submit" />
</form>
</cfoutput>
And this works just fine, gives me just what I am looking for. But...The cfhttp code below just returns my securetokenId and an error code that makes NO sense..
Result Code 4 means that my AMT is incorrectly formatted
RESULT=4&SECURETOKENID=08646BF7E5BC88E8A44015803CCF54&RESPMSG=Invalid amount
<cfhttp method="post" url="#pfl_gettoken_host_addr#" useragent="Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.7 (KHTML, like Gecko) Chrome/5.0.391.0 Safari/533.7" >
<cfhttpparam name="USER" type="formField" value="#variables.pfl_user#">
<cfhttpparam name="VENDOR" type="formField" value="#variables.pfl_vendor#">
<cfhttpparam name="PARTNER" type="formField" value="#variables.pfl_partner#">
<cfhttpparam name="PWD" type="formField" value="#variables.pfl_pwd#">
<cfhttpparam name="CREATESECURETOKEN" type="formField" value="Y">
<cfhttpparam name="SECURETOKENID" type="formField" value="#rStr.newTokenKey#">
<cfhttpparam name="TRXTYPE" type="formField" value="S">
<cfhttpparam name="AMT" type="formField" value="24.95">
<cfhttpparam name="CURRENCY" type="formfield" value="USD">
<cfhttpparam type="header" name="X-VPS-REQUEST-ID" value="#gettickcount()#" >
<cfhttpparam type="header" name="Accept-Encoding" value="gzip, deflate, sdch, x-gzip, compress, x-compress" >
<cfhttpparam type="header" name="X-VPS-CLIENT-TIMEOUT" value="10" >
<cfhttpparam type="header" name="Accept" value="application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5">
<cfhttpparam type="header" name="Accept-Language" value="en-US,en;q=0.8">
<cfhttpparam type="header" name="Accept-Charset" value="ISO-8859-1,utf-8;q=0.7,*;q=0.3">
<cfhttpparam type="header" name="content-type" value="text/name value">
</cfhttp>
Anyone have some ideas? All the Header ideas come from the PayPal Docs and things I have found here on Stack.
I have to do something, I have some screenscraper douche using my PayPal account to test out his/her stolen credit cards..so I have turned PayPal off until I make the change. I have to do this first call server side, via a post to "protect" my credentials
To answer the obvious question up front:
yes, I am generating a new key
yes everything is set correctly (according to PayPal) in my account
yes, I am using the same vars (except for the newly generated SECURETOKENID) for both requests
M
**The Solution is pretty simple; though finding the actual problem was a bit of work. For all of the CFHTTPPARAM type=formfield tags, choose encoded="no"
**
This was a case of !RTFM.
**The Solution is pretty simple; though finding the actual problem was a bit of work, though in hindsight I should have done that right off the bat.
SOLUTION: For all of the CFHTTPPARAM type=formfield tags, choose encoded="no"
To find the problem I posted from a page on my dev server to a catching page on my dev server where I used GetHttpRequestData() to dump what I was sending. Once I saw the encoding I knew what the problem was and from there the fix was simple.

Show message only when there are no messages for other components

I have 3 messages displayed when validating the form, kind of this :
<p:message id="msgCity1" for="city1" styleClass="required" display="text" />
<p:message id="msgCity2" for="city2" styleClass="required" display="text" />
<p:message id="msgCountry" for="msgCountry" styleClass="required" display="text" />
the first(msgCity1) and second(msgCity2) messages are validated on event (keyup)
the last one is validate on server side, I would like to show the last message (msgCountry), if the validation is ok for the first 2 messages, I mean if the message are empty,
For that I would like to use rendered on the last message but I do not how I can get the value of the first 2 message in xhtml
Rather hook on UIInput#isValid() directly than on the presence of a message for the input.
E.g.
<h:inputText id="city1" binding="#{city1}" ... />
<h:inputText id="city2" binding="#{city2}" ... />
...
<p:message for="msgCountry" ... rendered="#{city1.valid and city2.valid}" />

Uploading a file with cfhttp appends a newline (even on binary files)

Update: I've found a workaround. If I submit a dummy form field along with the file, it works. Is this a ColdFusion bug, or is there something in the HTTP spec that says forms must contain at least one non-file form field?
Update 2: I'm convinced this is a ColdFusion cfhttp bug. This is based on Leigh's answer and the fact that I used the code below to submit a form with only the file element using javascript, and it works fine:
<form enctype="multipart/form-data" action="<cfoutput>#CGI.PATH_INFO#</cfoutput>" method="POST" name="theForm">
<input name="theFile" type="file" /><br/>
</form>
submit
I'm running into a problem uploading files from a ColdFusion server to another webserver. It seems that cfhttpparam type="file" is indiscriminately appending a newline (carriage return and line feed) to the end of the file. This is breaking binary files. This does not happen when I manually upload the file via form field. I have tried with and without mimetype parameter, and I've tried lying about mimetype with various binary formats (exe, zip, jpg), but nothing has worked. Is there some parameter I'm missing, or is this a bug in ColdFusion? (I'm running on CF 8.0.1.195765 on WinXP.)
Below is test code I'm using, it just uploads the file to the same directory. The manual upload works, but the server-based upload ends up appending a CRLF to the file.
<cfset MyDir = "C:\test" />
<cfset MyFile = "test.zip" />
<cfif IsDefined("Form.TheFile")>
<cffile action="upload" fileField="theFile" destination="#MyDir#" nameConflict="MakeUnique" />
<cfelse>
<cfhttp url="http://#CGI.SERVER_NAME##CGI.SCRIPT_NAME#" method="POST" throwOnError="Yes">
<cfhttpparam type="file" name="theFile" file="#MyDir#\#MyFile#" />
</cfhttp>
</cfif>
<html><body>
<h2>Manual upload</h2>
<form enctype="multipart/form-data" action="<cfoutput>#CGI.PATH_INFO#</cfoutput>" method="POST">
<input name="theFile" type="file" /><br/>
<input type="submit" value="Submit" />
</form>
</body></html>
or is there something in the HTTP spec
that says forms must contain at least
one non-file form field?
I do not know for certain. But according to these definitions it seems like a POST containing only a file input should be valid. So I suspect the problem may be CFHTTP in ACF.
According to Fiddler the raw content from the cfhttp call in ACF contains an extra new line just before the end boundary (0D 0A in hex view). But under Railo it does not. So I think ACF's cfhttp might be the culprit.
Sample Code:
<cfhttp url="http://127.0.0.1:8888/cfusion/receive.cfm" method="post">
<cfhttpparam name="myFile" type="file" file="c:/test/testFile.zip" mimetype="application/octet-stream" />
</cfhttp>
Results Railo 3.1.2
POST /railo/receive.cfm HTTP/1.1
User-Agent: Railo (CFML Engine)
Host: 127.0.0.1:8888
Content-Length: 382
Content-Type: multipart/form-data; boundary=m_l7PD5xIydR_hQpo8fDxL0Hb7vu_F8DSzwn
--m_l7PD5xIydR_hQpo8fDxL0Hb7vu_F8DSzwn
Content-Disposition: form-data; name="myFile"; filename="testFile.zip"
Content-Type: application/octet-stream; charset=ISO-8859-1
Content-Transfer-Encoding: binary
PK
&�1=�cN'testFile.txtTestingPK
&�1=�cN' testFile.txtPK:1
--m_l7PD5xIydR_hQpo8fDxL0Hb7vu_F8DSzwn--
Results ACF (versions 8 and 9)
POST /cfusion/receive.cfm HTTP/1.1
Host: 127.0.0.1:8888
... other headers removed for brevity ....
Content-type: multipart/form-data; boundary=-----------------------------7d0d117230764
Content-length: 350
-------------------------------7d0d117230764
Content-Disposition: form-data; name="JobFile"; filename="c:\test\testFile.zip"
Content-Type: application/octet-stream
PK
&�1=�cN'testFile.txtTestingPK
&�1=�cN' testFile.txtPK:1
-------------------------------7d0d117230764--
Maybe Railo 3.1.2 and ColdFusion 9 handle this a bit differently, but your code looks a bit incorrect for me.
Your CGI.PATH_INFO is not applicable here.
While browser is smart enough to use path without hostname, CFHTTP feels better with full hostname + script path + script name. Note: cgi.SCRIPT_NAME worked in CF9, Railo required cgi.SERVER_NAME to be prepended, though I feel this more correct in general.
That's why a bit modified version of the code works fine for me. Zip file is uploaded and posted without being corrupted.
Form:
<form enctype="multipart/form-data" action="<cfoutput>#cgi.SCRIPT_NAME#</cfoutput>" method="POST">
<input name="theFile" type="file" /><br/>
<input type="submit" value="Submit" />
</form>
CFHTTP:
<cfhttp url="#cgi.SERVER_NAME##cgi.SCRIPT_NAME#" method="POST" throwOnError="Yes">
<cfhttpparam type="file" name="theFile" file="#MyDir#/#MyFile#" />
</cfhttp>
Hope this helps.
I get the extra line feed and carriage return on file appends too. The problem for me is/was the combination of cfhttp and the cfloop. Once I broke the file creation into 3 parts: Create, cfloop endrow-1, then appending last record.
Seems like a kludgy way to do it, but no extra line feed.