class ReactiveShipping::CanadaPost
Constants
- Box
- DTD_NAME
- DTD_URI
- NON_ISO_COUNTRY_NAMES
- PackedItem
- PostalOutlet
- RESPONSE_CODES
- URL
Public Class Methods
default_location()
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 97 def self.default_location { :country => 'CA', :province => 'ON', :city => 'Ottawa', :address1 => '61A York St', :postal_code => 'K1N5T2' } end
Public Instance Methods
find_rates(origin, destination, line_items = [], options = {})
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 83 def find_rates(origin, destination, line_items = [], options = {}) rate_request = build_rate_request(origin, destination, line_items, options) commit(rate_request, origin, destination, options) end
maximum_address_field_length()
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 92 def maximum_address_field_length # https://www.canadapost.ca/cpo/mc/business/productsservices/developers/services/shippingmanifest/createshipment.jsf 44 end
maximum_weight()
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 88 def maximum_weight Measured::Weight.new(30, :kg) end
requirements()
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 79 def requirements [:login] end
Protected Instance Methods
commit(request, origin, destination, options = {})
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 109 def commit(request, origin, destination, options = {}) parse_rate_response(ssl_post(URL, request), origin, destination, options) end
Private Instance Methods
build_line_items(xml, line_items)
click to toggle source
<!– List of items in the shopping –> <!– cart –> <!– Each item is defined by : –> <!– - quantity (mandatory) –> <!– - size (mandatory) –> <!– - weight (mandatory) –> <!– - description (mandatory) –> <!– - ready to ship (optional) –>
# File lib/reactive_shipping/carriers/canada_post.rb, line 238 def build_line_items(xml, line_items) xml.lineItems do line_items.each do |line_item| xml.item do xml.quantity(1) xml.weight(line_item.kilograms) xml.length(line_item.cm(:length).to_s) xml.width(line_item.cm(:width).to_s) xml.height(line_item.cm(:height).to_s) xml.description(line_item.options[:description] || ' ') xml.readyToShip(line_item.options[:ready_to_ship] || nil) # By setting the 'readyToShip' tag to true, Sell Online will not pack this item in the boxes defined in the merchant profile. end end end end
build_rate_request(origin, destination, line_items = [], options = {})
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 123 def build_rate_request(origin, destination, line_items = [], options = {}) line_items = [line_items] unless line_items.is_a?(Array) origin = origin.is_a?(Location) ? origin : Location.new(origin) destination = destination.is_a?(Location) ? destination : Location.new(destination) generate_xml do |xml| xml.eparcel do xml.language(@options[:french] ? 'fr' : 'en') xml.ratesAndServicesRequest do xml.merchantCPCID(@options[:login]) xml.fromPostalCode(origin.postal_code) xml.turnAroundTime(options[:turn_around_time]) if options[:turn_around_time] xml.itemsPrice(dollar_amount(line_items.map(&:value).compact.sum)) build_line_items(xml, line_items) xml.city(destination.city) xml.provOrState(destination.province) xml.country(handle_non_iso_country_names(destination.country)) xml.postalCode(destination.postal_code) end end end end
dollar_amount(cents)
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 255 def dollar_amount(cents) "%0.2f" % (cents / 100.0) end
generate_xml() { |xml| ... }
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 115 def generate_xml(&block) builder = Nokogiri::XML::Builder.new do |xml| xml.doc.create_internal_subset(DTD_NAME, nil, DTD_URI) yield(xml) end builder.to_xml end
handle_non_iso_country_names(country)
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 259 def handle_non_iso_country_names(country) NON_ISO_COUNTRY_NAMES[country.to_s] || country end
parse_rate_response(response, origin, destination, options = {})
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 148 def parse_rate_response(response, origin, destination, options = {}) xml = Nokogiri.XML(response) success = response_success?(xml) message = response_message(xml) rate_estimates = [] boxes = [] if success xml.xpath('eparcel/ratesAndServicesResponse/product').each do |product| service_name = (@options[:french] ? @@name_french : @@name) + " " + product.at('name').text service_code = product['id'] rate_estimates << RateEstimate.new(origin, destination, @@name, service_name, :service_code => service_code, :total_price => product.at('rate').text, :currency => 'CAD', :shipping_date => product.at('shippingDate').text, :delivery_range => [product.at('deliveryDate').text] * 2 ) end boxes = xml.xpath('eparcel/ratesAndServicesResponse/packing/box').map do |box| b = Box.new b.packedItems = [] b.name = box.at('name').text b.weight = box.at('weight').text.to_f b.expediter_weight = box.at('expediterWeight').text.to_f b.length = box.at('length').text.to_f b.width = box.at('width').text.to_f b.height = box.at('height').text.to_f b.packedItems = box.xpath('packedItem').map do |item| p = PackedItem.new p.quantity = item.at('quantity').text.to_i p.description = item.at('description').text p end b end postal_outlets = xml.xpath('eparcel/ratesAndServicesResponse/nearestPostalOutlet').map do |outlet| postal_outlet = PostalOutlet.new postal_outlet.sequence_no = outlet.at('postalOutletSequenceNo').text postal_outlet.distance = outlet.at('distance').text postal_outlet.name = outlet.at('outletName').text postal_outlet.business_name = outlet.at('businessName').text postal_outlet.postal_address = Location.new( :address1 => outlet.at('postalAddress/addressLine').text, :postal_code => outlet.at('postalAddress/postal_code').text, :city => outlet.at('postalAddress/municipality').text, :province => outlet.at('postalAddress/province').text, :country => 'Canada', :phone_number => outlet.at('phoneNumber').text ) postal_outlet.business_hours = outlet.elements.collect('businessHours') do |hour| { :day_of_week => hour.at('dayOfWeek').text, :time => hour.at('time').text } end postal_outlet end end CanadaPostRateResponse.new(success, message, Hash.from_xml(response), :rates => rate_estimates, :xml => response, :boxes => boxes, :postal_outlets => postal_outlets) end
response_message(xml)
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 221 def response_message(xml) if response_success?(xml) xml.at('eparcel/ratesAndServicesResponse/statusMessage').text else xml.at('eparcel/error/statusMessage').text end end
response_success?(xml)
click to toggle source
# File lib/reactive_shipping/carriers/canada_post.rb, line 214 def response_success?(xml) return false unless xml.at('eparcel/error').nil? value = xml.at('eparcel/ratesAndServicesResponse/statusCode').text value == '1' || value == '2' end