ideaoforder-shipping 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,585 @@
1
+ # Author:: Lucas Carlson (mailto:lucas@rufy.com)
2
+ # Copyright:: Copyright (c) 2005 Lucas Carlson
3
+ # License:: LGPL
4
+ #
5
+ #
6
+ # See http://www.fedex.com/us/solutions/wis/pdf/xml_transguide.pdf?link=4 for the full XML-based API
7
+
8
+ module Shipping
9
+ class FedEx < Base
10
+ # Gets the list price the regular consumer would have to pay. Discount price is what the
11
+ # person with this particular account number will pay
12
+ def price
13
+ get_price
14
+ return REXML::XPath.first(@response, "//FDXRateReply/EstimatedCharges/ListCharges/NetCharge").text.to_f
15
+ rescue ShippingError
16
+ raise ShippingError, get_error
17
+ end
18
+
19
+ # Gets the discount price of the shipping (with discounts taken into consideration).
20
+ # "base price" doesn't include surcharges like fuel cost, so I don't think it is the correct price to get
21
+ def discount_price
22
+ get_price
23
+ return REXML::XPath.first(@response, "//FDXRateReply/EstimatedCharges/DiscountedCharges/NetCharge").text.to_f
24
+ rescue ShippingError
25
+ raise ShippingError, get_error
26
+ end
27
+
28
+ # still not sure what the best way to handle this transaction's return data would be. Possibly a hash of the form {service => delivery_estimate}?
29
+ def express_service_availability
30
+ @data = String.new
31
+ b = Builder::XmlMarkup.new :target => @data
32
+ b.instruct!
33
+ b.FDXServiceAvailabilityRequest('xmlns:api' => 'http://www.fedex.com/fsmapi', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'FDXServiceAvailabilityRequest.xsd') { |b|
34
+ b.RequestHeader { |b|
35
+ b.AccountNumber @fedex_account
36
+ b.MeterNumber @fedex_meter
37
+ }
38
+ b.OriginAddress { |b|
39
+ b.PostalCode @sender_zip
40
+ b.CountryCode @sender_country_code || "US"
41
+ }
42
+ b.DestinationAddress { |b|
43
+ b.PostalCode @zip
44
+ b.CountryCode @country || "US"
45
+ }
46
+ b.ShipDate @ship_date unless @ship_date.blank?
47
+ b.PackageCount @package_total || '1'
48
+ }
49
+
50
+ get_response @fedex_url
51
+ end
52
+
53
+ def register
54
+ @required = [:name, :company, :phone, :email, :address, :city, :state, :zip]
55
+ @required += [:fedex_account, :fedex_url]
56
+
57
+ state = STATES.has_value?(@state.downcase) ? STATES.index(@state.downcase).upcase : @state.upcase rescue nil
58
+
59
+ @data = String.new
60
+ b = Builder::XmlMarkup.new :target => @data
61
+ b.instruct!
62
+ b.FDXSubscriptionRequest('xmlns:api' => 'http://www.fedex.com/fsmapi', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'FDXSubscriptionRequest.xsd') { |b|
63
+ b.RequestHeader { |b|
64
+ b.CustomerTransactionIdentifier @transaction_identifier if @transaction_identifier # optional
65
+ b.AccountNumber @fedex_account
66
+ }
67
+ b.Contact { |b|
68
+ b.PersonName @name
69
+ b.CompanyName @company
70
+ b.Department @department if @department
71
+ b.PhoneNumber @phone.to_s.gsub(/[^\d]/,"")
72
+ b.tag! :"E-MailAddress", @email
73
+ }
74
+ b.Address { |b|
75
+ b.Line1 @address
76
+ b.Line2 @address2 if @address2
77
+ b.City @city
78
+ b.StateOrProvinceCode state
79
+ b.PostalCode @zip
80
+ b.CountryCode @country || 'US'
81
+ }
82
+ }
83
+
84
+ get_response @fedex_url
85
+
86
+ return REXML::XPath.first(@response, "//FDXSubscriptionReply/MeterNumber").text
87
+ end
88
+
89
+ # require 'fileutils'
90
+ # fedex = Shipping::FedEx.new :name => 'John Doe', ... , :sender_zip => 97202
91
+ # label = fedex.label
92
+ # puts label.tracking_number
93
+ # FileUtils.cp label.image.path, '/path/to/my/images/directory/'
94
+ #
95
+ # There are several types of labels that can be returned by changing @image_type.
96
+ # PNG is selected by default.
97
+ #
98
+ def label
99
+ @required = [:phone, :email, :address, :city, :state, :zip ]
100
+ @required += [:sender_phone, :sender_email, :sender_address, :sender_city, :sender_state, :sender_zip ]
101
+ @required += [:fedex_account, :fedex_url, :fedex_meter]
102
+
103
+ @transaction_type ||= 'ship_ground'
104
+ @weight = (@weight.to_f*10).round/10.0
105
+ @declared_value = (@declared_value.to_f*100).round/100.0 unless @declared_value.blank?
106
+ state = STATES.has_value?(@state.downcase) ? STATES.index(@state.downcase).upcase : @state.upcase
107
+ sender_state = STATES.has_value?(@sender_state.downcase) ? STATES.index(@sender_state.downcase).upcase : @sender_state.upcase
108
+
109
+ @data = String.new
110
+ b = Builder::XmlMarkup.new :target => @data
111
+ b.instruct!
112
+ b.FDXShipRequest('xmlns:api' => 'http://www.fedex.com/fsmapi', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'FDXShipRequest.xsd') { |b|
113
+ b.RequestHeader { |b|
114
+ b.AccountNumber @fedex_account
115
+ b.MeterNumber @fedex_meter
116
+ b.CarrierCode TransactionTypes[@transaction_type][1]
117
+ }
118
+ b.ShipDate((Time.now).strftime("%Y-%m-%d"))
119
+ b.ShipTime((Time.now).strftime("%H:%M:%S"))
120
+ b.DropoffType @dropoff_type || 'REGULARPICKUP'
121
+ b.Service ServiceTypes[@service_type] || ServiceTypes['ground_service'] # default to ground service
122
+ b.Packaging PackageTypes[@packaging_type] || 'YOURPACKAGING'
123
+ b.WeightUnits @weight_units || 'LBS' # or KGS
124
+ b.Weight @weight
125
+ b.CurrencyCode @currency_code || 'USD'
126
+ b.Origin { |b|
127
+ b.Contact { |b|
128
+ if @sender_name.to_s.size > 2
129
+ b.PersonName @sender_name
130
+ b.CompanyName @sender_company unless @sender_company.blank?
131
+ elsif @sender_company.to_s.size > 2
132
+ b.PersonName @sender_name unless @sender_name.blank?
133
+ b.CompanyName @sender_company
134
+ else
135
+ raise ShippingError, "Either the sender_name or the sender_company value must be bigger than 2 characters."
136
+ end
137
+ b.Department @sender_department unless @sender_department.blank?
138
+ b.PhoneNumber @sender_phone.gsub(/[^\d]/,"")
139
+ b.PagerNumber @sender_pager.gsub(/[^\d]/,"") if @sender_pager.class == String
140
+ b.FaxNumber @sender_fax.gsub(/[^\d]/,"") if @sender_fax.class == String
141
+ b.tag! :"E-MailAddress", @sender_email
142
+ }
143
+ b.Address { |b|
144
+ b.Line1 @sender_address
145
+ b.Line2 @sender_address2 unless @sender_address2.blank?
146
+ b.City @sender_city
147
+ b.StateOrProvinceCode sender_state
148
+ b.PostalCode @sender_zip
149
+ b.CountryCode @sender_country || 'US'
150
+ }
151
+ }
152
+ b.Destination { |b|
153
+ b.Contact { |b|
154
+ if @name.to_s.size > 2
155
+ b.PersonName @name
156
+ b.CompanyName @company unless @company.blank?
157
+ elsif @company.to_s.size > 2
158
+ b.PersonName @name unless @name.blank?
159
+ b.CompanyName @company
160
+ else
161
+ raise ShippingError, "Either the name or the company value must be bigger than 2 characters."
162
+ end
163
+ b.Department @department unless @department.blank?
164
+ b.PhoneNumber @phone.gsub(/[^\d]/,"")
165
+ b.PagerNumber @pager.gsub(/[^\d]/,"") if @pager.class == String
166
+ b.FaxNumber @fax.gsub(/[^\d]/,"") if @fax.class == String
167
+ b.tag! :"E-MailAddress", @email
168
+ }
169
+ b.Address { |b|
170
+ b.Line1 @address
171
+ b.Line2 @address2 unless @address2.blank?
172
+ b.City @city
173
+ b.StateOrProvinceCode state
174
+ b.PostalCode @zip
175
+ b.CountryCode @country || 'US'
176
+ }
177
+ }
178
+ b.Payment { |b|
179
+ b.PayorType PaymentTypes[@pay_type] || 'SENDER'
180
+ b.Payor { |b|
181
+ b.AccountNumber @payor_account_number
182
+ b.CountryCode @payor_country_code unless @payor_country_code.blank?
183
+ } unless @payor_account_number.blank?
184
+ }
185
+ b.RMA { |b|
186
+ b.Number @rma_number
187
+ } unless @rma_number.blank?
188
+ b.SpecialServices { |b|
189
+ b.EMailNotification { |b|
190
+ b.ShipAlertOptionalMessage @message
191
+ b.Shipper { |b|
192
+ b.ShipAlert @shipper_ship_alert ? 'true' : 'false'
193
+ b.LanguageCode @shipper_language || 'EN' # FR also available
194
+ }
195
+ b.Recipient { |b|
196
+ b.ShipAlert @recipient_ship_alert ? 'true' : 'false'
197
+ b.LanguageCode @recipient_language || 'EN' # FR also available
198
+ }
199
+ b.Other { |b|
200
+ b.tag! :"E-MailAddress", @other_email
201
+ b.ShipAlert @other_ship_alert ? 'true' : 'false'
202
+ b.LanguageCode @other_language || 'EN' # FR also available
203
+ } unless @other_email.blank?
204
+ }
205
+ } unless @message.blank?
206
+ b.Label { |b|
207
+ b.Type @label_type || '2DCOMMON'
208
+ b.ImageType @image_type || 'PNG'
209
+ }
210
+ }
211
+ get_response @fedex_url
212
+
213
+ begin
214
+ response = Hash.new
215
+ response[:tracking_number] = REXML::XPath.first(@response, "//FDXShipReply/Tracking/TrackingNumber").text
216
+ response[:encoded_image] = REXML::XPath.first(@response, "//FDXShipReply/Labels/OutboundLabel").text
217
+ response[:image] = Tempfile.new("shipping_label")
218
+ response[:image].write Base64.decode64( response[:encoded_image] )
219
+ response[:image].rewind
220
+ rescue
221
+ raise ShippingError, get_error
222
+ end
223
+
224
+ # allows for things like fedex.label.url
225
+ def response.method_missing(name, *args)
226
+ has_key?(name) ? self[name] : super
227
+ end
228
+
229
+ # don't allow people to edit the response
230
+ response.freeze
231
+ end
232
+
233
+ # require 'fileutils'
234
+ # fedex = Shipping::FedEx.new :name => 'John Doe', ... , :sender_zip => 97202
235
+ # label = fedex.email_label
236
+ # puts label.url
237
+ # puts label.tracking_number
238
+ #
239
+ def return_label
240
+ @required = [:phone, :email, :address, :city, :state, :zip ]
241
+ @required += [:sender_phone, :sender_email, :sender_address, :sender_city, :sender_state, :sender_zip ]
242
+ @required += [:fedex_account, :fedex_url, :fedex_meter, :weight ]
243
+
244
+ @transaction_type ||= 'ship_ground'
245
+ @weight = (@weight.to_f*10).round/10.0
246
+ @declared_value = (@declared_value.to_f*100).round/100.0 unless @declared_value.blank?
247
+
248
+ state = STATES.has_value?(@state.downcase) ? STATES.index(@state.downcase).upcase : @state.upcase rescue nil
249
+ sender_state = STATES.has_value?(@sender_state.downcase) ? STATES.index(@sender_state.downcase).upcase : @sender_state.upcase rescue nil
250
+
251
+ @data = String.new
252
+ b = Builder::XmlMarkup.new :target => @data
253
+ b.instruct!
254
+ b.FDXEmailLabelRequest('xmlns:api' => 'http://www.fedex.com/fsmapi', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'FDXEmailLabelRequest.xsd') { |b|
255
+ b.RequestHeader { |b|
256
+ b.AccountNumber @fedex_account
257
+ b.MeterNumber @fedex_meter
258
+ b.CarrierCode TransactionTypes[@transaction_type][1]
259
+ }
260
+ b.URLExpirationDate((Time.now + 3600*24).strftime("%Y-%m-%d"))
261
+ b.tag! :"URLNotificationE-MailAddress", @sender_email
262
+ b.MerchantPhoneNumber @sender_phone.gsub(/[^\d]/,"")
263
+ b.Service ServiceTypes[@service_type] || ServiceTypes['ground_service'] # default to ground service
264
+ b.Packaging PackageTypes[@packaging_type] || 'YOURPACKAGING'
265
+ b.WeightUnits @weight_units || 'LBS' # or KGS
266
+ b.CurrencyCode @currency_code || 'USD'
267
+ b.Origin { |b|
268
+ b.Contact { |b|
269
+ if @sender_name.to_s.size > 2
270
+ b.PersonName @sender_name
271
+ b.CompanyName @sender_company unless @sender_company.blank?
272
+ elsif @sender_company.to_s.size > 2
273
+ b.PersonName @sender_name unless @sender_name.blank?
274
+ b.CompanyName @sender_company
275
+ else
276
+ raise ShippingError, "Either the sender_name or the sender_company value must be bigger than 2 characters."
277
+ end
278
+ b.Department @sender_department unless @sender_department.blank?
279
+ b.PhoneNumber @sender_phone.gsub(/[^\d]/,"")
280
+ b.PagerNumber @sender_pager.gsub(/[^\d]/,"") if @sender_pager.class == String
281
+ b.FaxNumber @sender_fax.gsub(/[^\d]/,"") if @sender_fax.class == String
282
+ b.tag! :"E-MailAddress", @sender_email
283
+ }
284
+ b.Address { |b|
285
+ b.Line1 @sender_address
286
+ b.Line2 @sender_address2 unless @sender_address2.blank?
287
+ b.City @sender_city
288
+ b.StateOrProvinceCode sender_state
289
+ b.PostalCode @sender_zip
290
+ b.CountryCode @sender_country || 'US'
291
+ }
292
+ }
293
+ b.Destination { |b|
294
+ b.Contact { |b|
295
+ if @name.to_s.size > 2
296
+ b.PersonName @name
297
+ b.CompanyName @company unless @company.blank?
298
+ elsif @company.to_s.size > 2
299
+ b.PersonName @name unless @name.blank?
300
+ b.CompanyName @company
301
+ else
302
+ raise ShippingError, "Either the name or the company value must be bigger than 2 characters."
303
+ end
304
+ b.Department @department unless @department.blank?
305
+ b.PhoneNumber @phone.gsub(/[^\d]/,"")
306
+ b.PagerNumber @pager.gsub(/[^\d]/,"") if @pager.class == String
307
+ b.FaxNumber @fax.gsub(/[^\d]/,"") if @fax.class == String
308
+ b.tag! :"E-MailAddress", @email
309
+ }
310
+ b.Address { |b|
311
+ b.Line1 @address
312
+ b.Line2 @address2 unless @address2.blank?
313
+ b.City @city
314
+ b.StateOrProvinceCode state
315
+ b.PostalCode @zip
316
+ b.CountryCode @country || 'US'
317
+ }
318
+ }
319
+
320
+ b.Payment { |b|
321
+ b.PayorType PaymentTypes[@pay_type] || 'SENDER'
322
+ b.Payor { |b|
323
+ b.AccountNumber @payor_account_number
324
+ b.CountryCode @payor_country_code unless @payor_country_code.blank?
325
+ } unless @payor_account_number.blank?
326
+ }
327
+
328
+ b.RMA { |b|
329
+ b.Number @rma_number
330
+ } unless @rma_number.blank?
331
+
332
+ b.Package { |b|
333
+ b.Weight @weight
334
+ b.DeclaredValue @declared_value || '99.00'
335
+ b.ReferenceInfo { |b|
336
+ b.CustomerReference @customer_reference
337
+ } unless @customer_reference.blank?
338
+ b.ItemDescription @description || "Shipment"
339
+ }
340
+
341
+ b.SpecialServices { |b|
342
+ b.EMailNotification { |b|
343
+ b.ShipAlertOptionalMessage @message
344
+ b.Shipper { |b|
345
+ b.ShipAlert @shipper_ship_alert ? 'true' : 'false'
346
+ b.LanguageCode @shipper_language || 'EN' # FR also available
347
+ }
348
+ b.Recipient { |b|
349
+ b.ShipAlert @recipient_ship_alert ? 'true' : 'false'
350
+ b.LanguageCode @recipient_language || 'EN' # FR also available
351
+ }
352
+ b.Other { |b|
353
+ b.tag! :"E-MailAddress", @other_email
354
+ b.ShipAlert @other_ship_alert ? 'true' : 'false'
355
+ b.LanguageCode @other_language || 'EN' # FR also available
356
+ } unless @other_email.blank?
357
+ }
358
+ } unless @message.blank?
359
+ }
360
+
361
+ get_response @fedex_url
362
+
363
+ begin
364
+ response = Hash.new
365
+ response[:url] = REXML::XPath.first(@response, "//FDXEmailLabelReply/URL").text
366
+ response[:userid] = REXML::XPath.first(@response, "//FDXEmailLabelReply/UserID").text
367
+ response[:password] = REXML::XPath.first(@response, "//FDXEmailLabelReply/Password").text
368
+ response[:tracking_number] = REXML::XPath.first(@response, "//FDXEmailLabelReply/Package/TrackingNumber").text
369
+ rescue
370
+ raise ShippingError, get_error
371
+ end
372
+
373
+ # allows for things like fedex.label.url
374
+ def response.method_missing(name, *args)
375
+ has_key?(name) ? self[name] : super
376
+ end
377
+
378
+ # don't allow people to edit the response
379
+ return response.freeze
380
+ end
381
+
382
+ def void(tracking_number)
383
+ @required = [:fedex_account, :fedex_url, :fedex_meter]
384
+
385
+ @transaction_type ||= 'ship_ground'
386
+
387
+ @data = String.new
388
+ b = Builder::XmlMarkup.new :target => @data
389
+ b.instruct!
390
+ b.FDXShipDeleteRequest('xmlns:api' => 'http://www.fedex.com/fsmapi', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'FDXShipDeleteRequest.xsd') { |b|
391
+ b.RequestHeader { |b|
392
+ b.AccountNumber @fedex_account
393
+ b.MeterNumber @fedex_meter
394
+ b.CarrierCode TransactionTypes[@transaction_type][1]
395
+ }
396
+ b.TrackingNumber tracking_number
397
+ }
398
+
399
+ get_response @fedex_url
400
+ raise ShippingError, get_error if get_error
401
+ return true
402
+ end
403
+
404
+ def available_services(force=nil)
405
+ if @services.empty? || force
406
+ get_available_services
407
+ else
408
+ @services
409
+ end
410
+ end
411
+
412
+ private
413
+
414
+ def get_price #:nodoc:
415
+ @required = [:zip, :sender_zip, :weight]
416
+ @required += [:transaction_type, :fedex_account, :fedex_meter, :fedex_url]
417
+
418
+ @transaction_type ||= 'rate_ground'
419
+ @weight = (@weight.to_f*10).round/10.0
420
+
421
+ @data = String.new
422
+ b = Builder::XmlMarkup.new(:target => @data)
423
+ b.instruct!
424
+ b.FDXRateRequest('xmlns:api' => 'http://www.fedex.com/fsmapi', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'FDXRateRequest.xsd') { |b|
425
+ b.RequestHeader { |b|
426
+ b.AccountNumber @fedex_account
427
+ b.MeterNumber @fedex_meter
428
+ b.CarrierCode TransactionTypes[@transaction_type][1]
429
+ }
430
+ b.ShipDate @ship_date unless @ship_date.blank?
431
+ b.DropoffType @dropoff_type || 'REGULARPICKUP'
432
+ b.Service ServiceTypes[@service_type] || ServiceTypes['ground_service'] # default to ground service
433
+ b.Packaging PackageTypes[@packaging_type] || 'YOURPACKAGING'
434
+ b.WeightUnits @weight_units || 'LBS'
435
+ b.Weight @weight
436
+ b.ListRate true #tells fedex to return list rates as well as discounted rates
437
+ b.OriginAddress { |b|
438
+ b.StateOrProvinceCode self.class.state_from_zip(@sender_zip)
439
+ b.PostalCode @sender_zip
440
+ b.CountryCode @sender_country_code || "US"
441
+ }
442
+ b.DestinationAddress { |b|
443
+ b.StateOrProvinceCode self.class.state_from_zip(@zip)
444
+ b.PostalCode @zip
445
+ b.CountryCode @country || "US"
446
+ }
447
+ b.Payment { |b|
448
+ b.PayorType PaymentTypes[@pay_type] || 'SENDER'
449
+ }
450
+ b.PackageCount @package_total || '1'
451
+ }
452
+
453
+ get_response @fedex_url
454
+ end
455
+
456
+ def get_error
457
+ return if @response.class != REXML::Document
458
+ error = REXML::XPath.first(@response, "//Error")
459
+ return if !error
460
+
461
+ code = REXML::XPath.first(error, "//Code").text
462
+ message = REXML::XPath.first(error, "//Message").text
463
+
464
+ return "Error #{code}: #{message}"
465
+ end
466
+
467
+ def get_available_services
468
+ @required = [:zip, :sender_zip, :weight]
469
+ @required += [:fedex_account, :fedex_meter, :fedex_url]
470
+
471
+ @transaction_type = 'rate_services'
472
+ @weight = (@weight.to_f*10).round/10.0
473
+
474
+ # Ground first
475
+ @services = []
476
+ rate_available_services_request('FDXG')
477
+ rate_available_services_request('FDXE')
478
+
479
+ return @services
480
+ end
481
+
482
+ def rate_available_services_request(carrier_code)
483
+ @data = String.new
484
+ b = Builder::XmlMarkup.new(:target => @data)
485
+ b.instruct!
486
+ b.FDXRateAvailableServicesRequest('xmlns:api' => 'http://www.fedex.com/fsmapi', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'FDXRateAvailableServicesRequest.xsd') { |b|
487
+ b.RequestHeader { |b|
488
+ b.AccountNumber @fedex_account
489
+ b.MeterNumber @fedex_meter
490
+ b.CarrierCode carrier_code
491
+ }
492
+ b.ShipDate @ship_date unless @ship_date.blank?
493
+ b.DropoffType DropoffTypes[@dropoff_type] || DropoffTypes['regular_pickup']
494
+ b.Packaging PackageTypes[@packaging_type] || PackageTypes['your_packaging']
495
+ b.WeightUnits @weight_units || 'LBS'
496
+ b.Weight @weight || '1.0'
497
+ b.ListRate 'false'
498
+ b.OriginAddress { |b|
499
+ b.StateOrProvince @sender_state
500
+ b.PostalCode @sender_zip
501
+ b.CountryCode @sender_country_code || 'US'
502
+ }
503
+ b.DestinationAddress { |b|
504
+ b.StateOrProvince @state
505
+ b.PostalCode @zip
506
+ b.CountryCode @country_code || 'US'
507
+ }
508
+ b.Payment { |b|
509
+ b.PayorType PaymentTypes[@pay_type] || PaymentTypes['sender']
510
+ }
511
+ b.PackageCount @package_total || 1
512
+ }
513
+ get_response @fedex_url
514
+
515
+ REXML::XPath.each(@response, "//Entry") { |el|
516
+ @services << Shipping::Base.initialize_for_fedex_service(el)
517
+ }
518
+
519
+ end
520
+
521
+ # The following type hashes are to allow cross-api data retrieval
522
+
523
+ ServiceTypes = {
524
+ "priority" => "PRIORITYOVERNIGHT",
525
+ "2day" => "FEDEX2DAY",
526
+ "standard_overnight" => "STANDARDOVERNIGHT",
527
+ "first_overnight" => "FIRSTOVERNIGHT",
528
+ "express_saver" => "FEDEXEXPRESSSAVER",
529
+ "1day_freight" => "FEDEX1DAYFREIGHT",
530
+ "2day_freight" => "FEDEX2DAYFREIGHT",
531
+ "3day_freight" => "FEDEX3DAYFREIGHT",
532
+ "international_priority" => "INTERNATIONALPRIORITY",
533
+ "international_economy" => "INTERNATIONALECONOMY",
534
+ "international_first" => "INTERNATIONALFIRST",
535
+ "international_priority_freight" => "INTERNATIONALPRIORITYFREIGHT",
536
+ "international_economy_freight" => "INTERNATIONALECONOMYFREIGHT",
537
+ "home_delivery" => "GROUNDHOMEDELIVERY",
538
+ "ground_service" => "FEDEXGROUND",
539
+ "international_ground_service" => "INTERNATIONALGROUND"
540
+ }
541
+
542
+ PackageTypes = {
543
+ "fedex_envelope" => "FEDEXENVELOPE",
544
+ "fedex_pak" => "FEDEXPAK",
545
+ "fedex_box" => "FEDEXBOX",
546
+ "fedex_tube" => "FEDEXTUBE",
547
+ "fedex_10_kg_box" => "FEDEX10KGBOX",
548
+ "fedex_25_kg_box" => "FEDEX25KGBOX",
549
+ "your_packaging" => "YOURPACKAGING"
550
+ }
551
+
552
+ DropoffTypes = {
553
+ 'regular_pickup' => 'REGULARPICKUP',
554
+ 'request_courier' => 'REQUESTCOURIER',
555
+ 'dropbox' => 'DROPBOX',
556
+ 'business_service_center' => 'BUSINESSSERVICECENTER',
557
+ 'station' => 'STATION'
558
+ }
559
+
560
+ PaymentTypes = {
561
+ 'sender' => 'SENDER',
562
+ 'recipient' => 'RECIPIENT',
563
+ 'third_party' => 'THIRDPARTY',
564
+ 'collect' => 'COLLECT'
565
+ }
566
+
567
+
568
+ TransactionTypes = {
569
+ 'rate_ground' => ['022','FDXG'],
570
+ 'rate_express' => ['022','FDXE'],
571
+ 'rate_services' => ['025',''],
572
+ 'ship_ground' => ['021','FDXG'],
573
+ 'ship_express' => ['021','FDXE'],
574
+ 'cancel_express' => ['023','FDXE'],
575
+ 'cancel_ground' => ['023','FDXG'],
576
+ 'close_ground' => ['007','FDXG'],
577
+ 'service_available' => ['019','FDXE'],
578
+ 'fedex_locater' => ['410',''],
579
+ 'subscribe' => ['211',''],
580
+ 'sig_proof_delivery' => ['402',''],
581
+ 'track' => ['405',''],
582
+ 'ref_track' => ['403','']
583
+ }
584
+ end
585
+ end