Posting XML With ColdFusion, CFHttp, And CFHttpParam

Posted June 1, 2007 at 4:27 PM

Tags: ColdFusion

I use ColdFusion and CFHttp all the time to grab data from other pages, but it's very rare that I ever post something. In the past, I have fooled around with posting files and cookie parameters, but not much exploration has gone on. But now, I am going to be building an API for a client project that is going to accept XML data strings. I am also going to have a hand in building the applications that make requests to this API.

So, I thought this was a good time to experiment with posting XML with ColdFusion and CFHttp. The first thing I did was look at ColdFusion's CFHttpParam tag because I know that it has a lot of available types. As it turns out, CFHttpParam has a type, XML. When you select this type, ColdFusion identifies the request as having a content-type of text/xml and uses the given XML as the body of the HTTP request. How useful is that?!?

If XML was not available as a CFHttpParam type, it would be ok. Without it, we would have to use one CFHttpParam of type BODY and another to define the mime type as text/xml, but this would accomplish the same thing.

If you are used to dealing with requests all the time (from a browser), but these really only ever deal with the URL and FORM scopes it might not be obvious as to what a request "body" even is or where it can be found. ColdFusion provides the function GetHttpRequestData() which makes the request headers and content available in a nice structure. If you put this code into a new ColdFusion template and run it:

 Launch code in new window » Download code as text file »

  • <cfdump
  • var="#GetHttpRequestData()#"
  • label="Get Http Request Data"
  • />

... you will get something that looks like:


 
 
 

 
ColdFusion Get Http Request Data Structure  
 
 
 

As you can see, all the request data is now easily accessible. We are going to be posting our XML data as the request body which will be available in the Content attribute of the above structure (currently showing an empty string).

Ok, to explore this, I set up a demo with two pages: one page creates a CFHttp request and the other page receives it and returns a confirmation value. Simple stuff, mostly proof of concept. Here is the page that posts the XML data using CFHttp:

 Launch code in new window » Download code as text file »

  • <!--- Get the URL. --->
  • <cfset strURL = (
  • CGI.server_name &
  • GetDirectoryFromPath( CGI.script_name ) &
  • "cfhttp_catch.cfm"
  • ) />
  •  
  •  
  • <!--- Create the XML data to post. --->
  • <cfsavecontent variable="strXML">
  •  
  • <transaction>
  • <type>Debit</type>
  • <cost>19.99</cost>
  • <date>06-01-2007</date>
  • <item>
  • <sku>GGW190034394</sku>
  • <name>Girls Gone Wild Vol. 13</name>
  • </item>
  • </transaction>
  •  
  • </cfsavecontent>
  •  
  •  
  •  
  • <!---
  • Post the XML data to catch page. We are going
  • to post this value as an XML object will actually
  • just post it as an XML body.
  • --->
  • <cfhttp
  • url="#strURL#"
  • method="POST"
  • useragent="#CGI.http_user_agent#"
  • result="objGet">
  •  
  • <!---
  • When posting the xml data, remember to trim
  • the value so that it is valid XML.
  • --->
  • <cfhttpparam
  • type="XML"
  • value="#strXML.Trim()#"
  • />
  •  
  • </cfhttp>
  •  
  •  
  • <!--- Output the return message. --->
  • Message: #objGet.FileContent#

The XML posted by the above page is being caught and processed by this page:

 Launch code in new window » Download code as text file »

  • <!---
  • All data that is posted to this page will now
  • be part of the HTTP Request data structure. Get
  • a reference to this structure.
  • --->
  • <cfset objRequest = GetHttpRequestData() />
  •  
  • <!---
  • Our XML data will be the content of the request.
  • Let's grab it out of the request structure. When
  • we do this, trim the value to help create a
  • valid XML string.
  • --->
  • <cfset strXML = objRequest.Content.Trim() />
  •  
  • <!---
  • At this point, we may or may not have a valid XML
  • string. Before we try to do any parsing, let's
  • validate it.
  • --->
  • <cfif IsXml( strXML )>
  •  
  • <!---
  • Now that we know the request was of valid
  • format, we can parse the XML document.
  • --->
  • <cfset xmlData = XmlParse( strXML ) />
  •  
  • <!---
  • For this demo, we are going to validate the
  • request ONLY for Credit / Debit.
  • --->
  • <cfset xmlType = XmlSearch(
  • xmlData,
  • "/transaction/type"
  • ) />
  •  
  • <!---
  • Check to see if we found a Type node as a child
  • to the transaction root node.
  • --->
  • <cfif ArrayLen( xmlType )>
  •  
  • <!---
  • We found the type - this request has been
  • validated. Now, we just need to return a
  • confirmation message.
  • --->
  • <cfset strResponse = ("#xmlType[ 1 ].XmlText# approved") />
  •  
  • <cfelse>
  •  
  • <!--- We did not find a valid node. --->
  • <cfset strResponse = "ERROR2: Missing type node" />
  •  
  • </cfif>
  •  
  • <cfelse>
  •  
  • <!---
  • The passed in data was not a valid XML string.
  • Store our error into our response message.
  • --->
  • <cfset strResponse = "ERROR1: Invalid request (Bad XML)" />
  •  
  • </cfif>
  •  
  •  
  • <!---
  • ASSERT: At this point, no matter what happend (if the
  • request was valid or invalid) we will have a message
  • in our response string.
  • --->
  •  
  •  
  • <!--- Return response string. --->
  • <cfcontent
  • type="text/plain"
  • variable="#ToBinary( ToBase64( strResponse ))#"
  • />

For the purposes of this demo, we are doing very little validation on the XML data as this is not a true API. If we run the above pages, we get the following return value:

Message: Debit approved

