UPS Tracking with XML and ColdFusion CFC
04/06/2006 10:45:04 PM
ColdFusion CFCs or ColdFusion components are very usefule when it comes to coding. It goes beyond Custom Tags in their functionality. I put together this CFC to perform UPS tracking and return the data into a structure that can be referenced to display the tracking information for a package. I borrowed most of the code and adapted for my own use in an eCommerce application that I have developed.
First we declare the opening tags for the component:
<cfcomponent> <cffunction name="Tracking" access="public" returntype="struct"> <cfargument name="TrackingNumber" type="string" required="yes">
The first thing within the CFC I do is allocate a struct called TrackingInfo to store variable for the return to the calling procedure:
<cfset TrackingInfo = structnew()>
Next we build the XML request to UPS with the cfsavecontent tag:
<cfsavecontent variable="XMLToSend"> <?xml version="1.0" ?> <AccessRequest xml:lang="en-US"> <AccessLicenseNumber>youraccesslicense</AccessLicenseNumber> <UserId>youruserid</UserId> <Password>yourpassword</Password> </AccessRequest> <?xml version="1.0" ?> <TrackRequest xml:lang="en-US"> <Request> <TransactionReference> <CustomerContext>Example 3</CustomerContext> <XpciVersion>1.0001</XpciVersion> </TransactionReference> <RequestAction>Track</RequestAction> <RequestOption></RequestOption> </Request> <TrackingNumber><cfoutput>#TrackingNumber#</cfoutput></TrackingNumber> </TrackRequest> </cfsavecontent>
The varable TrackingNumber is the UPS Tracking Number that you pass in. This chunk of code is saved in the variable XMLToSend. Next thing is to pass the code to UPS using the cfhttp tag to pass the information:
<cfhttp url="https://wwwcie.ups.com/ups.app/xml/Track" method="post"> <cfhttpparam name="Content-Type" type="HEADER" value="content-type: text/xml; charset='UTF-8';"> <cfhttpparam type="body" value="#XMLToSend#"> </cfhttp> <cfset response = cfhttp.fileContent>
The response is saved in the variable response for further processing. We use the XMLParse function tag to create a parseable XML string. ColdFusion has many powerful XML parsing functions built in and you still need to know the structure of the returning XML to really get at the data you want.
<cfset StartingPosition = Find('<TrackResponse>',response)> <cfset XMLResponse = XMLParse(Mid(response,StartingPosition,(Len(response)+1)-StartingPosition))> <cfset trackXML = XMLResponse> <cfset TrackingInfo.ResponseStatusCode = xmlResponse.TrackResponse.Response.ResponseStatusCode.XMLText>
Here we've retrieved the ResponseStatusCode and stored it into the TrackingInfo struct. A ResponseStatusCode of 1 means that we had a successful communication and that tracking data is available. This next chuck of code saves the appropriate return variables in the TrackingInfo struct. If we did not receive a 1 in ResponseStatusCode, we just dummy up the remaining variables in the struct.
<cfif TrackingInfo.ResponseStatusCode eq "1"> <cfset TrackingInfo.rcvStatusCode = xmlResponse.TrackResponse.Shipment.Package.Activity.Status.StatusType.Code.XMLText> <cfset TrackingInfo.rcvStatus = xmlResponse.TrackResponse.Shipment.Package.Activity.Status.StatusType.Description.XMLText> <cfset rcvDate = xmlResponse.TrackResponse.Shipment.Package.Activity.Date.XMLText> <cfset rcvTime = xmlResponse.TrackResponse.Shipment.Package.Activity.Time.XMLText> <cfif isdefined("xmlResponse.TrackResponse.Shipment.Package.Activity.ActivityLocation.SignedForByName.XMLText")> <cfset TrackingInfo.rcvSigner = xmlResponse.TrackResponse.Shipment.Package.Activity.ActivityLocation.SignedForByName.XMLText> <cfelse> <cfset TrackingInfo.rcvSigner = ""> </cfif> <cfset TrackingInfo.LocationCity = xmlResponse.TrackResponse.Shipment.Package.Activity.ActivityLocation.Address.City.XMLText> <cfset TrackingInfo.LocationState = xmlResponse.TrackResponse.Shipment.Package.Activity.ActivityLocation.Address.StateProvinceCode.XMLText> <cfset TrackingInfo.LocationCountry = xmlResponse.TrackResponse.Shipment.Package.Activity.ActivityLocation.Address.CountryCode.XMLText> <cfset TrackingInfo.shipService = xmlResponse.TrackResponse.Shipment.Service.Description.XMLText> <cfset TrackingInfo.shipWeight = xmlResponse.TrackResponse.Shipment.Package.PackageWeight.Weight.XMLText> <cfset TrackingInfo.shipMeasure = xmlResponse.TrackResponse.Shipment.Package.PackageWeight.UnitOfMeasurement.Code.XmlText> <cfset tempPickup = xmlResponse.TrackResponse.Shipment.PickupDate.XMLText> <cfset TrackingInfo.rcvDate = Mid(rcvDate,5,2) & "/" & Mid(rcvDate,7,2) & "/" & mid(rcvDate,1,4)> <cfset TrackingInfo.rcvTime = Mid(rcvTime,1,2) & ":" & Mid(rcvTime,3,2) & ":" & mid(rcvTime,6,2)> <cfset TrackingInfo.shipPickup = CreateDate(Left(tempPickup,4),Mid(tempPickup,5,2),Right(tempPickup,2))> <cfelse> <cfset TrackingInfo.rcvStatusCode = ""> <cfset TrackingInfo.rcvStatus = "DATA UNAVAILABLE"> <cfset rcvDate = ""> <cfset rcvTime = ""> <cfset TrackingInfo.rcvSigner = ""> <cfset TrackingInfo.LocationCity = ""> <cfset TrackingInfo.LocationState = ""> <cfset TrackingInfo.LocationCountry = ""> <cfset TrackingInfo.shipService = ""> <cfset TrackingInfo.shipWeight = ""> <cfset TrackingInfo.shipMeasure = ""> <cfset TrackingInfo.rcvDate = ""> <cfset TrackingInfo.rcvTime = ""> <cfset TrackingInfo.shipPickup = ""> </cfif>
Finally the return the TrackingInfo struct with the following command:
<cfreturn TrackingInfo>
We need to close up the function and the component.
</cffunction> </cfcomponent>
This code needs to be saved as UPS.cfc and called from the main program as follows:
<cfinvoke component="UPS" method="Tracking" returnvariable="TrackingInfo"> <cfinvokeargument name="TrackingNumber" value="#TrackingNumber#"> </cfinvoke>
<cfoutput> #TrackingInfo.LocationCity# <br> #TrackingInfo.LocationState# <br> #TrackingInfo.LocationCountry <br> #TrackingInfo.shipService <br> #TrackingInfo.shipWeight <br> #TrackingInfo.shipMeasure# <br> #TrackingInfo.rcvDate#<br> #TrackingInfo.rcvTime# <br> #TrackingInfo.shipPickup# </cfoutput>
This code has been real helpful and I hope you can use it in your programming adventures.
Comments (7)
| Permalink
Hello,
I have tried to implement this and the code is not working correctly.
I'm getting error:
Element TRACKRESPONSE.SHIPMENT.PACKAGE.ACTIVITY.ACTIVITYLOCATION.ADDRESS.CITY.XMLTEXT is undefined in XMLRESPONSE.
Any ideas?
I tried to use the code EXACTLY as you have it below except using our own access and license key which we use in the UPS shipping calc XML that works well , but for some reason we cannot get this to work. When I put in the test tracking number etc and run it, all I get is a blamk screen, even with debugging switched on
Posted By Mervyn / Posted At 10/18/2006 01:00 PM
As author of the above code I have revised the above code to include the actual CFC wrappers and invoke code. These are critial elements to getting this to work. Also, you must have the access code and login information from UPS.
Thanks for your comments.
This works great now with Tracking Numbers however when I replace it with the ReferenceNumber and change the CFC accordingly by inserting :
#RefNumber#
and supplying the reference number it does not work BUT I have an HTML form that does work with the reference number so I know that it is valid
it does not appear to work
Posted By Mervyn / Posted At 10/27/2006 02:45 PM
This works great now with Tracking Numbers however when I replace it with the ReferenceNumber and change the CFC accordingly by inserting
There is also the CFGRIDUPDATE tag, however, if you have multiple field keys, this probably will not work.
very very good
Posted By acirci / Posted At 03/01/2008 06:13 AM
This works great now with Tracking Numbers however when I replace it with the ReferenceNumber and change the CFC accordingly by inserting : #RefNumber# and supplying the reference number it does not work BUT I have an HTML form that does work with the reference number so I know that it is valid it does not appear to work
Posted By teknoloji / Posted At 03/01/2008 06:14 AM
|