Class: FriendlyShipping::Services::Ups

Inherits:
Object
  • Object
show all
Includes:
Dry::Monads::Result::Mixin
Defined in:
lib/friendly_shipping/services/ups/label_options.rb,
lib/friendly_shipping/services/ups.rb,
lib/friendly_shipping/services/ups/label.rb,
lib/friendly_shipping/services/ups/timing_options.rb,
lib/friendly_shipping/services/ups/shipping_methods.rb,
lib/friendly_shipping/services/ups/label_item_options.rb,
lib/friendly_shipping/services/ups/parse_xml_response.rb,
lib/friendly_shipping/services/ups/parse_money_element.rb,
lib/friendly_shipping/services/ups/parse_rate_response.rb,
lib/friendly_shipping/services/ups/label_billing_options.rb,
lib/friendly_shipping/services/ups/label_package_options.rb,
lib/friendly_shipping/services/ups/rate_estimate_options.rb,
lib/friendly_shipping/services/ups/parse_modifier_element.rb,
lib/friendly_shipping/services/ups/serialize_package_node.rb,
lib/friendly_shipping/services/ups/serialize_access_request.rb,
lib/friendly_shipping/services/ups/serialize_address_snippet.rb,
lib/friendly_shipping/services/ups/parse_void_shipment_response.rb,
lib/friendly_shipping/services/ups/rate_estimate_package_options.rb,
lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb,
lib/friendly_shipping/services/ups/parse_time_in_transit_response.rb,
lib/friendly_shipping/services/ups/parse_shipment_confirm_response.rb,
lib/friendly_shipping/services/ups/serialize_void_shipment_request.rb,
lib/friendly_shipping/services/ups/parse_city_state_lookup_response.rb,
lib/friendly_shipping/services/ups/parse_address_validation_response.rb,
lib/friendly_shipping/services/ups/serialize_shipment_accept_request.rb,
lib/friendly_shipping/services/ups/serialize_time_in_transit_request.rb,
lib/friendly_shipping/services/ups/serialize_shipment_address_snippet.rb,
lib/friendly_shipping/services/ups/serialize_shipment_confirm_request.rb,
lib/friendly_shipping/services/ups/serialize_city_state_lookup_request.rb,
lib/friendly_shipping/services/ups/serialize_address_validation_request.rb,
lib/friendly_shipping/services/ups/parse_address_classification_response.rb,
lib/friendly_shipping/services/ups/serialize_rating_service_selection_request.rb

Overview

Option container for rating a shipment via UPS

Required:

Optional:

Defined Under Namespace

Classes: Label, LabelBillingOptions, LabelItemOptions, LabelOptions, LabelPackageOptions, ParseAddressClassificationResponse, ParseAddressValidationResponse, ParseCityStateLookupResponse, ParseModifierElement, ParseMoneyElement, ParseRateResponse, ParseShipmentAcceptResponse, ParseShipmentConfirmResponse, ParseTimeInTransitResponse, ParseVoidShipmentResponse, ParseXMLResponse, RateEstimateOptions, RateEstimatePackageOptions, SerializeAccessRequest, SerializeAddressSnippet, SerializeAddressValidationRequest, SerializeCityStateLookupRequest, SerializePackageNode, SerializeRatingServiceSelectionRequest, SerializeShipmentAcceptRequest, SerializeShipmentAddressSnippet, SerializeShipmentConfirmRequest, SerializeTimeInTransitRequest, SerializeVoidShipmentRequest, TimingOptions

Constant Summary collapse