The process worked quite nicely. Now, posting XML data is related to a SOAP request. SOAP, from what I can understand, is standard for formatting XML requests. If you go that route, ColdFusion provides many SOAP-related convenience functions that are worth looking into.

Download Code Snippet ZIP File

Comments (10)  |  Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page




Adobe ColdFusion 8.0.1 Update - Helping Programmers To Be Signifanctly Less Girlie - Download ColdFusion 8 Update 8.0.1 Now.

Reader Comments

Hi, I have found the information in your tutorial great for an integration I am doing with the Chase paymentech orbital gateway, the only problem I have is that I am not able to send the correct MIME headers (which are mandatory) along with the XML, I have tried sending them using a CFHTTPparam of type Header, also of type Mimetype, but I am getting different errors, any information that can point me in the right direction would be greatly appreciated.

This is the code I am using:

----------------------

<cfsavecontent variable="XMLPacket">
<?xml version="1.0" encoding="UTF-8"?>
<Request>
<NewOrder>
<IndustryType>EC</IndustryType>
<MessageType>AV</MessageType>
<BIN>000001</BIN>
<MerchantID>1521115142</MerchantID>
<TerminalID>001</TerminalID>
</NewOrder>
</Request>
</cfsavecontent>

<cfhttp
url="orbital1.paymentech.net/authorize"
port="443"
method ="POST"
throwonerror="yes">
<cfhttpparam type="XML" value="#XMLpacket#">
</cfhttp>

--------------------------

And this is are Mime headers I need to send:

MIME-Version: 1.0
Content-type: application/PTI42
Content-length: #len(xmlpacket)#
Content-transfer-encoding: text
Request-number: 1
Document-type: Request
Merchant-id: 1521115124
Interface-Version: Test 1.4

Sincerely

Luis Rueda

Posted by Luis Rueda on Jul 16, 2007 at 12:03 PM


@Luis,

Mime information is only for the body of the request. The rest of those should just be standard HEADER values. Have you tried send them with CFHttpParam using that type?

Example:

<cfhttpparam
type="header"
name="Request-number"
value="1"
/>

Let me know if that helps at all?

Posted by Ben Nadel on Jul 16, 2007 at 5:57 PM


very useful breakdown. One suggestion. Please always include the VERSION of ColdFusion you are using. I'm guessing this is MX 7 or above. Unfortunately I'm stuck implementing the Chase gateway with a CF version 5 server. I may have to tell the client to switch hosts...

Posted by Ken on Sep 30, 2007 at 5:19 PM


@Ken,

Yeah, I am on ColdFusion MX 7.

Posted by Ben Nadel on Oct 1, 2007 at 7:28 AM


Hi Ben thank you for your reply, I changed the code but I am receiving the same response which is a "20400 invalid request" error message (I guess I am not sending correctly the header information), this is what I tried:

<cfhttp
url="orbitalvar1.paymentech.net/authorize"
port="443"
method ="POST"
throwonerror="yes"
charset="utf-8">
<cfhttpparam type="HEADER" name="POST /AUTHORIZE HTTP/1.0" value=""/>
<cfhttpparam type="HEADER" name="MIME-Version" value="1.0"/>
<cfhttpparam type="HEADER" name="Content-type" value="application/PTI41"/>
<cfhttpparam type="HEADER" name="Content-length" value="#len(xmlentry)#"/>
<cfhttpparam type="HEADER" name="Content-transfer-encoding" value="text"/>
<cfhttpparam type="HEADER" name="Request-number" value="1"/>
<cfhttpparam type="HEADER" name="Document-type" value="Request"/>
<cfhttpparam type="HEADER" name="Merchant-id" value="173361"/>
<cfhttpparam type="Body" value="#XMLentry#"/>
</cfhttp>

Appreciating your attention

Luis

Posted by Luis Rueda on Oct 8, 2007 at 5:00 PM


@Luis,

I have never seen this error before. After some brief Googling, it looks like it has to do with character encodings. Take a look at this page; it looks like it would help you out:

https://ebay.custhelp.com/cgi-bin/ebay.cfg/php/enduser/std_adp.php?p_faqid=280

Looks like you might have to add CharSet to your encoding tag.

Posted by Ben Nadel on Oct 9, 2007 at 7:41 AM


@ Luis

I am also trying to setup a transaction attempt with Chase Paymantech. They sure don't make things easy! I would try switching your cfhttp call to the following:

<cfhttp
url="https://orbitalvar1.paymentech.net/authorize"
port="443"
method="POST"
useragent="#CGI.http_user_agent#"
>

This is working for me so far, in that I'm not getting the error that you reported.

Posted by Ian on Oct 18, 2007 at 10:35 AM


I'm also stuck with Coldfusion 5 and it appears you can't manipulate header information with CFHTTPPARAM. That is according to this post on the PayPal developer community site. http://www.pdncommunity.com/pdn/board/message?board.id=payflow&thread.id=938

If anyone knows a work around please share.

Posted by warren on Nov 27, 2007 at 1:23 PM


Hi folks, after many unsuccessful attempts trying to integrate the Orbital gateway with Coldfusion MX using XML, we gave a try to a COM integration using Paymentech's SDK which was really easy, so no more cfhttpparam headaches from this side.

Kind Regards

Luis

Posted by Luis Rueda on Nov 27, 2007 at 5:21 PM


seems to work just fine with paypal reporting api. thanks for the tip

Posted by sam on May 9, 2008 at 4:19 PM


Post Comment  |  Ask Ben


Home   |   Web Log   |   ColdFusion   |   Projects   |   Resume   |   Job Form   |   Search   |   Contact
Epicenter Consulting - Custom Software Solutions for Business Evolution HostMySite.com - The Leader In ColdFusion Hosting