class Fedex::Request::Base
Constants
- CARRIER_CODES
List of available Carrier Codes
- CLEARANCE_BROKERAGE_TYPE
Clearance Brokerage Type
- DROP_OFF_TYPES
List of available DropOffTypes
- PACKAGING_TYPES
List of available Packaging Type
- PAYMENT_TYPE
List of available Payment Types
- PRODUCTION_URL
Fedex
Production URL- RECIPIENT_CUSTOM_ID_TYPE
Recipient Custom ID Type
- SERVICE_TYPES
List of available Service Types
- TEST_URL
Fedex
Text URL
Attributes
If true the rate method will return the complete response from the Fedex
Web Service
Public Class Methods
In order to use Fedex
rates API you must first apply for a developer(and later production keys), Visit {www.fedex.com/us/developer/ Fedex
Developer Center} for more information about how to obtain your keys. @param [String] key - Fedex
web service key @param [String] password - Fedex
password @param [String] account_number - Fedex
account_number @param [String] meter - Fedex
meter number @param [String] mode - [development/production]
return a Fedex::Request::Base
object
# File lib/fedex/request/base.rb, line 50 def initialize(credentials, options={}) requires!(options, :shipper, :recipient, :packages) @credentials = credentials @shipper, @recipient, @packages, @service_type, @customs_clearance_detail, @debug = options[:shipper], options[:recipient], options[:packages], options[:service_type], options[:customs_clearance_detail], options[:debug] @origin = options[:origin] @debug = ENV['DEBUG'] == 'true' @shipping_options = options[:shipping_options] ||={} @payment_options = options[:payment_options] ||={} requires!(@payment_options, :type, :account_number, :name, :company, :phone_number, :country_code) if @payment_options.length > 0 if options.has_key?(:mps) @mps = options[:mps] requires!(@mps, :package_count, :total_weight, :sequence_number) requires!(@mps, :master_tracking_id) if @mps.has_key?(:sequence_number) && @mps[:sequence_number].to_i >= 2 else @mps = {} end # Expects hash with addr and port if options[:http_proxy] self.class.http_proxy options[:http_proxy][:host], options[:http_proxy][:port] end end
Public Instance Methods
Sends post request to Fedex
web service and parse the response. Implemented by each subclass
# File lib/fedex/request/base.rb, line 74 def process_request raise NotImplementedError, "Override process_request in subclass" end
Private Instance Methods
Add Client Detail information(account_number and meter_number) to xml request
# File lib/fedex/request/base.rb, line 90 def add_client_detail(xml) xml.ClientDetail{ xml.AccountNumber @credentials.account_number xml.MeterNumber @credentials.meter xml.Localization{ xml.LanguageCode 'en' # English xml.LocaleCode 'us' # United States } } end
# File lib/fedex/request/base.rb, line 305 def add_customer_references(xml, package) # customer_refrences is a legacy misspelling if refs = package[:customer_references] || package[:customer_refrences] refs.each do |ref| xml.CustomerReferences{ if ref.is_a?(Hash) # :type can specify custom type: # # BILL_OF_LADING, CUSTOMER_REFERENCE, DEPARTMENT_NUMBER, # ELECTRONIC_PRODUCT_CODE, INTRACOUNTRY_REGULATORY_REFERENCE, # INVOICE_NUMBER, P_O_NUMBER, RMA_ASSOCIATION, # SHIPMENT_INTEGRITY, STORE_NUMBER xml.CustomerReferenceType ref[:type] xml.Value ref[:value] else xml.CustomerReferenceType 'CUSTOMER_REFERENCE' xml.Value ref end } end end end
Add customs clearance(for international shipments)
# File lib/fedex/request/base.rb, line 329 def add_customs_clearance(xml) xml.CustomsClearanceDetail{ hash_to_xml(xml, @customs_clearance_detail) } end
Add Master Tracking Id (for MPS Shipping Labels, this is required when requesting labels 2 through n)
# File lib/fedex/request/base.rb, line 210 def add_master_tracking_id(xml) if @mps.has_key? :master_tracking_id xml.MasterTrackingId{ xml.TrackingIdType @mps[:master_tracking_id][:tracking_id_type] xml.TrackingNumber @mps[:master_tracking_id][:tracking_number] } end end
Add shipper to xml request
# File lib/fedex/request/base.rb, line 147 def add_origin(xml) xml.Origin{ xml.Contact{ xml.PersonName @origin[:name] xml.CompanyName @origin[:company] xml.PhoneNumber @origin[:phone_number] } xml.Address { Array(@origin[:address]).take(2).each do |address_line| xml.StreetLines address_line end xml.City @origin[:city] xml.StateOrProvinceCode @origin[:state] xml.PostalCode @origin[:postal_code] xml.CountryCode @origin[:country_code] } } end
Add packages to xml request
# File lib/fedex/request/base.rb, line 220 def add_packages(xml) add_master_tracking_id(xml) if @mps.has_key? :master_tracking_id package_count = @packages.size if @mps.has_key? :package_count xml.PackageCount @mps[:package_count] else xml.PackageCount package_count end @packages.each do |package| xml.RequestedPackageLineItems{ if @mps.has_key? :sequence_number xml.SequenceNumber @mps[:sequence_number] else xml.GroupPackageCount 1 end if package[:insured_value] xml.InsuredValue{ xml.Currency package[:insured_value][:currency] xml.Amount package[:insured_value][:amount] } end xml.Weight{ xml.Units package[:weight][:units] xml.Value package[:weight][:value] } if package[:dimensions] xml.Dimensions{ xml.Length package[:dimensions][:length] xml.Width package[:dimensions][:width] xml.Height package[:dimensions][:height] xml.Units package[:dimensions][:units] } end add_customer_references(xml, package) if package[:special_services_requested] xml.SpecialServicesRequested{ if package[:special_services_requested][:special_service_types] if package[:special_services_requested][:special_service_types].is_a? Array package[:special_services_requested][:special_service_types].each do |type| xml.SpecialServiceTypes type end else xml.SpecialServiceTypes package[:special_services_requested][:special_service_types] end end # Handle COD Options if package[:special_services_requested][:cod_detail] xml.CodDetail{ xml.CodCollectionAmount{ xml.Currency package[:special_services_requested][:cod_detail][:cod_collection_amount][:currency] xml.Amount package[:special_services_requested][:cod_detail][:cod_collection_amount][:amount] } if package[:special_services_requested][:cod_detail][:add_transportation_charges] xml.AddTransportationCharges package[:special_services_requested][:cod_detail][:add_transportation_charges] end xml.CollectionType package[:special_services_requested][:cod_detail][:collection_type] xml.CodRecipient { add_shipper(xml) } if package[:special_services_requested][:cod_detail][:reference_indicator] xml.ReferenceIndicator package[:special_services_requested][:cod_detail][:reference_indicator] end } end # DangerousGoodsDetail goes here if package[:special_services_requested][:dry_ice_weight] xml.DryIceWeight{ xml.Units package[:special_services_requested][:dry_ice_weight][:units] xml.Value package[:special_services_requested][:dry_ice_weight][:value] } end if package[:special_services_requested][:signature_option_detail] xml.SignatureOptionDetail{ xml.OptionType package[:special_services_requested][:signature_option_detail][:signature_option_type] } end if package[:special_services_requested][:priority_alert_detail] xml.PriorityAlertDetail package[:special_services_requested][:priority_alert_detail] end } end } end end
Add recipient to xml request
# File lib/fedex/request/base.rb, line 167 def add_recipient(xml) xml.Recipient{ xml.Contact{ xml.PersonName @recipient[:name] xml.CompanyName @recipient[:company] xml.PhoneNumber @recipient[:phone_number] } xml.Address { Array(@recipient[:address]).take(2).each do |address_line| xml.StreetLines address_line end xml.City @recipient[:city] xml.StateOrProvinceCode @recipient[:state] xml.PostalCode @recipient[:postal_code] xml.CountryCode @recipient[:country_code] xml.Residential @recipient[:residential] } } end
Add information for shipments
# File lib/fedex/request/base.rb, line 112 def add_requested_shipment(xml) xml.RequestedShipment{ xml.DropoffType @shipping_options[:drop_off_type] ||= "REGULAR_PICKUP" xml.ServiceType service_type xml.PackagingType @shipping_options[:packaging_type] ||= "YOUR_PACKAGING" add_shipper(xml) add_recipient(xml) add_shipping_charges_payment(xml) add_customs_clearance(xml) if @customs_clearance_detail xml.RateRequestTypes "ACCOUNT" add_packages(xml) } end
Add shipper to xml request
# File lib/fedex/request/base.rb, line 127 def add_shipper(xml) xml.Shipper{ xml.Contact{ xml.PersonName @shipper[:name] xml.CompanyName @shipper[:company] xml.PhoneNumber @shipper[:phone_number] } xml.Address { Array(@shipper[:address]).take(2).each do |address_line| xml.StreetLines address_line end xml.City @shipper[:city] xml.StateOrProvinceCode @shipper[:state] xml.PostalCode @shipper[:postal_code] xml.CountryCode @shipper[:country_code] } } end
Add shipping charges to xml request
# File lib/fedex/request/base.rb, line 188 def add_shipping_charges_payment(xml) xml.ShippingChargesPayment{ xml.PaymentType @payment_options[:type] || "SENDER" xml.Payor{ if service[:version].to_i >= Fedex::API_VERSION.to_i xml.ResponsibleParty { xml.AccountNumber @payment_options[:account_number] || @credentials.account_number xml.Contact { xml.PersonName @payment_options[:name] || @shipper[:name] xml.CompanyName @payment_options[:company] || @shipper[:company] xml.PhoneNumber @payment_options[:phone_number] || @shipper[:phone_number] } } else xml.AccountNumber @payment_options[:account_number] || @credentials.account_number xml.CountryCode @payment_options[:country_code] || @shipper[:country_code] end } } end
Add Version to xml request, using the version identified in the subclass
# File lib/fedex/request/base.rb, line 102 def add_version(xml) xml.Version{ xml.ServiceId service[:id] xml.Major service[:version] xml.Intermediate 0 xml.Minor 0 } end
Add web authentication detail information(key and password) to xml request
# File lib/fedex/request/base.rb, line 80 def add_web_authentication_detail(xml) xml.WebAuthenticationDetail{ xml.UserCredential{ xml.Key @credentials.key xml.Password @credentials.password } } end
Fedex
Web Service Api
# File lib/fedex/request/base.rb, line 336 def api_url @credentials.mode == "production" ? PRODUCTION_URL : TEST_URL end
Build xml Fedex
Web Service request Implemented by each subclass
# File lib/fedex/request/base.rb, line 342 def build_xml raise NotImplementedError, "Override build_xml in subclass" end
Build xml nodes dynamically from the hash keys and values
# File lib/fedex/request/base.rb, line 347 def hash_to_xml(xml, hash) hash.each do |key, value| key_s_down = key.to_s.downcase if key_s_down.match(/^commodities_\d{1,}$/) element = 'Commodities' elsif key_s_down.match(/^masked_data_\d{1,}$/) element = 'MaskedData' else element = camelize(key) end if value.is_a?(Hash) xml.send element do |x| hash_to_xml(x, value) end elsif value.is_a?(Array) value.each do |v| xml.send element do |x| hash_to_xml(x, v) end end else xml.send element, value end end end
Parse response, convert keys to underscore symbols
# File lib/fedex/request/base.rb, line 374 def parse_response(response) response = sanitize_response_keys(response.parsed_response) end
Recursively sanitizes the response object by cleaning up any hash keys.
# File lib/fedex/request/base.rb, line 379 def sanitize_response_keys(response) if response.is_a?(Hash) response.inject({}) { |result, (key, value)| result[underscorize(key).to_sym] = sanitize_response_keys(value); result } elsif response.is_a?(Array) response.collect { |result| sanitize_response_keys(result) } else response end end
# File lib/fedex/request/base.rb, line 389 def service raise NotImplementedError, "Override service in subclass: {:id => 'service', :version => 1}" end
Use GROUND_HOME_DELIVERY for shipments going to a residential address within the US.
# File lib/fedex/request/base.rb, line 395 def service_type if @recipient[:residential].to_s =~ /true/i and @service_type =~ /GROUND/i and @recipient[:country_code] =~ /US/i "GROUND_HOME_DELIVERY" else @service_type end end
Successful request
# File lib/fedex/request/base.rb, line 404 def success?(response) (!response[:rate_reply].nil? and %w{SUCCESS WARNING NOTE}.include? response[:rate_reply][:highest_severity]) end