CARRIER =
FriendlyShipping::Carrier.new(
  id: 'ups',
  name: 'United Parcel Service',
  code: 'ups',
  shipping_methods: SHIPPING_METHODS
)
TEST_URL =
'https://wwwcie.ups.com'
LIVE_URL =
'https://onlinetools.ups.com'
RESOURCES =
{
  address_validation: '/ups.app/xml/XAV',
  city_state_lookup: '/ups.app/xml/AV',
  rates: '/ups.app/xml/Rate',
  ship_confirm: '/ups.app/xml/ShipConfirm',
  ship_accept: '/ups.app/xml/ShipAccept',
  timings: '/ups.app/xml/TimeInTransit',
  void: '/ups.app/xml/Void',
}.freeze
EU_COUNTRIES =
%w(
  AT BE BG CY CZ DE DK EE ES FI FR GB GR HR HU IE IT LT LU LV MT NL PL PT RO SE SI SK
).map { |country_code| Carmen::Country.coded(country_code) }
SHIPPING_METHODS =
[
  ['US', 'international', 'UPS Standard', '11'],
  ['US', 'international', 'UPS Worldwide Express', '07'],
  ['US', 'international', 'UPS Worldwide Expedited', '08'],
  ['US', 'international', 'UPS Worldwide Express Plus', '54'],
  ['US', 'international', 'UPS Worldwide Saver', '65'],
  ['US', 'domestic', 'UPS 2nd Day Air', '02'],
  ['US', 'domestic', 'UPS 2nd Day Air A.M.', '59'],
  ['US', 'domestic', 'UPS 3 Day Select', '12'],
  ['US', 'domestic', 'UPS Ground', '03'],
  ['US', 'domestic', 'UPS Next Day Air', '01'],
  ['US', 'domestic', 'UPS Next Day Air Early', '14'],
  ['US', 'domestic', 'UPS Next Day Air Saver', '13'],
  ['US', 'domestic', 'UPS SurePost Less than 1LB', '92'],
  ['US', 'domestic', 'UPS SurePost 1LB or greater', '93'],
  ['US', 'domestic', 'UPS SurePost BPM', '94'],
  ['US', 'domestic', 'UPS SurePost Media Mail', '95'],
  ['CA', 'domestic', 'UPS Expedited Canadian domestic shipments', '02'],
  ['CA', 'domestic', 'UPS Express Saver Canadian domestic shipments', '13'],
  ['CA', 'domestic', 'UPS 3 Day Select Shipments originating in Canada to CA and US 48', '12'],
  ['CA', 'international', 'UPS 3 Day Select Shipments originating in Canada to CA and US 48', '12'],
  ['CA', 'domestic', 'UPS Access Point Economy Canadian domestic shipments', '70'],
  ['CA', 'domestic', 'UPS Express Canadian domestic shipments', '01'],
  ['CA', 'domestic', 'UPS Express Early Canadian domestic shipments', '14'],
  ['CA', 'international', 'UPS Express Saver International shipments originating in Canada', '65'],
  ['CA', 'international', 'UPS Standard Shipments originating in Canada (Domestic and Int’l)', '11'],
  ['CA', 'domestic', 'UPS Standard Shipments originating in Canada (Domestic and Int’l)', '11'],
  ['CA', 'international', 'UPS Worldwide Expedited International shipments originating in Canada', '08'],
  ['CA', 'international', 'UPS Worldwide Express International shipments originating in Canada', '07'],
  ['CA', 'international', 'UPS Worldwide Express Plus International shipments originating in Canada', '54'],
  ['CA', 'international', 'UPS Express Early Shipments originating in Canada to CA and US 48', '54'],
  ['CA', 'domestic', 'UPS Express Early Shipments originating in Canada to CA and US 48', '54'],
  ['EU', 'domestic', 'UPS Access Point Economy Shipments within the European Union', '70'],
  ['EU', 'international', 'UPS Expedited Shipments originating in the European Union', '08'],
  ['EU', 'international', 'UPS Express Shipments originating in the European Union', '07'],
  ['EU', 'international', 'UPS Standard Shipments originating in the European Union', '11'],
  ['EU', 'international', 'UPS Worldwide Express Plus Shipments originating in the European Union', '54'],
  ['EU', 'international', 'UPS Worldwide Saver Shipments originating in the European Union', '65'],
  ['MX', 'domestic', 'UPS Access Point Economy Shipments within Mexico', '70'],
  ['MX', 'international', 'UPS Expedited Shipments originating in Mexico', '08'],
  ['MX', 'international', 'UPS Express Shipments originating in Mexico', '07'],
  ['MX', 'international', 'UPS Standard Shipments originating in Mexico', '11'],
  ['MX', 'international', 'UPS Worldwide Express Plus Shipments originating in Mexico', '54'],
  ['MX', 'international', 'UPS Worldwide Saver Shipments originating in Mexico', '65'],
  ['PL', 'domestic', 'UPS Access Point Economy Polish domestic shipments', '70'],
  ['PL', 'domestic', 'UPS Today Dedicated Courier Polish domestic shipments', '83'],
  ['PL', 'domestic', 'UPS Today Express Polish domestic shipments', '85'],
  ['PL', 'domestic', 'UPS Today Express Saver Polish domestic shipments', '86'],
  ['PL', 'domestic', 'UPS Today Standard Polish domestic shipments', '82'],
  ['PL', 'international', 'UPS Expedited Shipments originating in Poland', '08'],
  ['PL', 'international', 'UPS Express Shipments originating in Poland', '07'],
  ['PL', 'international', 'UPS Express Plus Shipments originating in Poland', '54'],
  ['PL', 'international', 'UPS Express Saver Shipments originating in Poland', '65'],
  ['PL', 'international', 'UPS Standard Shipments originating in Poland', '11'],
  ['PR', 'domestic', 'UPS 2nd Day Air', '02'],
  ['PR', 'domestic', 'UPS Ground', '03'],
  ['PR', 'domestic', 'UPS Next Day Air', '01'],
  ['PR', 'domestic', 'UPS Next Day Air Early', '14'],
  ['PR', 'international', 'UPS Worldwide Expedited', '08'],
  ['PR', 'international', 'UPS Worldwide Express', '07'],
  ['PR', 'international', 'UPS Worldwide Express Plus', '54'],
  ['PR', 'international', 'UPS Worldwide Saver', '65'],
  ['DE', 'domestic', 'UPS Express 12:00 German domestic shipments', '74'],
  ['OTHER', 'domestic', 'UPS Express', '07'],
  ['OTHER', 'domestic', 'UPS Standard', '11'],
  ['OTHER', 'international', 'UPS Worldwide Expedited', '08'],
  ['OTHER', 'international', 'UPS Worldwide Express Plus', '54'],
  ['OTHER', 'international', 'UPS Worldwide Saver', '65'],
  ['ALL', 'international', 'UPS Worldwide Express Freight', '96'],
  ['ALL', 'international', 'UPS Worldwide Express Freight Midday', '71']
].freeze.map do |origin_country_code, dom_or_intl, name, code|
  FriendlyShipping::ShippingMethod.new(
    name: name,
    service_code: code,
    domestic: dom_or_intl == 'domestic',
    international: dom_or_intl == 'international',
    origin_countries: countries_by_code(origin_country_code),
    multi_package: true
  ).freeze
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key:, login:, password:, test: true, client: HttpClient.new) ⇒ Ups

