In my previous post, I talked about FedEx Address verification. In this post, I present a function that will create a FedEx Express shipping label. It will pass along your shipment information and then save the shipping label as a PDF file (or PNG, DPL, etc..) on your hard drive.
Before running this code and creating your own FedEx shipping labels, you need to register with FedEx and get an API access key. Once you have that, you are ready to access the FedEx test server.
As you can see, this function contains a substantial number of arguments. I think most of the arguments are self-explanatory. The first set of arguments, grouped as [To Address], are the shipping address.
The second set of arguments, grouped as [Package Details], concerns your package’s weight, length, etc. FedEx has several different types of boxes to choose from, and I list all available options under the argument PackagingType, attribute “Hint.” Whenver an option is available, I have listed it under the “Hint” attribute in other arguments too. You are supposed to choose one of them as the value when more than one option is available.
Argument [orderid], is any number you wish to use to identify your order. I used this same ID number to name the PDF file that saves the shipping label. For example, if your Order ID is 1234, you will have a file named1234.pdf. I also used this number to create log file names. FedEx prints this number on the shipping label so you can track packages using your FedEx account. The arguments [Department] and [ponumber] also appear on the FedEx label, and FedEx uses them as additional reference values.
Under the argument [SpecialServices], if you choose “HOLD_AT_LOCATION,” then you have to include the location address in the [“Hold At" Location Address] section. If you chose ‘DRY_ICE,’ then you have to include a weight in the [DryIceWeight] section.
The arguments [returnLog] and [fedexcallLog] are the folder path to log request and response. If you don’t need to keep a log, these arguments can remain empty.
The [fedex Access Settings] section provides the API access details, such as your access key, password, meter number etc. I keep these values in the application scoop, and they are entered as default values.
Argument [FedexPDF] defines the full path of the folder where you want to save the label PDF file. The default value is FedexPDF, which is a folder named FedexPDF saved in the same location as your ColdFusion file. If this default folder does not exist, the PDF file for the shipping label will not get saved.
After saving the label file and the log files, the FedEx tracking number will be returned as a string.
There are lot more options you can add into this function, especially in the special services area. For now, though, this function covers all the basics––actually, a bit more than the basics!
1: <cffunction name="shipping" access="remote" returntype="string" output="No"> 2: <!--- To Address ---> 3: <cfargument name="Company" type="string" required="Yes" > 4: <cfargument name="Name" type="string" required="Yes" > 5: <cfargument name="Address1" type="string" required="Yes" > 6: <cfargument name="Address2" type="string" required="No" default=""> 7: <cfargument name="City" type="string" required="Yes" > 8: <cfargument name="State" type="string" required="Yes" > 9: <cfargument name="ZIP" type="string" required="Yes" > 10: <cfargument name="Phone" type="string" required="Yes" > 11: <cfargument name="IsResident" type="string" required="No" default="false" > 12: <!--- package Details ---> 13: <cfargument name="weight" type="string" required="Yes" > 14: <cfargument name="Length" type="string" required="Yes" > 15: <cfargument name="Width" type="string" required="Yes" > 16: <cfargument name="Height" type="string" required="Yes" > 17: <cfargument name="PackagingType" type="string" required="Yes" hint="Available Options : FEDEX_10KG_BOX, FEDEX_25KG_BOX, FEDEX_BOX, FEDEX_ENVELOPE, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING"> 18: <!--- shipping details ----> 19: <cfargument name="orderid" type="string" required="No" default="#CreateUUID()#"> 20: <cfargument name="ShippingMethod" type="string" required="No" default="STANDARD_OVERNIGHT" hint="Available Options : EUROPE_FIRST_INTERNATIONAL_PRIORITY, FEDEX_1_DAY_FREIGHT, FEDEX_2_DAY, FEDEX_2_DAY_FREIGHT, FEDEX_3_DAY_FREIGHT, FEDEX_EXPRESS_SAVER, FEDEX_GROUND, FIRST_OVERNIGHT, GROUND_HOME_DELIVERY, INTERNATIONAL_ECONOMY, INTERNATIONAL_ECONOMY_FREIGHT, INTERNATIONAL_FIRST, INTERNATIONAL_PRIORITY, INTERNATIONAL_PRIORITY_FREIGHT, PRIORITY_OVERNIGHT, SMART_POST, STANDARD_OVERNIGHT"> 21: <cfargument name="ShipDate" type="string" required="No" default="#now()#"> 22: <cfargument name="department" type="string" required="No" default=""> 23: <cfargument name="ponumber" type="string" required="No" default=""> 24: <cfargument name="DropoffType" type="string" required="No" default="REGULAR_PICKUP" hint="Available Options : REGULAR_PICKUP, REQUEST_COURIER, DROP_BOX, BUSINESS_SERVICE_CENTER, STATION"> 25: <cfargument name="SpecialServices" type="string" required="No" default="" hint="Available Options : DANGEROUS_GOODS, BROKER_SELECT_OPTION, COD, DRY_ICE, ELECTRONIC_TRADE_DOCUMENTS, EMAIL_NOTIFICATION, FUTURE_DAY_SHIPMENT, HOLD_AT_LOCATION, HOME_DELIVERY_PREMIUM, INSIDE_DELIVERY, INSIDE_PICKUP, PENDING_SHIPMENT, RETURN_SHIPMENT, SATURDAY_DELIVERY, SATURDAY_PICKUP"> 26: <cfargument name="DryIceWeight" type="string" required="No" default="" hint="Dry Ice Weight"> 27: <!--- "Hold At" Location Address ----> 28: <cfargument name="HoldAtAddress1" type="string" required="No" default=""> 29: <cfargument name="HoldAtAddress2" type="string" required="No" default=""> 30: <cfargument name="HoldAtCity" type="string" required="No" default=""> 31: <cfargument name="HoldAtState" type="string" required="No" default=""> 32: <cfargument name="HoldAtZIP" type="string" required="No" default=""> 33: <cfargument name="HoldAtPhone" type="string" required="No" default=""> 34: <cfargument name="HoldAtIsResident" type="string" required="No" default="false" > 35: <!--- log settings ---> 36: <cfargument name="returnLog" type="string" required="No" default="#ExpandPath('log/return/')#"> 37: <cfargument name="fedexcallLog" type="string" required="No" default="#ExpandPath('log/fedexcall/')#"> 38: <!--- fedex Access Settings ---> 39: <cfargument name="key" type="string" required="No" default="#application.FedExkey#"> 40: <cfargument name="password" type="string" required="No" default="#application.FedExpassword#"> 41: <cfargument name="account" type="string" required="No" default="#application.FedExaccount#"> 42: <cfargument name="meter" type="string" required="No" default="#application.FedExmeter#"> 43: <cfargument name="serverurl" type="string" required="No" default="#application.FedExserver#" hint="SandBox : https://gatewaybeta.fedex.com/xml , Production: https://gateway.fedex.com/xml"> 44: <cfargument name="billingAct" type="string" required="No" default="#application.FedExbillingAct#"> 45: <cfargument name="PaymentType" type="string" required="No" default="THIRD_PARTY" hint="Available Options : COLLECT, RECIPIENT, SENDER, THIRD_PARTY"> 46: <cfargument name="LabelType" type="string" required="No" default="PAPER_4X6" hint="Available Options : PAPER_4X6, PAPER_4X8, PAPER_4X9, PAPER_7X4.75, PAPER_8.5X11_BOTTOM_HALF_LABEL, PAPER_8.5X11_TOP_HALF_LABEL, STOCK_4X6, STOCK_4X6.75_LEADING_DOC_TAB, STOCK_4X6.75_TRAILING_DOC_TAB, STOCK_4X8, STOCK_4X9_LEADING_DOC_TAB, STOCK_4X9_TRAILING_DOC_TAB"> 47: <!--- shipping label settings ---> 48: <cfargument name="FedexPDF" type="string" required="No" default="#ExpandPath('FedexPDF/')#"> 49: <cfargument name="labelFile" type="string" required="No" default="pdf" hint="Available Options : DPL, EPL2, PDF, PNG, ZPLII"> 50: <!--- From Address ---> 51: <cfargument name="FromCompany" type="string" required="No" default="My Company" > 52: <cfargument name="FromName" type="string" required="No" default="John Doe" > 53: <cfargument name="FromAddress1" type="string" required="No" default="16 Court Street" > 54: <cfargument name="FromAddress2" type="string" required="No" default=""> 55: <cfargument name="FromCity" type="string" required="No" default="New York"> 56: <cfargument name="FromState" type="string" required="No" default="NY"> 57: <cfargument name="FromZIP" type="string" required="No" default="10211"> 58: <cfargument name="FromPhone" type="string" required="No" default="2015282777" > 59: <cfargument name="FromIsResident" type="string" required="No" default="false" > 60: 61: <!---- ************************************************************** ---> 62: <!---- create fedex xml ---> 63: <!---- ************************************************************** ---> 64: <cfsavecontent variable="XMLPacket"><cfoutput> 65: <ns:ProcessShipmentRequest 66: xsi:schemaLocation ="http://www.fedex.com/templates/components/apps/wpor/secure/downloads/xml/Aug09/Advanced/ShipService_v7.xsd" 67: xmlns:ns ="http://fedex.com/ws/ship/v7" 68: xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"> 69: 70: <ns:WebAuthenticationDetail> 71: <ns:UserCredential> 72: <ns:Key>#arguments.key#
</ns:Key> 73: <ns:Password>#arguments.password#
</ns:Password> 74: </ns:UserCredential> 75: </ns:WebAuthenticationDetail> 76: 77: <ns:ClientDetail> 78: <ns:AccountNumber>#arguments.account#
</ns:AccountNumber> 79: <ns:MeterNumber>#arguments.meter#
</ns:MeterNumber> 80: </ns:ClientDetail> 81: 82: <ns:TransactionDetail> 83: <ns:CustomerTransactionId>#arguments.orderid#
</ns:CustomerTransactionId> 84: </ns:TransactionDetail> 85: 86: <ns:Version> 87: <ns:ServiceId>ship
</ns:ServiceId> 88: <ns:Major>7
</ns:Major> 89: <ns:Intermediate>0
</ns:Intermediate> 90: <ns:Minor>0
</ns:Minor> 91: </ns:Version> 92: <ns:RequestedShipment> 93: <ns:ShipTimestamp>#dateformat(arguments.ShipDate,
"yyyy-mm-dd")#T#TimeFormat(arguments.ShipDate,
"HH:mm:ss")#
</ns:ShipTimestamp> 94: <ns:DropoffType>#arguments.DropoffType#
</ns:DropoffType> 95: <ns:ServiceType>#trim(arguments.ShippingMethod)#
</ns:ServiceType> 96: <ns:PackagingType>#trim(arguments.PackagingType)#
</ns:PackagingType> 97: <ns:Shipper> 98: <ns:Contact> 99: <ns:PersonName>#arguments.FromName#
</ns:PersonName> 100: <ns:CompanyName>#arguments.FromCompany#
</ns:CompanyName> 101: <ns:PhoneNumber>#arguments.FromPhone#
</ns:PhoneNumber> 102: </ns:Contact> 103: <ns:Address> 104: <ns:StreetLines>#arguments.FromAddress1#
</ns:StreetLines> 105: <cfif len(trim(arguments.FromAddress2))><ns:StreetLines>#XMLFormat(arguments.FromAddress2)#
</ns:StreetLines></cfif> 106: <ns:City>#arguments.FromCity#
</ns:City> 107: <ns:StateOrProvinceCode>#arguments.FromState#
</ns:StateOrProvinceCode> 108: <ns:PostalCode>#arguments.FromZIP#
</ns:PostalCode> 109: <ns:CountryCode>US
</ns:CountryCode> 110: <ns:Residential>#arguments.FromIsResident#
</ns:Residential> 111: </ns:Address> 112: </ns:Shipper> 113: <ns:Recipient> 114: <ns:Contact> 115: <ns:PersonName>#XMLFormat(arguments.Name)#
</ns:PersonName> 116: <cfif len(trim(arguments.Company))> 117: <ns:CompanyName>#XMLFormat(arguments.Company)#
</ns:CompanyName> 118: </cfif> 119: <ns:PhoneNumber>#XMLFormat(arguments.Phone)#
</ns:PhoneNumber> 120: </ns:Contact> 121: <ns:Address> 122: <ns:StreetLines>#XMLFormat(arguments.Address1)#
</ns:StreetLines> 123: <cfif len(trim(arguments.Address2))><ns:StreetLines>#XMLFormat(arguments.Address2)#
</ns:StreetLines></cfif> 124: <ns:City>#XMLFormat(arguments.City)#
</ns:City> 125: <ns:StateOrProvinceCode>#XMLFormat(arguments.State)#
</ns:StateOrProvinceCode> 126: <ns:PostalCode>#XMLFormat(arguments.ZIP)#
</ns:PostalCode> 127: <ns:CountryCode>US
</ns:CountryCode> 128: <ns:Residential>#arguments.IsResident#
</ns:Residential> 129: </ns:Address> 130: </ns:Recipient> 131: 132: <ns:ShippingChargesPayment> 133: <ns:PaymentType>#arguments.PaymentType#
</ns:PaymentType> 134: <ns:Payor> 135: <ns:AccountNumber>#arguments.billingAct#
</ns:AccountNumber> 136: <ns:CountryCode>US
</ns:CountryCode> 137: </ns:Payor> 138: </ns:ShippingChargesPayment> 139: <cfif len(arguments.SpecialServices) and listfind("SATURDAY_DELIVERY,SATURDAY_PICKUP,HOLD_AT_LOCATION",arguments.SpecialServices)> 140: <ns:SpecialServicesRequested> 141: <ns:SpecialServiceTypes>#arguments.SpecialServices#
</ns:SpecialServiceTypes> 142: <cfswitch expression="#arguments.SpecialServices#"> 143: <cfcase value="HOLD_AT_LOCATION"> 144: <ns:HoldAtLocationDetail> 145: <ns:PhoneNumber>#XMLFormat(arguments.HoldAtPhone)#
</ns:PhoneNumber> 146: <ns:Address> 147: <ns:StreetLines>#XMLFormat(arguments.HoldAtAddress1)#
</ns:StreetLines> 148: <cfif len(trim(arguments.HoldAtAddress2))><ns:StreetLines>#XMLFormat(arguments.HoldAtAddress2)#
</ns:StreetLines></cfif> 149: <ns:City>#XMLFormat(arguments.HoldAtCity)#
</ns:City> 150: <ns:StateOrProvinceCode>#XMLFormat(arguments.HoldAtState)#
</ns:StateOrProvinceCode> 151: <ns:PostalCode>#XMLFormat(arguments.HoldAtZIP)#
</ns:PostalCode> 152: <ns:CountryCode>US
</ns:CountryCode> 153: <ns:Residential>#arguments.HoldAtIsResident#
</ns:Residential> 154: </ns:Address> 155: </ns:HoldAtLocationDetail> 156: </cfcase> 157: </cfswitch> 158: </ns:SpecialServicesRequested> 159: </cfif> 160: 161: <ns:LabelSpecification> 162: <ns:LabelFormatType>COMMON2D
</ns:LabelFormatType> 163: <ns:ImageType>#ucase(arguments.labelFile)#
</ns:ImageType> 164: <ns:LabelStockType>#arguments.LabelType#
</ns:LabelStockType> 165: </ns:LabelSpecification> 166: 167: <ns:RateRequestTypes>ACCOUNT
</ns:RateRequestTypes> 168: 169: <ns:PackageCount>1
</ns:PackageCount> 170: <ns:PackageDetail>INDIVIDUAL_PACKAGES
</ns:PackageDetail> 171: <ns:RequestedPackageLineItems> 172: <ns:SequenceNumber>1
</ns:SequenceNumber> 173: <ns:Weight> 174: <ns:Units>LB
</ns:Units> 175: <ns:Value>#trim(arguments.weight)#
</ns:Value> 176: </ns:Weight> 177: <ns:Dimensions> 178: <ns:Length>#trim(arguments.Length)#
</ns:Length> 179: <ns:Width>#trim(arguments.Width)#
</ns:Width> 180: <ns:Height>#trim(arguments.Height)#
</ns:Height> 181: <ns:Units>IN
</ns:Units> 182: </ns:Dimensions> 183: <ns:PhysicalPackaging>BOX
</ns:PhysicalPackaging> 184: 185: <ns:CustomerReferences> 186: <ns:CustomerReferenceType>INVOICE_NUMBER
</ns:CustomerReferenceType> 187: <ns:Value>#arguments.orderid#
</ns:Value> 188: </ns:CustomerReferences> 189: <cfif len(arguments.department)> 190: <ns:CustomerReferences> 191: <ns:CustomerReferenceType>DEPARTMENT_NUMBER
</ns:CustomerReferenceType> 192: <ns:Value>#arguments.department#
</ns:Value> 193: </ns:CustomerReferences> 194: </cfif> 195: <cfif len(arguments.ponumber)> 196: <ns:CustomerReferences> 197: <ns:CustomerReferenceType>P_O_NUMBER
</ns:CustomerReferenceType> 198: <ns:Value>#arguments.ponumber#
</ns:Value> 199: </ns:CustomerReferences> 200: </cfif> 201: <cfif len(arguments.SpecialServices) and listfind("DRY_ICE,DANGEROUS_GOODS",arguments.SpecialServices)> 202: <ns:SpecialServicesRequested> 203: <ns:SpecialServiceTypes>#arguments.SpecialServices#
</ns:SpecialServiceTypes> 204: <cfswitch expression="#arguments.SpecialServices#"> 205: <cfcase value="DRY_ICE"> 206: <ns:DryIceWeight> 207: <ns:Units>KG
</ns:Units> 208: <ns:Value>#arguments.DryIceWeight#
</ns:Value> 209: </ns:DryIceWeight> 210: </cfcase> 211: <!--- More special services discussions needed to be added here ----> 212: </cfswitch> 213: </ns:SpecialServicesRequested> 214: </cfif> 215: 216: </ns:RequestedPackageLineItems> 217: </ns:RequestedShipment> 218: </ns:ProcessShipmentRequest> 219: </cfoutput></cfsavecontent> 220: 221: 222: <!---- ************************************************************** ---> 223: <!---- log the outgoing fedex request ---> 224: <!---- ************************************************************** ---> 225: <cfif len(arguments.fedexcallLog) and DirectoryExists(arguments.fedexcallLog)> 226: <cfif FileExists("#arguments.fedexcallLog##arguments.orderid#.xml")> 227: <cffile 228: action = "delete" 229: file = "#arguments.fedexcallLog##arguments.orderid#.xml"> 230: </cfif> 231: <cffile 232: action = "write" 233: charset ="utf-8" 234: file = "#arguments.fedexcallLog##arguments.orderid#.xml" 235: output = "#XMLPacket#"> 236: </cfif> 237: <!---- ************************************************************** ---> 238: <!---- call fedex ---> 239: <!---- ************************************************************** ---> 240: <cftry> 241: <cfhttp url="#arguments.serverurl#" port="443" method ="POST" throwonerror="yes"> 242: <cfhttpparam name="name" type="XML" value="#XMLPacket#"> 243: </cfhttp> 244: <cfset local.output = XmlParse(CFHTTP.FileContent)> 245: <cfcatch> 246: <cfset TrackingNumber = ""> 247: <cfset local.output = cfcatch> 248: </cfcatch> 249: </cftry> 250: 251: <!---- ************************************************************** ---> 252: <!---- log fedex return ---> 253: <!---- ************************************************************** ---> 254: <cfif len(arguments.returnLog) and DirectoryExists(arguments.returnLog)> 255: <cfif FileExists("#arguments.returnLog##arguments.orderid#.xml")> 256: <cffile 257: action = "delete" 258: file = "#arguments.returnLog##arguments.orderid#.xml"> 259: </cfif> 260: <cffile 261: action = "write" 262: file = "#arguments.returnLog##arguments.orderid#.xml" 263: output = "#local.output#" 264: charset = "utf-8"> 265: </cfif> 266: 267: <!---- ************************************************************** ---> 268: <!---- save Label / Get Tracking Number ---> 269: <!---- ************************************************************** ---> 270: <cfif IsDefined("local.output.ProcessShipmentReply.CompletedShipmentDetail.CompletedPackageDetails.TrackingIds.TrackingNumber")> 271: <cfset TrackingNumber = local.output.ProcessShipmentReply.CompletedShipmentDetail.CompletedPackageDetails.TrackingIds.TrackingNumber.XmlText> 272: 273: <cfif len(arguments.FedexPDF) and DirectoryExists(arguments.FedexPDF)> 274: <cfset local.img = local.output.ProcessShipmentReply.CompletedShipmentDetail.CompletedPackageDetails.Label.Parts.Image.XmlText> 275: <cfset local.img = ToBinary(local.output.ProcessShipmentReply.CompletedShipmentDetail.CompletedPackageDetails.Label.Parts.Image.XmlText)> 276: 277: <cfif FileExists("#arguments.FedexPDF##arguments.orderid#.#arguments.labelFile#")> 278: <cffile 279: action = "delete" 280: file = "#arguments.FedexPDF##arguments.orderid#.#arguments.labelFile#"> 281: </cfif> 282: <cffile action ="write" 283: charset ="utf-8" 284: file ="#arguments.FedexPDF##arguments.orderid#.#arguments.labelFile#" 285: output ="#local.img#"> 286: </cfif> 287: <cfelse> 288: <cfset TrackingNumber = ""> 289: </cfif> 290: <cfreturn TrackingNumber> 291: </cffunction>
Here is the FedEx ShipAPI Certification Test Scenario Cheat Sheet using this function.
Posted by Saman W Jayasekara at Monday 03 May 2010 10:35 AM
.
Shipping API
.
ColdFusion