Class: Shipping::AmazonSeller
- Defined in:
- app/services/shipping/amazon_seller.rb
Overview
Shipping carrier class for Amazon Buy Shipping API
Provides Amazon's negotiated carrier rates with A-to-Z Buy Shipping protections
This class follows the same interface as other Shipping::* carriers
(specifically mirroring Shipping::WalmartSeller) and integrates with
the WyShipping rate comparison system.
Usage:
shipper = Shipping::AmazonSeller.new(
amazon_partner: :amazon_seller_central_us,
amazon_order_id: '111-2222222-3333333',
sender_address: '123 Warehouse St',
# ... other address fields
)
response = shipper.find_rates
if response[:success]
response[:rates].each { |rate| puts rate[:service_name] }
end
Constant Summary collapse
- CARRIER_NAME =
'AmazonSeller'- SERVICE_CODE_PREFIX =
Service code prefix to distinguish Amazon Buy Shipping rates from direct carrier rates
'AMZBS_'
Instance Attribute Summary collapse
-
#amazon_order_id ⇒ Object
Returns the value of attribute amazon_order_id.
-
#amazon_partner ⇒ Object
Returns the value of attribute amazon_partner.
-
#api_log ⇒ Object
readonly
Accumulated API call log from all Amazon Buy Shipping operations on this shipper instance.
-
#deliver_by_date ⇒ Object
Returns the value of attribute deliver_by_date.
-
#ship_by_date ⇒ Object
Returns the value of attribute ship_by_date.
Attributes inherited from Base
#address, #address2, #address3, #address_residential, #attention_name, #billing_account, #billing_country, #billing_zip, #ci_comments, #city, #close_report_only, #cod_amount, #cod_collection_type, #company, #country, #currency_code, #data, #debug, #declared_value, #delivery_instructions, #delivery_total_value, #description, #discount_price, #dropoff_type, #email, #eta, #export_reason, #freight_class, #freightquote_authorization_url, #freightquote_client_id, #freightquote_client_secret, #freightquote_customer_code, #freightquote_events_url, #freightquote_rating_url, #freightquote_shipping_url, #freightquote_voiding_url, #handling_instructions, #has_loading_dock, #image_type, #include_first_class_mail_options, #insured_value, #is_construction_site, #is_trade_show, #label_type, #limited_access, #line_items, #master_tracking_number, #measure_height, #measure_length, #measure_units, #measure_width, #media_mail, #multiple_piece_shipping, #negotiated_rates, #package, #package_count, #package_sequence_number, #package_total, #packages, #packaging_type, #pay_type, #phone, #pickup_datetime, #pickup_instructions, #plain_response, #price, #rate_data, #reference_number_1, #reference_number_2, #reference_number_3, #reference_number_code_1, #reference_number_code_2, #required, #requires_appointment, #requires_inside_delivery, #requires_liftgate, #response, #return_to_address, #return_to_address2, #return_to_address3, #return_to_address_residential, #return_to_attention_name, #return_to_city, #return_to_company, #return_to_country, #return_to_email, #return_to_has_loading_dock, #return_to_is_construction_site, #return_to_is_trade_show, #return_to_limited_access, #return_to_name, #return_to_phone, #return_to_requires_appointment, #return_to_requires_inside_delivery, #return_to_requires_liftgate, #return_to_state, #return_to_zip, #rl_carriers_api_key, #rl_carriers_shipping_url, #saturday_delivery, #sender_address, #sender_address2, #sender_address3, #sender_address_residential, #sender_attention_name, #sender_city, #sender_company, #sender_country, #sender_email, #sender_has_loading_dock, #sender_is_construction_site, #sender_is_trade_show, #sender_limited_access, #sender_name, #sender_phone, #sender_requires_appointment, #sender_requires_inside_delivery, #sender_requires_liftgate, #sender_state, #sender_tax_identification_number, #sender_zip, #service_code, #service_type, #services, #ship_date, #shipengine_api_key, #shipengine_canadapost_account_id, #shipengine_canadapost_parent_account_number, #shipengine_canpar_account_id, #shipengine_dhl_express_account_id, #shipengine_fed_ex_account_id, #shipengine_fed_ex_ca_account_id, #shipengine_purolator_account_id, #shipengine_ups_account_id, #shipengine_ups_ca_account_id, #shipengine_usps_account_id, #shipper_address, #shipper_address2, #shipper_address3, #shipper_address_residential, #shipper_attention_name, #shipper_city, #shipper_company, #shipper_country, #shipper_email, #shipper_has_loading_dock, #shipper_is_construction_site, #shipper_is_trade_show, #shipper_limited_access, #shipper_name, #shipper_phone, #shipper_requires_appointment, #shipper_requires_inside_delivery, #shipper_requires_liftgate, #shipper_state, #shipper_zip, #signature_confirmation, #skip_png_download, #skip_rate_test, #special_instructions, #state, #tax_identification_number, #time_in_transit, #total_shipment_weight, #transaction_type, #weight, #weight_units, #zip
Instance Method Summary collapse
-
#create_label(rate, logger = nil) ⇒ Hash
Create a shipping label via Amazon Buy Shipping.
-
#find_rates(logger = nil) ⇒ Hash
Get shipping rate offerings from Amazon Buy Shipping.
-
#get_documents(shipment_id, package_reference_id, logger = nil) ⇒ Hash
Download label documents for a previously purchased shipment Only needed if label_data was not returned inline during purchase.
-
#initialize(options = {}) ⇒ AmazonSeller
constructor
A new instance of AmazonSeller.
-
#void_label(shipment_id, logger = nil) ⇒ Hash
Cancel/void a purchased Amazon Buy Shipping label.
Methods inherited from Base
#fedex, #purolator, state_from_zip, #ups, #ups_freight
Constructor Details
#initialize(options = {}) ⇒ AmazonSeller
Returns a new instance of AmazonSeller.
33 34 35 36 37 38 39 40 |
# File 'app/services/shipping/amazon_seller.rb', line 33 def initialize( = {}) super @amazon_partner = [:amazon_partner] @amazon_order_id = [:amazon_order_id] @deliver_by_date = [:deliver_by_date] @ship_by_date = [:ship_by_date] @api_log = [] end |
Instance Attribute Details
#amazon_order_id ⇒ Object
Returns the value of attribute amazon_order_id.
23 24 25 |
# File 'app/services/shipping/amazon_seller.rb', line 23 def amazon_order_id @amazon_order_id end |
#amazon_partner ⇒ Object
Returns the value of attribute amazon_partner.
23 24 25 |
# File 'app/services/shipping/amazon_seller.rb', line 23 def amazon_partner @amazon_partner end |
#api_log ⇒ Object (readonly)
Accumulated API call log from all Amazon Buy Shipping operations on this shipper instance
31 32 33 |
# File 'app/services/shipping/amazon_seller.rb', line 31 def api_log @api_log end |
#deliver_by_date ⇒ Object
Returns the value of attribute deliver_by_date.
23 24 25 |
# File 'app/services/shipping/amazon_seller.rb', line 23 def deliver_by_date @deliver_by_date end |
#ship_by_date ⇒ Object
Returns the value of attribute ship_by_date.
23 24 25 |
# File 'app/services/shipping/amazon_seller.rb', line 23 def ship_by_date @ship_by_date end |
Instance Method Details
#create_label(rate, logger = nil) ⇒ Hash
Create a shipping label via Amazon Buy Shipping
89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'app/services/shipping/amazon_seller.rb', line 89 def create_label(rate, logger = nil) logger ||= Rails.logger return { success: false, error: 'Amazon partner and order ID are required' } unless @amazon_partner.present? && @amazon_order_id.present? per_pkg = rate[:per_package_rates] || rate.dig(:rate_data, :per_package_rates) || rate.dig(:rate_data, 'per_package_rates') per_pkg = per_pkg&.map { |pr| pr.respond_to?(:symbolize_keys) ? pr.symbolize_keys : pr } if per_pkg.is_a?(Array) && per_pkg.size > 1 create_label_multi_package(rate, per_pkg, logger) else create_label_single(rate, logger) end end |
#find_rates(logger = nil) ⇒ Hash
Get shipping rate offerings from Amazon Buy Shipping
Amazon's GetRates API only supports 1 package per request.
For multi-package shipments, we make separate API calls per package
and aggregate the results — only services available for ALL packages
are returned, with charges summed across packages.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'app/services/shipping/amazon_seller.rb', line 50 def find_rates(logger = nil) logger ||= Rails.logger return build_error_response('Amazon partner configuration is required') unless @amazon_partner.present? return build_error_response('Amazon order ID is required') unless @amazon_order_id.present? return build_error_response('Valid origin address is required') unless valid_origin_address? begin orchestrator = Edi::Amazon::Orchestrator.new(@amazon_partner) amz_client = Edi::Amazon::ShipWithAmazon.new(orchestrator) = all_packages = [:packages] || [] logger.info("[AMZ-BS] Requesting rates for order: #{@amazon_order_id}, #{all_packages.size} package(s)") if all_packages.size <= 1 result = amz_client.get_rates() @api_log.concat(amz_client.api_log) if result.success rates = build_rate_estimates(result.rates, result.request_token) build_success_response(rates, ) else build_error_response(result.error || 'Failed to retrieve Amazon Buy Shipping rates') end else find_rates_multi_package(amz_client, , all_packages, logger) end rescue StandardError => e logger.error("[AMZ-BS] find_rates error: #{e.}") logger.error(e.backtrace.first(5).join("\n")) build_error_response("Error retrieving Amazon Buy Shipping rates: #{e.}") end end |
#get_documents(shipment_id, package_reference_id, logger = nil) ⇒ Hash
Download label documents for a previously purchased shipment
Only needed if label_data was not returned inline during purchase
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'app/services/shipping/amazon_seller.rb', line 241 def get_documents(shipment_id, package_reference_id, logger = nil) logger ||= Rails.logger return { success: false, error: 'Amazon partner configuration is required' } unless @amazon_partner.present? begin orchestrator = Edi::Amazon::Orchestrator.new(@amazon_partner) amz_client = Edi::Amazon::ShipWithAmazon.new(orchestrator) result = amz_client.get_shipment_documents(shipment_id, package_reference_id) @api_log.concat(amz_client.api_log) { success: result.success, label_data: result.label_data, format: result.format, error: result.error } rescue StandardError => e logger.error("[AMZ-BS] get_documents error: #{e.}") { success: false, error: e. } end end |
#void_label(shipment_id, logger = nil) ⇒ Hash
Cancel/void a purchased Amazon Buy Shipping label
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'app/services/shipping/amazon_seller.rb', line 216 def void_label(shipment_id, logger = nil) logger ||= Rails.logger return { success: false, error: 'Amazon partner configuration is required' } unless @amazon_partner.present? return { success: false, error: 'Shipment ID is required' } unless shipment_id.present? begin orchestrator = Edi::Amazon::Orchestrator.new(@amazon_partner) amz_client = Edi::Amazon::ShipWithAmazon.new(orchestrator) result = amz_client.cancel_shipment(shipment_id) @api_log.concat(amz_client.api_log) { success: result.success, error: result.error } rescue StandardError => e logger.error("[AMZ-BS] void_label error: #{e.}") { success: false, error: e. } end end |