Showing posts with label Web Services. Show all posts
Showing posts with label Web Services. Show all posts

Friday, December 4, 2009

Fedex Web Services + createObject("webservice") == Migraine

A very long time ago, I wrote an entry on my novice struggles using the Fedex web services with createObject(). Though the entry shows I still had a lot to learn about web services, I still get occasional questions about it. In particular, about working with the Fedex web services and createObject(). So I will offer this advice to anyone looking to do the same - don't.

While ColdFusion definitely simplifies the process of working with web services, it is also not the best tool for every web service. Especially the more complex ones. If you have ever tried using the FedEx web services with createObject("webservice"), you know how painful it can be. They are extremely complex and deeply nested. So unless you miraculously hit on the right code the first time around, you are likely to waste a LOT of time trying to troubleshoot cryptic Axis error messages .. and the time you spend will not be fun.

So my recommendation is to try using SOAP + CFHTTP instead. The Fedex WSDL developer files include working SOAP samples. They will get you up and running much faster than trying to translate the java examples into CF code. An old entry on Russ Michaels blog has some good tips on working with SOAP. There is also a current project using the SOAP approach with the Fedex Rates Web Service, under the project name CFFedexRates. You could easily use it as a base for some of the other web services.

Take my word for it, you will be glad you did.

Update December 9, 2009:
For a version of CFFedexRates that is compatible with the Rate Service v7, see issue #2 http://code.google.com/p/cffedexrates/issues/detail?id=2


Update January 21, 2010:
The featured downloads section was updated to include a version compatible with Rate Service v7.

Update May 4, 2010:
For a version of CFFedexRates that is compatible with the Rate Service v8, see issue #4 http://code.google.com/p/cffedexrates/issues/detail?id=4

...Read More

Saturday, December 1, 2007

How the heck do you use the FedEx Rate web service?


