friendly_shipping 0.5.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop-relaxed.yml +3 -4
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +32 -1
- data/friendly_shipping.gemspec +12 -12
- data/lib/friendly_shipping/api_failure.rb +2 -15
- data/lib/friendly_shipping/http_client.rb +16 -9
- data/lib/friendly_shipping/services/ship_engine/bad_request_handler.rb +15 -3
- data/lib/friendly_shipping/services/ups/parse_address_classification_response.rb +5 -2
- data/lib/friendly_shipping/services/ups/parse_address_validation_response.rb +5 -2
- data/lib/friendly_shipping/services/ups/parse_city_state_lookup_response.rb +5 -2
- data/lib/friendly_shipping/services/ups/parse_money_element.rb +2 -2
- data/lib/friendly_shipping/services/ups/parse_rate_response.rb +5 -1
- data/lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb +5 -1
- data/lib/friendly_shipping/services/ups/parse_shipment_confirm_response.rb +5 -1
- data/lib/friendly_shipping/services/ups/parse_time_in_transit_response.rb +6 -2
- data/lib/friendly_shipping/services/ups/parse_void_shipment_response.rb +5 -1
- data/lib/friendly_shipping/services/ups/parse_xml_response.rb +16 -7
- data/lib/friendly_shipping/services/ups_freight.rb +44 -13
- data/lib/friendly_shipping/services/ups_freight/generate_delivery_options_hash.rb +21 -0
- data/lib/friendly_shipping/services/ups_freight/generate_document_options_hash.rb +28 -0
- data/lib/friendly_shipping/services/ups_freight/generate_email_options_hash.rb +25 -0
- data/lib/friendly_shipping/services/ups_freight/generate_freight_rate_request_hash.rb +2 -10
- data/lib/friendly_shipping/services/ups_freight/generate_freight_ship_request_hash.rb +81 -0
- data/lib/friendly_shipping/services/ups_freight/generate_location_hash.rb +5 -2
- data/lib/friendly_shipping/services/ups_freight/generate_pickup_options_hash.rb +21 -0
- data/lib/friendly_shipping/services/ups_freight/generate_pickup_request_hash.rb +31 -0
- data/lib/friendly_shipping/services/ups_freight/label_delivery_options.rb +29 -0
- data/lib/friendly_shipping/services/ups_freight/label_document_options.rb +56 -0
- data/lib/friendly_shipping/services/ups_freight/label_email_options.rb +40 -0
- data/lib/friendly_shipping/services/ups_freight/label_item_options.rb +10 -0
- data/lib/friendly_shipping/services/ups_freight/label_options.rb +37 -0
- data/lib/friendly_shipping/services/ups_freight/label_package_options.rb +10 -0
- data/lib/friendly_shipping/services/ups_freight/label_pickup_options.rb +29 -0
- data/lib/friendly_shipping/services/ups_freight/parse_freight_label_response.rb +57 -0
- data/lib/friendly_shipping/services/ups_freight/parse_freight_rate_response.rb +29 -32
- data/lib/friendly_shipping/services/ups_freight/parse_shipment_document.rb +24 -0
- data/lib/friendly_shipping/services/ups_freight/pickup_request_options.rb +29 -0
- data/lib/friendly_shipping/services/ups_freight/rates_options.rb +3 -6
- data/lib/friendly_shipping/services/ups_freight/restful_api_error_handler.rb +30 -0
- data/lib/friendly_shipping/services/ups_freight/shipment_document.rb +21 -0
- data/lib/friendly_shipping/services/ups_freight/shipment_information.rb +35 -0
- data/lib/friendly_shipping/services/usps/parse_address_validation_response.rb +5 -1
- data/lib/friendly_shipping/services/usps/parse_city_state_lookup_response.rb +5 -1
- data/lib/friendly_shipping/services/usps/parse_package_rate.rb +25 -15
- data/lib/friendly_shipping/services/usps/parse_rate_response.rb +5 -2
- data/lib/friendly_shipping/services/usps/parse_time_in_transit_response.rb +6 -2
- data/lib/friendly_shipping/services/usps/parse_xml_response.rb +15 -5
- data/lib/friendly_shipping/services/usps/rate_estimate_package_options.rb +7 -5
- data/lib/friendly_shipping/services/usps/shipping_methods.rb +23 -12
- data/lib/friendly_shipping/shipping_method.rb +5 -2
- data/lib/friendly_shipping/version.rb +1 -1
- metadata +75 -40
- data/lib/friendly_shipping/services/ups_freight/generate_ups_security_hash.rb +0 -23
- data/lib/friendly_shipping/services/ups_freight/parse_json_response.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff4df4b78d4b922cd7f2c08ad8256c828783be946fdbd1ba551a5ec562f3176f
|
4
|
+
data.tar.gz: 472c8ef33c9e0b581fe582f630daf04033719c5c90ba2f7ac0a2194a6aed1f20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89fd85041a4800344354421548d197e642a4812e0e9af04d9bcc45f663e704506bff9b9901708a1ff452309e991a83134b84d88e945e5f8627dc5e776bdd5910
|
7
|
+
data.tar.gz: 872f43aea4c769fde901b47fa67e39e90b089cd5d10e3fccf28317b81dab234bb56c10590b00c930e7c50de358baa903c7ce3e383f52c4dbe867af54a42c18ae
|
data/.gitignore
CHANGED
data/.rubocop-relaxed.yml
CHANGED
@@ -133,6 +133,9 @@ Style/WordArray:
|
|
133
133
|
Enabled: false
|
134
134
|
StyleGuide: https://relaxed.ruby.style/#stylewordarray
|
135
135
|
|
136
|
+
Layout/LineLength:
|
137
|
+
Enabled: false
|
138
|
+
|
136
139
|
Lint/AmbiguousRegexpLiteral:
|
137
140
|
Enabled: false
|
138
141
|
StyleGuide: https://relaxed.ruby.style/#lintambiguousregexpliteral
|
@@ -156,9 +159,6 @@ Metrics/ModuleLength:
|
|
156
159
|
Metrics/CyclomaticComplexity:
|
157
160
|
Enabled: false
|
158
161
|
|
159
|
-
Metrics/LineLength:
|
160
|
-
Enabled: false
|
161
|
-
|
162
162
|
Metrics/MethodLength:
|
163
163
|
Enabled: false
|
164
164
|
|
@@ -167,4 +167,3 @@ Metrics/ParameterLists:
|
|
167
167
|
|
168
168
|
Metrics/PerceivedComplexity:
|
169
169
|
Enabled: false
|
170
|
-
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,37 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [0.6.3] - 2020-10-30
|
8
|
+
|
9
|
+
### Added
|
10
|
+
|
11
|
+
- USPS Service: Append HFP (Hold For Pickup) to service code when necessary (#110)
|
12
|
+
- USPS Service: Add Priority Cubic shipping method (#113)
|
13
|
+
|
14
|
+
### Changed
|
15
|
+
|
16
|
+
- USPS Service: Refactor to use explicit service codes (#111)
|
17
|
+
- USPS Service: Match Priority Express by CLASSID instead of service name (#112)
|
18
|
+
- UPS Service: Rename peak surcharge keys to match UPS docs (#114)
|
19
|
+
|
20
|
+
## [0.6.2] - 2020-08-12
|
21
|
+
|
22
|
+
- UPS Service: Be more resilient when UPS does not send a PickupTime element
|
23
|
+
|
24
|
+
## [0.6.1] - 2020-03-11
|
25
|
+
|
26
|
+
- Add Content-Type header to UPS Freight API requests, fixing "Name too long" 500 error responses
|
27
|
+
|
28
|
+
## [0.6.0] - 2020-03-11
|
29
|
+
|
30
|
+
- Changelog additions missed in previous release
|
31
|
+
|
32
|
+
## [0.5.3] - 2020-03-11
|
33
|
+
|
34
|
+
- UPS Service: Add support for shipping labels / bills of lading (#92)
|
35
|
+
- UPS/USPS Services: Return ApiFailure instead of a string for failed API responses (#95)
|
36
|
+
- UPS/USPS Services: Refactor ApiFailure to subclass ApiResponse (#96)
|
37
|
+
|
7
38
|
## [0.5.2] - 2020-01-31
|
8
39
|
|
9
40
|
### Added
|
@@ -17,7 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
17
48
|
|
18
49
|
### Changed
|
19
50
|
- USPS Service: Rename "Package Services" shipping method (#85)
|
20
|
-
- Documentation updates (#86)
|
51
|
+
- Documentation updates (#86)
|
21
52
|
|
22
53
|
## [0.5] - 2020-01-24
|
23
54
|
|
data/friendly_shipping.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
|
13
13
|
spec.summary = "An integration layer for shipping services"
|
14
14
|
spec.description = "Allows you to quote or ship a Physical::Shipment object"
|
15
|
-
spec.homepage = "https://github.com/
|
15
|
+
spec.homepage = "https://github.com/friendlycart/friendly_shipping"
|
16
16
|
spec.license = "MIT"
|
17
17
|
|
18
18
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
@@ -24,21 +24,21 @@ Gem::Specification.new do |spec|
|
|
24
24
|
|
25
25
|
spec.add_runtime_dependency "data_uri", "~> 0.0.3"
|
26
26
|
spec.add_runtime_dependency "dry-monads", "~> 1.0"
|
27
|
-
spec.add_runtime_dependency "money", "
|
28
|
-
spec.add_runtime_dependency "nokogiri", "
|
29
|
-
spec.add_runtime_dependency "physical", ">= 0.4.4"
|
27
|
+
spec.add_runtime_dependency "money", "~> 6.0"
|
28
|
+
spec.add_runtime_dependency "nokogiri", "~> 1.6"
|
29
|
+
spec.add_runtime_dependency "physical", "~> 0.4", ">= 0.4.4"
|
30
30
|
spec.add_runtime_dependency "rest-client", "~> 2.0"
|
31
31
|
spec.required_ruby_version = '>= 2.5'
|
32
32
|
|
33
|
-
spec.add_development_dependency "bundler"
|
34
|
-
spec.add_development_dependency "dotenv"
|
33
|
+
spec.add_development_dependency "bundler", ">= 1.17", "< 3"
|
34
|
+
spec.add_development_dependency "dotenv", "~> 2.7"
|
35
35
|
spec.add_development_dependency "factory_bot", "~> 5.0"
|
36
|
-
spec.add_development_dependency "pry"
|
37
|
-
spec.add_development_dependency "rake", "
|
36
|
+
spec.add_development_dependency "pry", "~> 0.12"
|
37
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
38
38
|
spec.add_development_dependency "rspec", "~> 3.0"
|
39
39
|
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4"
|
40
|
-
spec.add_development_dependency "rubocop"
|
41
|
-
spec.add_development_dependency "simplecov"
|
42
|
-
spec.add_development_dependency "vcr"
|
43
|
-
spec.add_development_dependency "webmock"
|
40
|
+
spec.add_development_dependency "rubocop", ">= 0.80", "< 1"
|
41
|
+
spec.add_development_dependency "simplecov", "~> 0.17"
|
42
|
+
spec.add_development_dependency "vcr", "~> 5.0"
|
43
|
+
spec.add_development_dependency "webmock", "~> 3.6"
|
44
44
|
end
|
@@ -1,21 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module FriendlyShipping
|
4
|
-
class ApiFailure
|
5
|
-
|
6
|
-
|
7
|
-
# @param [Object] failure The API failure
|
8
|
-
# @param [FriendlyShipping::Request] original_request The HTTP request (when debugging is enabled)
|
9
|
-
# @param [FriendlyShipping::Response] original_response The HTTP response (when debugging is enabled)
|
10
|
-
def initialize(failure, original_request:, original_response:)
|
11
|
-
@failure = failure
|
12
|
-
|
13
|
-
# We do not want to attach debugging information in every single response to save memory in production
|
14
|
-
return unless original_request&.debug
|
15
|
-
|
16
|
-
@original_request = original_request
|
17
|
-
@original_response = original_response
|
18
|
-
end
|
4
|
+
class ApiFailure < ApiResult
|
5
|
+
alias_method :failure, :data
|
19
6
|
|
20
7
|
def to_s
|
21
8
|
failure.to_s
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/monads/result'
|
4
|
+
require 'friendly_shipping/api_failure'
|
4
5
|
require 'rest-client'
|
5
6
|
|
6
7
|
module FriendlyShipping
|
@@ -21,19 +22,19 @@ module FriendlyShipping
|
|
21
22
|
|
22
23
|
Success(convert_to_friendly_response(http_response))
|
23
24
|
rescue ::RestClient::Exception => e
|
24
|
-
error_handler.call(e)
|
25
|
+
error_handler.call(e, original_request: request, original_response: e.response)
|
25
26
|
end
|
26
27
|
|
27
|
-
def post(
|
28
|
+
def post(request)
|
28
29
|
http_response = ::RestClient.post(
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
request.url,
|
31
|
+
request.body,
|
32
|
+
request.headers
|
32
33
|
)
|
33
34
|
|
34
35
|
Success(convert_to_friendly_response(http_response))
|
35
36
|
rescue ::RestClient::Exception => e
|
36
|
-
error_handler.call(e)
|
37
|
+
error_handler.call(e, original_request: request, original_response: e.response)
|
37
38
|
end
|
38
39
|
|
39
40
|
def put(request)
|
@@ -45,13 +46,19 @@ module FriendlyShipping
|
|
45
46
|
|
46
47
|
Success(convert_to_friendly_response(http_response))
|
47
48
|
rescue ::RestClient::Exception => e
|
48
|
-
error_handler.call(e)
|
49
|
+
error_handler.call(e, original_request: request, original_response: e.response)
|
49
50
|
end
|
50
51
|
|
51
52
|
private
|
52
53
|
|
53
|
-
def wrap_in_failure(error)
|
54
|
-
Failure(
|
54
|
+
def wrap_in_failure(error, original_request: nil, original_response: nil)
|
55
|
+
Failure(
|
56
|
+
ApiFailure.new(
|
57
|
+
error,
|
58
|
+
original_request: original_request,
|
59
|
+
original_response: original_response
|
60
|
+
)
|
61
|
+
)
|
55
62
|
end
|
56
63
|
|
57
64
|
def convert_to_friendly_response(http_response)
|
@@ -8,11 +8,23 @@ module FriendlyShipping
|
|
8
8
|
class BadRequestHandler
|
9
9
|
extend Dry::Monads::Result::Mixin
|
10
10
|
|
11
|
-
def self.call(error)
|
11
|
+
def self.call(error, original_request: nil, original_response: nil)
|
12
12
|
if error.http_code == 400
|
13
|
-
Failure(
|
13
|
+
Failure(
|
14
|
+
ApiFailure.new(
|
15
|
+
BadRequest.new(error),
|
16
|
+
original_request: original_request,
|
17
|
+
original_response: original_response
|
18
|
+
)
|
19
|
+
)
|
14
20
|
else
|
15
|
-
Failure(
|
21
|
+
Failure(
|
22
|
+
ApiFailure.new(
|
23
|
+
error,
|
24
|
+
original_request: original_request,
|
25
|
+
original_response: original_response
|
26
|
+
)
|
27
|
+
)
|
16
28
|
end
|
17
29
|
end
|
18
30
|
end
|
@@ -7,8 +7,11 @@ module FriendlyShipping
|
|
7
7
|
extend Dry::Monads::Result::Mixin
|
8
8
|
|
9
9
|
def self.call(request:, response:)
|
10
|
-
parsing_result = ParseXMLResponse.call(
|
11
|
-
|
10
|
+
parsing_result = ParseXMLResponse.call(
|
11
|
+
request: request,
|
12
|
+
response: response,
|
13
|
+
expected_root_tag: 'AddressValidationResponse'
|
14
|
+
)
|
12
15
|
parsing_result.bind do |xml|
|
13
16
|
address_type = xml.at('AddressClassification/Description')&.text&.downcase
|
14
17
|
Success(
|
@@ -7,8 +7,11 @@ module FriendlyShipping
|
|
7
7
|
extend Dry::Monads::Result::Mixin
|
8
8
|
|
9
9
|
def self.call(request:, response:)
|
10
|
-
parsing_result = ParseXMLResponse.call(
|
11
|
-
|
10
|
+
parsing_result = ParseXMLResponse.call(
|
11
|
+
request: request,
|
12
|
+
response: response,
|
13
|
+
expected_root_tag: 'AddressValidationResponse'
|
14
|
+
)
|
12
15
|
parsing_result.bind do |xml|
|
13
16
|
if xml.at('NoCandidatesIndicator')
|
14
17
|
Failure(
|
@@ -7,8 +7,11 @@ module FriendlyShipping
|
|
7
7
|
extend Dry::Monads::Result::Mixin
|
8
8
|
|
9
9
|
def self.call(request:, response:, location:)
|
10
|
-
parsing_result = ParseXMLResponse.call(
|
11
|
-
|
10
|
+
parsing_result = ParseXMLResponse.call(
|
11
|
+
request: request,
|
12
|
+
response: response,
|
13
|
+
expected_root_tag: 'AddressValidationResponse'
|
14
|
+
)
|
12
15
|
parsing_result.fmap do |xml|
|
13
16
|
FriendlyShipping::ApiResult.new(
|
14
17
|
[
|
@@ -75,8 +75,8 @@ module FriendlyShipping
|
|
75
75
|
"407" => "EXTENDED AREA PICKUP",
|
76
76
|
"410" => "RETURN OF DOCUMENT",
|
77
77
|
"430" => "PEAK SEASON",
|
78
|
-
"431" => "
|
79
|
-
"432" => "
|
78
|
+
"431" => "LARGE PACKAGE SEASONAL SURCHARGE",
|
79
|
+
"432" => "ADDITIONAL HANDLING SEASONAL SURCHARGE",
|
80
80
|
"440" => "SHIP LARGE PACKAGE",
|
81
81
|
"441" => "CARBON NEUTRAL",
|
82
82
|
"442" => "PKG QV IN TRANSIT NOTIFICATION",
|
@@ -9,7 +9,11 @@ module FriendlyShipping
|
|
9
9
|
class ParseRateResponse
|
10
10
|
class << self
|
11
11
|
def call(request:, response:, shipment:)
|
12
|
-
parsing_result = ParseXMLResponse.call(
|
12
|
+
parsing_result = ParseXMLResponse.call(
|
13
|
+
request: request,
|
14
|
+
response: response,
|
15
|
+
expected_root_tag: 'RatingServiceSelectionResponse'
|
16
|
+
)
|
13
17
|
parsing_result.fmap do |xml|
|
14
18
|
FriendlyShipping::ApiResult.new(
|
15
19
|
build_rates(xml, shipment),
|
@@ -11,7 +11,11 @@ module FriendlyShipping
|
|
11
11
|
|
12
12
|
class << self
|
13
13
|
def call(request:, response:)
|
14
|
-
parsing_result = ParseXMLResponse.call(
|
14
|
+
parsing_result = ParseXMLResponse.call(
|
15
|
+
request: request,
|
16
|
+
response: response,
|
17
|
+
expected_root_tag: 'ShipmentAcceptResponse'
|
18
|
+
)
|
15
19
|
parsing_result.fmap do |xml|
|
16
20
|
FriendlyShipping::ApiResult.new(
|
17
21
|
build_labels(xml),
|
@@ -7,7 +7,11 @@ module FriendlyShipping
|
|
7
7
|
class Ups
|
8
8
|
class ParseShipmentConfirmResponse
|
9
9
|
def self.call(request:, response:)
|
10
|
-
parsing_result = ParseXMLResponse.call(
|
10
|
+
parsing_result = ParseXMLResponse.call(
|
11
|
+
request: request,
|
12
|
+
response: response,
|
13
|
+
expected_root_tag: 'ShipmentConfirmResponse'
|
14
|
+
)
|
11
15
|
parsing_result.fmap do |xml|
|
12
16
|
FriendlyShipping::ApiResult.new(
|
13
17
|
xml.root.at('ShipmentDigest').text,
|
@@ -5,7 +5,11 @@ module FriendlyShipping
|
|
5
5
|
class Ups
|
6
6
|
class ParseTimeInTransitResponse
|
7
7
|
def self.call(request:, response:)
|
8
|
-
parsing_result = ParseXMLResponse.call(
|
8
|
+
parsing_result = ParseXMLResponse.call(
|
9
|
+
request: request,
|
10
|
+
response: response,
|
11
|
+
expected_root_tag: 'TimeInTransitResponse'
|
12
|
+
)
|
9
13
|
parsing_result.fmap do |xml|
|
10
14
|
origin_country_code = xml.at('TransitResponse/TransitFrom/AddressArtifactFormat/CountryCode').text
|
11
15
|
timings = xml.root.xpath('//TransitResponse/ServiceSummary').map do |service_summary|
|
@@ -21,7 +25,7 @@ module FriendlyShipping
|
|
21
25
|
delivery_time = service_summary.at('EstimatedArrival/Time').text
|
22
26
|
delivery = Time.parse("#{delivery_date} #{delivery_time}")
|
23
27
|
pickup_date = service_summary.at('EstimatedArrival/PickupDate').text
|
24
|
-
pickup_time = service_summary.at('EstimatedArrival/PickupTime')
|
28
|
+
pickup_time = service_summary.at('EstimatedArrival/PickupTime')&.text
|
25
29
|
pickup = Time.parse("#{pickup_date} #{pickup_time}")
|
26
30
|
|
27
31
|
# Some additional data
|
@@ -7,7 +7,11 @@ module FriendlyShipping
|
|
7
7
|
class Ups
|
8
8
|
class ParseVoidShipmentResponse
|
9
9
|
def self.call(request:, response:)
|
10
|
-
parsing_result = ParseXMLResponse.call(
|
10
|
+
parsing_result = ParseXMLResponse.call(
|
11
|
+
request: request,
|
12
|
+
response: response,
|
13
|
+
expected_root_tag: 'VoidShipmentResponse'
|
14
|
+
)
|
11
15
|
parsing_result.fmap do |xml|
|
12
16
|
FriendlyShipping::ApiResult.new(
|
13
17
|
xml.root.at('ResponseStatusDescription').text,
|
@@ -8,19 +8,18 @@ module FriendlyShipping
|
|
8
8
|
SUCCESSFUL_RESPONSE_STATUS_CODE = '1'
|
9
9
|
|
10
10
|
class << self
|
11
|
-
def call(
|
12
|
-
xml = Nokogiri.XML(
|
11
|
+
def call(request:, response:, expected_root_tag:)
|
12
|
+
xml = Nokogiri.XML(response.body, &:strict)
|
13
13
|
|
14
14
|
if xml.root.nil? || xml.root.name != expected_root_tag
|
15
|
-
|
16
|
-
|
17
|
-
if request_successful?(xml)
|
15
|
+
wrap_failure('Invalid document', request, response)
|
16
|
+
elsif request_successful?(xml)
|
18
17
|
Success(xml)
|
19
18
|
else
|
20
|
-
|
19
|
+
wrap_failure(error_message(xml), request, response)
|
21
20
|
end
|
22
21
|
rescue Nokogiri::XML::SyntaxError => e
|
23
|
-
|
22
|
+
wrap_failure(e, request, response)
|
24
23
|
end
|
25
24
|
|
26
25
|
private
|
@@ -34,6 +33,16 @@ module FriendlyShipping
|
|
34
33
|
desc = xml.root.at_xpath('Response/Error/ErrorDescription')&.text
|
35
34
|
[status, desc].compact.join(": ").presence || 'UPS could not process the request.'
|
36
35
|
end
|
36
|
+
|
37
|
+
def wrap_failure(failure, request, response)
|
38
|
+
Failure(
|
39
|
+
FriendlyShipping::ApiFailure.new(
|
40
|
+
failure,
|
41
|
+
original_request: request,
|
42
|
+
original_response: response
|
43
|
+
)
|
44
|
+
)
|
45
|
+
end
|
37
46
|
end
|
38
47
|
end
|
39
48
|
end
|
@@ -4,11 +4,21 @@ require 'dry/monads/result'
|
|
4
4
|
require 'friendly_shipping/http_client'
|
5
5
|
require 'friendly_shipping/services/ups_freight/shipping_methods'
|
6
6
|
require 'friendly_shipping/services/ups_freight/rates_options'
|
7
|
+
require 'friendly_shipping/services/ups_freight/label_options'
|
7
8
|
require 'friendly_shipping/services/ups_freight/rates_package_options'
|
8
9
|
require 'friendly_shipping/services/ups_freight/rates_item_options'
|
10
|
+
require 'friendly_shipping/services/ups_freight/label_package_options'
|
11
|
+
require 'friendly_shipping/services/ups_freight/label_item_options'
|
12
|
+
require 'friendly_shipping/services/ups_freight/label_document_options'
|
13
|
+
require 'friendly_shipping/services/ups_freight/label_email_options'
|
14
|
+
require 'friendly_shipping/services/ups_freight/label_pickup_options'
|
15
|
+
require 'friendly_shipping/services/ups_freight/label_delivery_options'
|
16
|
+
require 'friendly_shipping/services/ups_freight/pickup_request_options'
|
17
|
+
require 'friendly_shipping/services/ups_freight/parse_freight_label_response'
|
9
18
|
require 'friendly_shipping/services/ups_freight/parse_freight_rate_response'
|
10
19
|
require 'friendly_shipping/services/ups_freight/generate_freight_rate_request_hash'
|
11
|
-
require 'friendly_shipping/services/ups_freight/
|
20
|
+
require 'friendly_shipping/services/ups_freight/generate_freight_ship_request_hash'
|
21
|
+
require 'friendly_shipping/services/ups_freight/restful_api_error_handler'
|
12
22
|
|
13
23
|
module FriendlyShipping
|
14
24
|
module Services
|
@@ -28,10 +38,11 @@ module FriendlyShipping
|
|
28
38
|
LIVE_URL = 'https://onlinetools.ups.com'
|
29
39
|
|
30
40
|
RESOURCES = {
|
31
|
-
rates: '/
|
41
|
+
rates: '/ship/v1801/freight/rating/ground',
|
42
|
+
labels: '/ship/v1607/freight/shipments/Ground'
|
32
43
|
}.freeze
|
33
44
|
|
34
|
-
def initialize(key:, login:, password:, test: true, client: HttpClient.new)
|
45
|
+
def initialize(key:, login:, password:, test: true, client: HttpClient.new(error_handler: RestfulApiErrorHandler))
|
35
46
|
@key = key
|
36
47
|
@login = login
|
37
48
|
@password = password
|
@@ -44,28 +55,48 @@ module FriendlyShipping
|
|
44
55
|
end
|
45
56
|
|
46
57
|
# Get rates for a shipment
|
47
|
-
# @param [Physical::Shipment]
|
58
|
+
# @param [Physical::Shipment] shipment The shipment we want to get rates for
|
48
59
|
# @param [FriendlyShipping::Services::UpsFreight::RatesOptions] options Options for obtaining rates for this shipment.
|
49
60
|
# @return [Result<ApiResult<Array<Rate>>>] The rates returned from UPS encoded in a
|
50
61
|
# `FriendlyShipping::ApiResult` object.
|
51
62
|
def rate_estimates(shipment, options:, debug: false)
|
52
63
|
freight_rate_request_hash = GenerateFreightRateRequestHash.call(shipment: shipment, options: options)
|
53
|
-
|
54
|
-
request = FriendlyShipping::Request.new(
|
55
|
-
url: url,
|
56
|
-
body: authentication_hash.merge(freight_rate_request_hash).to_json,
|
57
|
-
debug: debug
|
58
|
-
)
|
64
|
+
request = build_request(:rates, freight_rate_request_hash, debug)
|
59
65
|
|
60
|
-
client.post(request).
|
66
|
+
client.post(request).fmap do |response|
|
61
67
|
ParseFreightRateResponse.call(response: response, request: request)
|
62
68
|
end
|
63
69
|
end
|
64
70
|
|
71
|
+
# Get labels for a shipment
|
72
|
+
# @param [Physical::Shipment] shipment The shipment we want to get rates for
|
73
|
+
# @param [FriendlyShipping::Services::UpsFreight::LabelOptions] options Options for shipping this shipment.
|
74
|
+
# @return [Result<ApiResult<ShipmentInformation>] The information that you need for shipping this shipment.
|
75
|
+
def labels(shipment, options:, debug: false)
|
76
|
+
freight_ship_request_hash = GenerateFreightShipRequestHash.call(shipment: shipment, options: options)
|
77
|
+
request = build_request(:labels, freight_ship_request_hash, debug)
|
78
|
+
|
79
|
+
client.post(request).fmap do |response|
|
80
|
+
ParseFreightLabelResponse.call(response: response, request: request)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
65
84
|
private
|
66
85
|
|
67
|
-
def
|
68
|
-
|
86
|
+
def build_request(action, payload, debug)
|
87
|
+
url = base_url + RESOURCES[action]
|
88
|
+
FriendlyShipping::Request.new(
|
89
|
+
url: url,
|
90
|
+
body: payload.to_json,
|
91
|
+
headers: {
|
92
|
+
Content_Type: 'application/json',
|
93
|
+
Accept: 'application/json',
|
94
|
+
Username: login,
|
95
|
+
Password: password,
|
96
|
+
AccessLicenseNumber: key
|
97
|
+
},
|
98
|
+
debug: debug
|
99
|
+
)
|
69
100
|
end
|
70
101
|
|
71
102
|
def base_url
|