Returns a new instance of Ups.



32
33
34
35
36
37
38
# File 'lib/friendly_shipping/services/ups.rb', line 32

def initialize(key:, login:, password:, test: true, client: HttpClient.new)
  @key = key
  @login = 
  @password = password
  @test = test
  @client = client
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



10
11
12
# File 'lib/friendly_shipping/services/ups.rb', line 10

def client
  @client
end

#keyObject (readonly)

Returns the value of attribute key.



10
11
12
# File 'lib/friendly_shipping/services/ups.rb', line 10

def key
  @key
end

#loginObject (readonly)

Returns the value of attribute login.



10
11
12
# File 'lib/friendly_shipping/services/ups.rb', line 10

def 
  @login
end

#passwordObject (readonly)

Returns the value of attribute password.



10
11
12
# File 'lib/friendly_shipping/services/ups.rb', line 10

def password
  @password
end

#testObject (readonly)

Returns the value of attribute test.



10
11
12
# File 'lib/friendly_shipping/services/ups.rb', line 10

def test
  @test
end

Instance Method Details

#address_classification(location, debug: false) ⇒ Result<ApiResult<String>>

Classify an address.

Parameters:

  • location (Physical::Location)

    The address we want to classify

Returns:

  • (Result<ApiResult<String>>)

    Either "commercial", "residential", or "unknown"



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/friendly_shipping/services/ups.rb', line 156

def address_classification(location, debug: false)
  address_validation_request_xml = SerializeAddressValidationRequest.call(location: location)
  url = base_url + RESOURCES[:address_validation]
  request = FriendlyShipping::Request.new(
    url: url,
    http_method: "POST",
    body: access_request_xml + address_validation_request_xml,
    readable_body: address_validation_request_xml,
    debug: debug
  )

  client.post(request).bind do |response|
    ParseAddressClassificationResponse.call(response: response, request: request)
  end
end

#address_validation(location, debug: false) ⇒ Result<ApiResult<Array<Physical::Location>>>

Validate an address.

Parameters:

  • location (Physical::Location)

    The address we want to verify

Returns:

  • (Result<ApiResult<Array<Physical::Location>>>)

    The response data from UPS encoded in a Physical::Location object. Name and Company name are always nil, the address lines will be made conformant to what UPS considers right. The returned location will have the address_type set if possible.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/friendly_shipping/services/ups.rb', line 137

def address_validation(location, debug: false)
  address_validation_request_xml = SerializeAddressValidationRequest.call(location: location)
  url = base_url + RESOURCES[:address_validation]
  request = FriendlyShipping::Request.new(
    url: url,
    http_method: "POST",
    body: access_request_xml + address_validation_request_xml,
    readable_body: address_validation_request_xml,
    debug: debug
  )

  client.post(request).bind do |response|
    ParseAddressValidationResponse.call(response: response, request: request)
  end
end

#carriersObject



40
41
42
# File 'lib/friendly_shipping/services/ups.rb', line 40

def carriers
  Success([CARRIER])
