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.



54
55
56
57
58
59
60
# File 'lib/friendly_shipping/services/ups.rb', line 54

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.



32
33
34
# File 'lib/friendly_shipping/services/ups.rb', line 32

def client
  @client
end

#keyObject (readonly)

Returns the value of attribute key.



32
33
34
# File 'lib/friendly_shipping/services/ups.rb', line 32

def key
  @key
end

#loginObject (readonly)

Returns the value of attribute login.



32
33
34
# File 'lib/friendly_shipping/services/ups.rb', line 32

def 
  @login
end

#passwordObject (readonly)

Returns the value of attribute password.



32
33
34
# File 'lib/friendly_shipping/services/ups.rb', line 32

def password
  @password
end

#testObject (readonly)

Returns the value of attribute test.



32
33
34
# File 'lib/friendly_shipping/services/ups.rb', line 32

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"



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

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.



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

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



62
63
64
# File 'lib/friendly_shipping/services/ups.rb', line 62

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.



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/friendly_shipping/services/ups.rb', line 198

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



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/friendly_shipping/services/ups.rb', line 111

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.



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

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:



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/friendly_shipping/services/ups.rb', line 91

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



214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/friendly_shipping/services/ups.rb', line 214

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