UPDATE The original code sample uses version 2 of the WSDL.
  • September 24, 2008: Updated to include a rough example for WSDL version 4

  • October 19, 2009: Updated to include a rough example for WSDL version 7


  • The code samples work as of those dates. But no guarantees Fedex will not make further changes. Also, given the complexity of this webservice, consider looking into the old fashioned SOAP/CFHTTP method. See CFFedexRates for a base example. Be sure to check the open Issues List as well. There may be newer versions available (as attachments).


    I admit it. I do not get web services. Creating the web service equivalent of a "Hello World" project on my computer was one thing. Trying to figure out how to consume an external web service is a completely different story.

    Next stop: Web Service Hell


    So I took the plunge and decided to try and figure out how to consume the FedEx Rate Web Service. On what feels like day 212 I finally got it working, somewhat ;)

    Three things you will need for your journey..


    1. My first step was to register for a developer account

    2. Armed with my new account information, I downloaded the "Rate Web Service" WDSL. Looked at it and thought "Gee ...that is great. Now what do I do with it?"

    3. So I googled a bit and figured out I could put the wdsl file in a web folder and then try and call it as a webservice from a test .cfm page. On my computer I placed it in this directory

    [directory] c:\cfusionmx7\wwwroot\fedex\RateService_v2.wsdl
    [url path] http://127.0.0.1:8501/fedex/RateService_v2.wsdl
    


    Abandon hope, all ye who enter here


    Before getting started, I checked the code samples section. There were no ColdFusion samples .. of course. So I downloaded the java code samples instead. Let me just say.. thank god. If not for the java samples I would still be struggling with my favorite error message ..and muttering it in my sleep.


    Web service operation "getRate" with parameters {PAYMENT={{PAYMENTTYPE={SENDER}}}, .... could not be found.


    Paradiso


    After much trial and error my test page is finally working. I ended up using createObject() to create the webservice, because of errors when using cfinvoke. I suspect it might be due to the optional parameters. Anyway, the code is rough, but its a start. Sorry in advance for the terrible code formatting. Figuring out the blog formatting is next on my list (..sure, sure ;)

    As always comments/suggestions/corrections are welcome.

    WSDL Version 2 Code
    <!--- setting used later on in the code to set shipment details --->
    <cfset PassRateRequestPackageSummary = true />
    
    <!--- java objects used for paramters later on in the code --->
    <cfset objPosInteger = createObject("java", "org.apache.axis.types.PositiveInteger") />
    <cfset objNonNegInteger = createObject("java", "org.apache.axis.types.NonNegativeInteger") />
    
    <!---
    Populate a structure with all rate request settings
    --->
    <cfset data = structNew() />
    <cfset data.ClientDetail.AccountNumber="My Test Account" />
    <cfset data.ClientDetail.MeterNumber="My Test Meter" />
    <cfset data.TransactionDetail.CustomerTransactionId = "Rate Request v2" />
    <cfset data.WebAuthenticationDetail.UserCredential.key ="My Developer Test Key" />
    <cfset data.WebAuthenticationDetail.UserCredential.password ="My Developer Test Password" />
    
    <cfset data.Version.serviceId = "crs" />
    <cfset data.Version.major = "2" />
    <cfset data.Version.intermediate =  "0" />
    <cfset data.Version.minor =  "0" />
    <cfset data.Origin.CountryCode= "US" />
    <!--- web service complained if this was not an array --->
    <cfset streetArray = arrayNew(1) />
    <cfset arrayAppend(streetArray, "Address Line 1") />
    <cfset data.Origin.StreetLines = streetArray />
    <cfset data.Origin.City = "City Name" />
    <cfset data.Origin.StateOrProvinceCode = "TN" />
    <cfset data.Origin.PostalCode = "38115" />
    <cfset data.Origin.UrbanizationCode = "" />
    <cfset data.Origin.Residential = "false" />
    
    <cfset data.Destination = structNew() />
    <cfset data.Destination.CountryCode= "US" />
    <!--- web service complained if this was not an array --->
    <cfset streetArray = arrayNew(1) />
    <cfset arrayAppend(streetArray, "Address Line 1") />
    <cfset data.Destination.StreetLines= streetArray />
    <cfset data.Destination.City= "City Name" />
    <cfset data.Destination.StateOrProvinceCode= "QC" />
    <cfset data.Destination.PostalCode= "H1E1A1" />
    <cfset data.Destination.CountryCode= "CA" />
    
    <cfset data.DropoffType = "REGULAR_PICKUP" />
    <cfset data.ServiceType = "INTERNATIONAL_PRIORITY" />
    <cfset data.PackagingType = "YOUR_PACKAGING" />
    
    <cfset data.Payment.PaymentType = "SENDER" />
    <cfset data.ShipDate = "2007-11-30" />
    <cfset RateRequestType = structNew() />
    <cfset RateRequestType.VALUE = "ACCOUNT" />
    <!--- web service complained if this was not an array --->
    <cfset rateRequestArray = ArrayNew(1) />
    <cfset arrayAppend(rateRequestArray, "ACCOUNT") />
    <cfset data.RateRequestTypes = rateRequestArray />
    
    
    <!--- Not passing one of these choices will result in "Schema Validation Failure", as one of these objects is required. --->
    <cfif PassRateRequestPackageSummary >
    <cfset data.RateRequestPackageSummary.TotalInsuredValue.Amount = "100">
    <cfset data.RateRequestPackageSummary.TotalInsuredValue.Currency = "USD">
    <cfset data.RateRequestPackageSummary.TotalWeight.Value = "20.0">
    <cfset data.RateRequestPackageSummary.TotalWeight.Units = "LB">
    <!--- could not get this to work without using java objects --->
    <cfset data.RateRequestPackageSummary.PieceCount = objPosInteger.init(1) />
    <!--- web service complained if this was not an array --->
    <cfset specialServiceArray = ArrayNew(1)>
    <cfset arrayAppend(specialServiceArray, "APPOINTMENT_DELIVERY")>
    <cfset data.RateRequestPackageSummary.SpecialServicesRequested.SpecialServiceTypes = specialServiceArray>
    <cfelse>
    <cfset data.PackageCount = objNonNegInteger.init(1) >
    <!--- web service complained if this was not an array --->
    <cfset packagesArray = ArrayNew(1)>
    <cfset newPackage = structNew()>
    <cfset newPackage.Weight.Value = "10.00">
    <cfset newPackage.Weight.Units = "LB">
    <cfset newPackage.InsuredValue.Amount = "10.00">
    <cfset newPackage.InsuredValue.Currency = "USD">
    <!--- could not get this to work without using java objects --->
    <cfset newPackage.Dimensions.Length = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Width = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Height = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Units = "IN">
    <cfset arrayAppend(packagesArray, newPackage)>
    <cfset data.Packages = packagesArray>
    </cfif>
    
    <!---
    Invoke the webservice
    
    Notes, Using cfinvoke did not work. I think
    it may be related to the optional parameters
    --->
    <cfscript>
    ws = createObject("webservice", "http://127.0.0.1:8501/FedEx/RateService_v2.wsdl");
    rateReply = ws.getRate(data);
    </cfscript>
    
    <!---
    Process the response
    --->
    <cfprocessingdirective suppressWhiteSpace="true" />
    <cfoutput>
    <h1>Response: #rateReply.getHighestSeverity().toString()#</h1>
    
    <cfif rateReply.getHighestSeverity().toString() is "SUCCESS">
    <!--- This is weight, and charge per package --->
    <cfset shipment = rateReply.getRatedShipmentDetails() />
    <cfloop    from="1" to="#arrayLen(shipment)#" index="i">
    <cfset shipmentDetails =  shipment[i].getShipmentRateDetail()>
    <cfset packages = shipment[i].getRatedPackages() />
    <cfloop from="1" to="#arrayLen(packages)#" index="j">
    <cfset packageDetail = packages[j].getPackageRateDetail() />
    <cfset surcharge = packageDetail.getSurcharges() />
    
    <!--- display package info --->
    Package: #i#<br />
    Billing weight: #packageDetail.getBillingWeight().getValue()#
    #packageDetail.getBillingWeight().getUnits().toString()#<br />
    Base charge:     #packageDetail.getBaseCharge().getAmount()#
    #packageDetail.getBaseCharge().getCurrency()#<br />
    
    <!--- display surcharges --->
    <cfloop from="1" to="#ArrayLen(surcharge)#" index="k">
    #surcharge[k].getSurchargeType().toString()#  <b>surcharge</b>
    #surcharge[k].getAmount().getAmount()#
    #surcharge[k].getAmount().getCurrency()#<br />
    </cfloop>
    <hr>
    
    <!--- display net charges --->
    Net charge:     #packageDetail.getNetCharge().getAmount()#
    #packageDetail.getNetCharge().getCurrency()#
    <hr>
    
    <!--- display totals. these values may be null ? --->
    <cfset TotalBillingWeight = shipmentDetails.getTotalBillingWeight() />
    <cfset TotalSurcharges = shipmentDetails.getTotalSurcharges() />
    <cfset TotalNetCharge = shipmentDetails.getTotalNetCharge() />
    <cfif IsDefined("totalBillingWeight")>
    Total billing weight:     #TotalBillingWeight.getValue()#
    #TotalBillingWeight.getUnits().toString()#<br />
    </cfif>
    <cfif IsDefined("TotalSurcharges")>
    Total surcharge: #TotalSurcharges.getAmount()# #TotalSurcharges.getCurrency()#<br />
    </cfif>
    <cfif IsDefined("TotalNetCharge")>
    Total net charge: #TotalNetCharge.getAmount()# #TotalNetCharge.getCurrency()#<br />
    </cfif>
    <hr>
    </cfloop>
    </cfloop>
    <cfelse>
    <cfset Notifications  = rateReply.getNotifications() />
    RateReply Notifications:  #Notifications[1].getMessage()#
    </cfif>
    </cfoutput>
    </cfprocessingdirective>
    


    WSDL Version 4 Code (Rough)
    <!--- java objects used for paramters later on in the code --->
    <cfset objPosInteger = createObject("java", "org.apache.axis.types.PositiveInteger") />
    <cfset objNonNegInteger = createObject("java", "org.apache.axis.types.NonNegativeInteger") />
    
    <!---
    Populate a structure with all rate request settings
    --->
    <cfset data = structNew() />
    
    <!---- set to true to get the rates for different service types --->
    <cfset getAllRatesFlag = false>
    
    <!--- credential information --->
    <cfset data.ClientDetail.AccountNumber = "My Test Account" />
    <cfset data.ClientDetail.MeterNumber = "My Test Meter" />
    <cfset data.TransactionDetail.CustomerTransactionId = "java sample - Rate Request" />
    <cfset data.WebAuthenticationDetail.UserCredential.key ="My Developer Test Key" />
    <cfset data.WebAuthenticationDetail.UserCredential.password ="My Developer Test Password" />
    
    <!--- webservice version --->
    <cfset data.Version.serviceId = "crs" />
    <cfset data.Version.major = "4" />
    <cfset data.Version.intermediate =  "0" />
    <cfset data.Version.minor =  "0" />
    
    <!--- shipment characteristics --->
    <cfset data.requestedShipment.DropoffType = "REGULAR_PICKUP" />
    <cfset data.requestedShipment.ShipTimestamp = now()>
    <cfif NOT getAllRatesFlag>
    <cfset data.requestedShipment.ServiceType = "INTERNATIONAL_PRIORITY">
    <cfset data.requestedShipment.PackagingType = "YOUR_PACKAGING">
    </cfif>
    
    <!--- shipper information --->
    <cfset streetArray = arrayNew(1) />
    <cfset arrayAppend(streetArray, "Address Line 1") />
    <cfset shipper.address.StreetLines = streetArray />
    <cfset shipper.address.City = "City Name" />
    <cfset shipper.address.StateOrProvinceCode = "TN" />
    <cfset shipper.address.PostalCode = "38115" />
    <cfset shipper.address.CountryCode = "US" />
    <cfset data.requestedShipment.shipper = shipper>
    
    <!--- receiver information --->
    <cfset streetArray = arrayNew(1) />
    <cfset arrayAppend(streetArray, "Address Line 1") />
    <cfset recipient.address.StreetLines= streetArray />
    <cfset recipient.address.City= "City Name" />
    <cfset recipient.address.StateOrProvinceCode= "QC" />
    <cfset recipient.address.PostalCode= "H1E1A1" />
    <cfset recipient.address.CountryCode= "CA" />
    <cfset data.requestedShipment.recipient = recipient>
    
    
    <cfset Payment.PaymentType = "SENDER">
    <cfset data.requestedShipment.shippingChargesPayment = Payment>
    
    <!--- package information --->
    <cfset packagesArray = ArrayNew(1)>
    <cfset newPackage = structNew()>
    <cfset newPackage.Weight.Value = "15.00">
    <cfset newPackage.Weight.Units = "LB">
    <cfset newPackage.InsuredValue.Amount = "10.00">
    <cfset newPackage.InsuredValue.Currency = "USD">
    
    <!--- package dimensions --->
    <!--- could not get this to work without using java objects --->
    <cfset newPackage.Dimensions.Length = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Width = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Height = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Units = "IN">
    <cfset arrayAppend(packagesArray, newPackage)>
    
    <cfset data.requestedShipment.RequestedPackages = packagesArray>
    <cfset data.requestedShipment.packageCount = objNonNegInteger.init("1")>
    <cfset data.requestedShipment.packageDetail = "INDIVIDUAL_PACKAGES">
    <cfset RateRequestTypeArray = arrayNew(1)>
    <cfset arrayAppend(RateRequestTypeArray, "ACCOUNT")>
    <cfset data.requestedShipment.RateRequestTypes = RateRequestTypeArray>
    
    <!---
    Invoke the webservice
    
    Notes, Using cfinvoke did not work. I think
    it may be related to the optional parameters
    --->
    <cfscript>
    ws = createObject("webservice", "http://127.0.0.1:8501/FedEx/RateService_v4.wsdl");
    rateReply = ws.getRates(data);
    </cfscript>
    
    <!---
    Process the response
    --->
    <cfoutput>
    <h1>Response: Highest Severity = #rateReply.getHighestSeverity().toString()#</h1>
    <cfset notifications = getNotifications(rateReply.getNotifications())>
    <cfdump var="#notifications#" label="Notifications">
    
    <cfif isResponseOK(rateReply.getHighestSeverity().toString())>
    <cfset rrds = rateReply.getRateReplyDetails() />
    
    <cfloop from="1" to="#arrayLen(rrds)#" index="i">
    <cfset rrd =  rrds[i]>
    
    Service type = #rrd.getServiceType()#<br>
    Packaging type = #rrd.getPackagingType()#<br>
    
    <cfset rsds = rrd.getRatedShipmentDetails()>
    <cfloop from="1" to="#arrayLen(rsds)#" index="j">
    <cfset rsd = rsds[j] />
    <cfset srd = rsd.getShipmentRateDetail() />
    
    RatedShipmentDetail #j#<br>
    <!--- using functions because these values may be null --->
    Rate type = #getValue( srd.getRateType() )#<br>
    Total Billing weight = #getWeightValue( srd.getTotalBillingWeight() )# <br>
    Total surcharges = #getMoneyValue( srd.getTotalSurcharges() )# <br>
    Total net charge #getMoneyValue( srd.getTotalNetCharge() )#<br>
    RatedPackageDetails:<hr>
    
    <cfset rpds = rsd.getRatedPackages()>
    <cfif not IsDefined("rpds")>
    <cfset rpds = arrayNew(1)>
    </cfif>
    
    <cfloop from="1" to="#arrayLen(rpds)#" index="k">
    RatedPackageDetail #k#<br>
    <cfset rpd = rpds[k]>
    <cfset prd = rpd.getPackageRateDetail()>
    <cfif IsDefined("prd")>
    Billing weight = #getWeightValue( prd.getBillingWeight() )# <br>
    Base charge = #getMoneyValue( prd.getBaseCharge() )# <br>
    <cfset surcharges = prd.getSurcharges()>
    <cfif not IsDefined("surcharges")>
    <cfset surcharges = arrayNew(1)>
    </cfif> 
    <cfloop from="1" to="#arrayLen(surcharges)#" index=",">
    #surcharge.getDescription()# surcharge = #getMoneyValue( surcharge.getAmount() )#<br>
    </cfloop>
    </cfif>
    </cfloop>
    </cfloop>
    </cfloop>
    </cfif>
    </cfoutput>
    
    <cffunction name="getMoneyValue" returntype="string">
    <cfargument name="obj" type="any" required="false">
    <cfif structKeyExists(arguments, "obj")>
    <cfreturn arguments.obj.getAmount().toString() &" "& arguments.obj.getCurrency().toString() />
    </cfif>
    
    <cfreturn "" />
    </cffunction>
    
    <cffunction name="getWeightValue" returntype="string">
    <cfargument name="obj" type="any" required="false">
    <cfif structKeyExists(arguments, "obj")>
    <cfreturn arguments.obj.getValue().toString() &" "& arguments.obj.getUnits().toString() />
    </cfif>
    
    <cfreturn "" />
    </cffunction>
    
    <cffunction name="getValue" returntype="string">
    <cfargument name="obj" type="any" required="false">
    <cfargument name="defaultValue" type="string" required="false" default="">
    <cfif structKeyExists(arguments, "obj")>
    <cfreturn arguments.obj.toString()/>
    <cfelse>
    <cfreturn arguments.defaultValue/>
    </cfif>
    </cffunction>
    
    <cffunction name="getNotifications" returntype="array" hint="Converts the notifications object into an array of structures">
    <cfargument name="notifications" type="array" required="false">
    
    <cfset var Local = structNew()>
    <cfset Local.results = arrayNew(1)>
    
    <cfif structKeyExists(arguments, "notifications") and arrayLen(arguments.notifications)>
    <cfloop from="1" to="#arrayLen(arguments.notifications)#" index="Local.x">
    <cfset Local.n = arguments.notifications[Local.x]>
    <cfif structKeyExists(Local, "n")>
    <cfset Local.ns = Local.n.getSeverity()>
    
    <cfset Local.note = structNew()>
    <cfset Local.note.severity = "">
    <cfif NOT structKeyExists(Local, "ns")>
    <cfset Local.severity = Local.ns.getValue()>
    </cfif>
    <cfset Local.note.code = Local.n.getCode()>
    <cfset Local.note.message = Local.n.getMessage()>
    <cfset Local.note.source = Local.n.getSource()>
    <cfset arrayAppend( Local.results, Local.note) >
    </cfif>
    </cfloop>
    </cfif>
    <cfreturn Local.results>
    </cffunction>
    
    <cffunction name="isResponseOK" returntype="boolean" hint="Returns true if the severity type is WARNIGN,NOTE or SUCCESS">
    <cfargument name="notificationSeverityType" required="false">
    <cfset var isOK = false>
    <cfif structKeyExists(arguments, "notificationSeverityType")>
    <cfswitch expression="#arguments.notificationSeverityType#">
    <cfcase value="WARNING,NOTE,SUCCESS">
    <cfset isOK = true>
    </cfcase>
    <cfdefaultcase>
    <cfset isOK = false>
    </cfdefaultcase>
    </cfswitch>
    </cfif>
    
    <cfreturn isOK>
    </cffunction>
    


    WSDL Version 7 Code (Rough)
    <!--- java objects used for paramters later on in the code --->
    <cfset objPosInteger = createObject("java", "org.apache.axis.types.PositiveInteger") />
    <cfset objNonNegInteger = createObject("java", "org.apache.axis.types.NonNegativeInteger") />
    
    <!---
    Populate a structure with all rate request settings
    --->
    <cfset data = structNew() />
    
    <!---- set to true to get the rates for different service types --->
    <cfset getAllRatesFlag = false>
    
    <!--- credential information --->
    <cfset data.ClientDetail.AccountNumber= "My Test Account" />
    <cfset data.ClientDetail.MeterNumber= "My Meter Number" />
    <cfset data.TransactionDetail.CustomerTransactionId = "Example - Rate Request" />
    <cfset data.WebAuthenticationDetail.UserCredential.key = "My Developer Test Key" />
    <cfset data.WebAuthenticationDetail.UserCredential.password = "My Developer Test Password" />
    
    <!--- webservice version --->
    <cfset data.Version.serviceId = "crs" />
    <cfset data.Version.major = "7" />
    <cfset data.Version.intermediate =  "0" />
    <cfset data.Version.minor =  "0" />
    
    <!--- shipment characteristics --->
    <cfset data.requestedShipment.DropoffType = "REGULAR_PICKUP" />
    <cfset data.requestedShipment.ShipTimestamp = now()>
    <cfif NOT getAllRatesFlag>
    <cfset data.requestedShipment.ServiceType = "INTERNATIONAL_PRIORITY">
    <cfset data.requestedShipment.PackagingType = "YOUR_PACKAGING">
    </cfif>
    
    <!--- shipper information --->
    <cfset streetArray = arrayNew(1) />
    <cfset arrayAppend(streetArray, "Address Line 1") />
    <cfset shipper.address.StreetLines = streetArray />
    <cfset shipper.address.City = "City Name" />
    <cfset shipper.address.StateOrProvinceCode = "TN" />
    <cfset shipper.address.PostalCode = "38115" />
    <cfset shipper.address.CountryCode = "US" />
    <cfset data.requestedShipment.shipper = shipper>
    
    <!--- receiver information --->
    <cfset streetArray = arrayNew(1) />
    <cfset arrayAppend(streetArray, "Address Line 1") />
    <cfset recipient.address.StreetLines= streetArray />
    <cfset recipient.address.City= "City Name" />
    <cfset recipient.address.StateOrProvinceCode= "QC" />
    <cfset recipient.address.PostalCode= "H1E1A1" />
    <cfset recipient.address.CountryCode= "CA" />
    <cfset data.requestedShipment.recipient = recipient>
    
    
    <cfset Payment.PaymentType = "SENDER">
    <cfset data.requestedShipment.shippingChargesPayment = Payment>
    
    <!--- package information --->
    <cfset packagesArray = ArrayNew(1)>
    <cfset newPackage = structNew()>
    <cfset newPackage.Weight.Value = "15.00">
    <cfset newPackage.Weight.Units = "LB">
    <cfset newPackage.InsuredValue.Amount = "10.00">
    <cfset newPackage.InsuredValue.Currency = "USD">
    
    <!--- package dimensions --->
    <!--- could not get this to work without using java objects --->
    <cfset newPackage.Dimensions.Length = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Width = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Height = objNonNegInteger.init(1)>
    <cfset newPackage.Dimensions.Units = "IN">
    <cfset arrayAppend(packagesArray, newPackage)>
    
    <cfset data.requestedShipment.RequestedPackageLineItems = packagesArray>
    <cfset data.requestedShipment.packageCount = objNonNegInteger.init("1")>
    <cfset data.requestedShipment.packageDetail = "INDIVIDUAL_PACKAGES">
    <cfset RateRequestTypeArray = arrayNew(1)>
    <cfset arrayAppend(RateRequestTypeArray, "ACCOUNT")>
    <cfset data.requestedShipment.RateRequestTypes = RateRequestTypeArray>
    
    <!---
    Invoke the webservice
    
    Notes, Using cfinvoke did not work. I think
    it may be related to the optional parameters
    --->
    <cfscript>
    ws = createObject("webservice", "http://127.0.0.1:8501/FedEx/RateService_v7.wsdl");
    rateReply = ws.getRates(data);
    </cfscript>
    
    <!---
    Process the response
    --->
    <cfoutput>
    <h1>Response: Highest Severity = #rateReply.getHighestSeverity().toString()#</h1>
    <cfset notifications = getNotifications(rateReply.getNotifications())>
    <cfdump var="#notifications#" label="Notifications">
    
    <cfif isResponseOK(rateReply.getHighestSeverity().toString())>
    <cfset rrds = rateReply.getRateReplyDetails() />
    
    <cfloop from="1" to="#arrayLen(rrds)#" index="i">
    <cfset rrd =  rrds[i]>
    
    Service type = #rrd.getServiceType()#<br>
    Packaging type = #rrd.getPackagingType()#<br>
    
    <cfset rsds = rrd.getRatedShipmentDetails()>
    <cfloop from="1" to="#arrayLen(rsds)#" index="j">
    <cfset rsd = rsds[j] />
    <cfset srd = rsd.getShipmentRateDetail() />
    
    RatedShipmentDetail #j#<br>
    <!--- using functions because these values may be null --->
    Rate type = #getValue( srd.getRateType() )#<br>
    Total Billing weight = #getWeightValue( srd.getTotalBillingWeight() )# <br>
    Total surcharges = #getMoneyValue( srd.getTotalSurcharges() )# <br>
    Total net charge #getMoneyValue( srd.getTotalNetCharge() )#<br>
    RatedPackageDetails:<hr>
    
    <cfset rpds = rsd.getRatedPackages()>
    <cfif not IsDefined("rpds")>
    <cfset rpds = arrayNew(1)>
    </cfif>
    
    <cfloop from="1" to="#arrayLen(rpds)#" index="k">
    RatedPackageDetail #k#<br>
    <cfset rpd = rpds[k]>
    <cfset prd = rpd.getPackageRateDetail()>
    <cfif IsDefined("prd")>
    Billing weight = #getWeightValue( prd.getBillingWeight() )# <br>
    Base charge = #getMoneyValue( prd.getBaseCharge() )# <br>
    <cfset surcharges = prd.getSurcharges()>
    <cfif not IsDefined("surcharges")>
    <cfset surcharges = arrayNew(1)>
    </cfif> 
    <cfloop from="1" to="#arrayLen(surcharges)#" index=",">
    #surcharge.getDescription()# surcharge = #getMoneyValue( surcharge.getAmount() )#<br>
    </cfloop>
    </cfif>
    </cfloop>
    </cfloop>
    </cfloop>
    </cfif>
    </cfoutput>
    
    <cffunction name="getMoneyValue" returntype="string">
    <cfargument name="obj" type="any" required="false">
    <cfif structKeyExists(arguments, "obj")>
    <cfreturn arguments.obj.getAmount().toString() &" "& arguments.obj.getCurrency().toString() />
    </cfif>
    
    <cfreturn "" />
    </cffunction>
    
    <cffunction name="getWeightValue" returntype="string">
    <cfargument name="obj" type="any" required="false">
    <cfif structKeyExists(arguments, "obj")>
    <cfreturn arguments.obj.getValue().toString() &" "& arguments.obj.getUnits().toString() />
    </cfif>
    
    <cfreturn "" />
    </cffunction>
    
    <cffunction name="getValue" returntype="string">
    <cfargument name="obj" type="any" required="false">
    <cfargument name="defaultValue" type="string" required="false" default="">
    <cfif structKeyExists(arguments, "obj")>
    <cfreturn arguments.obj.toString()/>
    <cfelse>
    <cfreturn arguments.defaultValue/>
    </cfif>
    </cffunction>
    

    ...Read More

      © Blogger templates The Professional Template by Ourblogtemplates.com 2008

    Header image adapted from atomicjeep