end

#city_state_lookup(location, debug: false) ⇒ Result<ApiResult<Array<Physical::Location>>>

Find city and state for a given ZIP code

Parameters:

  • location (Physical::Location)

    A location object with country and ZIP code set

Returns:

  • (Result<ApiResult<Array<Physical::Location>>>)

    The response data from UPS encoded in a Physical::Location object. Country, City and ZIP code will be set, everything else nil.



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/friendly_shipping/services/ups.rb', line 176

def city_state_lookup(location, debug: false)
  city_state_lookup_request_xml = SerializeCityStateLookupRequest.call(location: location)
  url = base_url + RESOURCES[:city_state_lookup]
  request = FriendlyShipping::Request.new(
    url: url,
    http_method: "POST",
    body: access_request_xml + city_state_lookup_request_xml,
    readable_body: city_state_lookup_request_xml,
    debug: debug
  )

  client.post(request).bind do |response|
    ParseCityStateLookupResponse.call(response: response, request: request, location: location)
  end
end

#labels(shipment, options:, debug: false) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/friendly_shipping/services/ups.rb', line 89

def labels(shipment, options:, debug: false)
  ## Method body starts
  ship_confirm_request_xml = SerializeShipmentConfirmRequest.call(
    shipment: shipment,
    options: options
  )
  ship_confirm_url = base_url + RESOURCES[:ship_confirm]

  ship_confirm_request = FriendlyShipping::Request.new(
    url: ship_confirm_url,
    http_method: "POST",
    body: access_request_xml + ship_confirm_request_xml,
    readable_body: ship_confirm_request_xml,
    debug: debug
  )

  client.post(ship_confirm_request).bind do |ship_confirm_response|
    ParseShipmentConfirmResponse.call(
      request: ship_confirm_request,
      response: ship_confirm_response
    )
  end.bind do |ship_confirm_result|
    ship_accept_url = base_url + RESOURCES[:ship_accept]
    ship_accept_request_xml = SerializeShipmentAcceptRequest.call(
      digest: ship_confirm_result.data,
      options: options
    )

    ship_accept_request = FriendlyShipping::Request.new(
      url: ship_accept_url,
      http_method: "POST",
      body: access_request_xml + ship_accept_request_xml,
      readable_body: ship_accept_request_xml,
      debug: debug
    )

    client.post(ship_accept_request).bind do |ship_accept_response|
      ParseShipmentAcceptResponse.call(request: ship_accept_request, response: ship_accept_response)
    end
  end
end

#rate_estimates(shipment, options:, debug: false) ⇒ Result<ApiResult<Array<Rate>>>

Get rates for a shipment

Parameters:

Returns:

  • (Result<ApiResult<Array<Rate>>>)

    The rates returned from UPS encoded in a FriendlyShipping::ApiResult object.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/friendly_shipping/services/ups.rb', line 50

def rate_estimates(shipment, options:, debug: false)
  rate_request_xml = SerializeRatingServiceSelectionRequest.call(shipment: shipment, options: options)
  url = base_url + RESOURCES[:rates]
  request = FriendlyShipping::Request.new(
    url: url,
    http_method: "POST",
    body: access_request_xml + rate_request_xml,
    readable_body: rate_request_xml,
    debug: debug
  )

  client.post(request).bind do |response|
    ParseRateResponse.call(response: response, request: request, shipment: shipment)
  end
end

#timings(shipment, options:, debug: false) ⇒ Object

Get timing information for a shipment

Parameters:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/friendly_shipping/services/ups.rb', line 69

def timings(shipment, options:, debug: false)
  time_in_transit_request_xml = SerializeTimeInTransitRequest.call(
    shipment: shipment,
    options: options
  )
  time_in_transit_url = base_url + RESOURCES[:timings]

  request = FriendlyShipping::Request.new(
    url: time_in_transit_url,
    http_method: "POST",
    body: access_request_xml + time_in_transit_request_xml,
    readable_body: time_in_transit_request_xml,
    debug: debug
  )

  client.post(request).bind do |response|
    ParseTimeInTransitResponse.call(response: response, request: request)
  end
end

#void(label, debug: false) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/friendly_shipping/services/ups.rb', line 192

def void(label, debug: false)
  url = base_url + RESOURCES[:void]
  void_request_xml = SerializeVoidShipmentRequest.call(label: label)
  request = FriendlyShipping::Request.new(
    url: url,
    http_method: "POST",
    body: access_request_xml + void_request_xml,
    readable_body: void_request_xml,
    debug: debug
  )
  client.post(request).bind do |response|
    ParseVoidShipmentResponse.call(request: request, response: response)
  end
end