friendly_shipping 0.6.4 → 0.7.0
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/.circleci/config.yml +18 -5
- data/.env.template +1 -1
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +14 -3
- data/README.md +1 -1
- data/friendly_shipping.gemspec +6 -7
- data/lib/friendly_shipping/api_error.rb +14 -0
- data/lib/friendly_shipping/api_error_handler.rb +30 -0
- data/lib/friendly_shipping/http_client.rb +9 -27
- data/lib/friendly_shipping/request.rb +5 -3
- data/lib/friendly_shipping/response.rb +27 -1
- data/lib/friendly_shipping/services/ship_engine/parse_label_response.rb +8 -2
- data/lib/friendly_shipping/services/ship_engine/parse_rate_estimate_response.rb +28 -6
- data/lib/friendly_shipping/services/ship_engine.rb +9 -5
- data/lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb +1 -1
- data/lib/friendly_shipping/services/ups/parse_shipment_confirm_response.rb +1 -1
- data/lib/friendly_shipping/services/ups/parse_void_shipment_response.rb +1 -1
- data/lib/friendly_shipping/services/ups/rate_estimate_options.rb +1 -1
- data/lib/friendly_shipping/services/ups/rate_estimate_package_options.rb +1 -1
- data/lib/friendly_shipping/services/ups/shipping_methods.rb +4 -0
- data/lib/friendly_shipping/services/ups.rb +10 -2
- data/lib/friendly_shipping/services/ups_freight/api_error.rb +36 -0
- data/lib/friendly_shipping/services/ups_freight/generate_delivery_options_hash.rb +6 -4
- data/lib/friendly_shipping/services/ups_freight/generate_freight_ship_request_hash.rb +5 -2
- data/lib/friendly_shipping/services/ups_freight/generate_location_hash.rb +6 -9
- data/lib/friendly_shipping/services/ups_freight/generate_pickup_options_hash.rb +4 -3
- data/lib/friendly_shipping/services/ups_freight/generate_reference_hash.rb +27 -0
- data/lib/friendly_shipping/services/ups_freight/label_delivery_options.rb +7 -1
- data/lib/friendly_shipping/services/ups_freight/label_options.rb +28 -2
- data/lib/friendly_shipping/services/ups_freight/label_pickup_options.rb +3 -0
- data/lib/friendly_shipping/services/ups_freight/parse_freight_label_response.rb +27 -8
- data/lib/friendly_shipping/services/ups_freight/parse_shipment_document.rb +1 -1
- data/lib/friendly_shipping/services/ups_freight/shipment_information.rb +5 -2
- data/lib/friendly_shipping/services/ups_freight.rb +8 -5
- data/lib/friendly_shipping/services/usps/parse_package_rate.rb +16 -1
- data/lib/friendly_shipping/services/usps/rate_estimate_options.rb +1 -1
- data/lib/friendly_shipping/services/usps/rate_estimate_package_options.rb +23 -19
- data/lib/friendly_shipping/services/usps/serialize_rate_request.rb +2 -0
- data/lib/friendly_shipping/services/usps.rb +2 -1
- data/lib/friendly_shipping/version.rb +1 -1
- data/lib/friendly_shipping.rb +1 -0
- metadata +18 -35
- data/lib/friendly_shipping/services/ups_freight/restful_api_error_handler.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e5444887ead0f957efaa619fc49bf737c34513f8a2480504beaabdbdab0eb2d
|
4
|
+
data.tar.gz: c52c103c53e9be10cef0d6288c1713de54441e536f8691cf0685c2bb0a4859ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eff139906b09356f48bbb34e39587f41f3802cba25abb87921b7e2883865d399d4b043b793c5e0ca40fddf9fe9ca00b326be39722466a9c59c83020a67d6674e
|
7
|
+
data.tar.gz: 396fe842544a93357d601d383a27d116b5b6f4e2947fec39703e7bd70a57b8fe30a63f68eb7312761db56e3533d59fbf70a3c87bb673ac3d497912c84b5a703b
|
data/.circleci/config.yml
CHANGED
@@ -2,12 +2,15 @@
|
|
2
2
|
#
|
3
3
|
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
4
4
|
#
|
5
|
-
version: 2
|
5
|
+
version: 2.1
|
6
6
|
jobs:
|
7
|
-
|
7
|
+
test:
|
8
|
+
parameters:
|
9
|
+
ruby-version:
|
10
|
+
type: string
|
8
11
|
docker:
|
9
12
|
# specify the version you desire here
|
10
|
-
- image:
|
13
|
+
- image: cimg/ruby:<< parameters.ruby-version >>
|
11
14
|
|
12
15
|
# Specify service dependencies here if necessary
|
13
16
|
# CircleCI maintains a library of pre-built images
|
@@ -22,7 +25,7 @@ jobs:
|
|
22
25
|
# Download and cache dependencies
|
23
26
|
- restore_cache:
|
24
27
|
keys:
|
25
|
-
- v1-dependencies-{{ checksum "friendly_shipping.gemspec" }}
|
28
|
+
- v1-dependencies-{{ checksum "friendly_shipping.gemspec" }}-<< parameters.ruby-version >>
|
26
29
|
# fallback to using the latest cache if no exact match is found
|
27
30
|
- v1-dependencies-
|
28
31
|
|
@@ -35,7 +38,7 @@ jobs:
|
|
35
38
|
- save_cache:
|
36
39
|
paths:
|
37
40
|
- ./vendor/bundle
|
38
|
-
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
|
41
|
+
key: v1-dependencies-{{ checksum "Gemfile.lock" }}-<< parameters.ruby-version >>
|
39
42
|
|
40
43
|
- run:
|
41
44
|
name: run Rubocop
|
@@ -60,3 +63,13 @@ jobs:
|
|
60
63
|
- store_artifacts:
|
61
64
|
path: /tmp/test-results
|
62
65
|
destination: test-results
|
66
|
+
|
67
|
+
workflows:
|
68
|
+
build_and_test:
|
69
|
+
jobs:
|
70
|
+
- test:
|
71
|
+
matrix:
|
72
|
+
parameters:
|
73
|
+
# https://github.com/CircleCI-Public/cimg-ruby
|
74
|
+
# only supports the last three ruby versions
|
75
|
+
ruby-version: ["3.1", "3.0", "2.7"]
|
data/.env.template
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# NO PASSWORDS OR SENSITIVE INFORMATION SHOULD BE STORED HERE
|
3
3
|
# Only pass along how those passwords/info are reference via ENV VARS
|
4
4
|
|
5
|
-
SHIPENGINE_API_KEY=
|
5
|
+
SHIPENGINE_API_KEY=ShipEngine API key
|
6
6
|
SHIPENGINE_CARRIER_ID=Carrier ID from your ShipEngine account to run test labels with
|
7
7
|
|
8
8
|
UPS_KEY=UPS API access key
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,22 +4,33 @@ 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.
|
7
|
+
## [0.7.0] - 2022-12-14
|
8
|
+
- Removes dependency on unmaintained data_uri gem
|
9
|
+
- Bumps required Ruby to 2.7
|
10
|
+
|
11
|
+
## [0.6.5] - 2022-04-25
|
8
12
|
|
9
13
|
### Added
|
14
|
+
- USPS Service: Add support for returned dimensional weight (#128)
|
15
|
+
- USPS Service: Add support for returned fees (#127)
|
10
16
|
|
17
|
+
### Changed
|
18
|
+
- ShipEngine Service: Prevent exceptions when no rates are returned (#125)
|
19
|
+
- Misc dependency updates (#116, #120, #121, #124)
|
20
|
+
|
21
|
+
## [0.6.4] - 2021-01-27
|
22
|
+
|
23
|
+
### Added
|
11
24
|
- UPS Service: Include negotiated charges for UPS (#119)
|
12
25
|
- UPS Service: Include shipment-level itemized charges (#117)
|
13
26
|
|
14
27
|
## [0.6.3] - 2020-10-30
|
15
28
|
|
16
29
|
### Added
|
17
|
-
|
18
30
|
- USPS Service: Append HFP (Hold For Pickup) to service code when necessary (#110)
|
19
31
|
- USPS Service: Add Priority Cubic shipping method (#113)
|
20
32
|
|
21
33
|
### Changed
|
22
|
-
|
23
34
|
- USPS Service: Refactor to use explicit service codes (#111)
|
24
35
|
- USPS Service: Match Priority Express by CLASSID instead of service name (#112)
|
25
36
|
- UPS Service: Rename peak surcharge keys to match UPS docs (#114)
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# FriendlyShipping - the friendly shipping provider API wrapper
|
2
2
|
|
3
|
-
This gem provides wrappers for popular shipping provider APIs. Currently, there are implementations for rate quoting and address validation, as well as shipping label generation via the `
|
3
|
+
This gem provides wrappers for popular shipping provider APIs. Currently, there are implementations for rate quoting and address validation, as well as shipping label generation via the `ShipEngine` API.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
data/friendly_shipping.gemspec
CHANGED
@@ -22,23 +22,22 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_runtime_dependency "data_uri", "~> 0.0.3"
|
26
25
|
spec.add_runtime_dependency "dry-monads", "~> 1.0"
|
27
26
|
spec.add_runtime_dependency "money", "~> 6.0"
|
28
27
|
spec.add_runtime_dependency "nokogiri", "~> 1.6"
|
29
|
-
spec.add_runtime_dependency "physical", "~> 0.4", ">= 0.4.
|
28
|
+
spec.add_runtime_dependency "physical", "~> 0.4", ">= 0.4.5"
|
30
29
|
spec.add_runtime_dependency "rest-client", "~> 2.0"
|
31
|
-
spec.required_ruby_version = '>= 2.
|
30
|
+
spec.required_ruby_version = '>= 2.7'
|
32
31
|
|
33
|
-
spec.add_development_dependency "bundler", ">= 1.
|
32
|
+
spec.add_development_dependency "bundler", ">= 2.1.4", "< 3"
|
34
33
|
spec.add_development_dependency "dotenv", "~> 2.7"
|
35
|
-
spec.add_development_dependency "factory_bot", "~>
|
34
|
+
spec.add_development_dependency "factory_bot", "~> 6.2"
|
36
35
|
spec.add_development_dependency "pry", "~> 0.12"
|
37
36
|
spec.add_development_dependency "rake", ">= 12.3.3"
|
38
37
|
spec.add_development_dependency "rspec", "~> 3.0"
|
39
38
|
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4"
|
40
|
-
spec.add_development_dependency "rubocop"
|
39
|
+
spec.add_development_dependency "rubocop"
|
41
40
|
spec.add_development_dependency "simplecov", "~> 0.17"
|
42
|
-
spec.add_development_dependency "vcr", "~>
|
41
|
+
spec.add_development_dependency "vcr", "~> 6.0"
|
43
42
|
spec.add_development_dependency "webmock", "~> 3.6"
|
44
43
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FriendlyShipping
|
4
|
+
class ApiError < StandardError
|
5
|
+
attr_reader :cause
|
6
|
+
|
7
|
+
# @param [RestClient::Exception] cause
|
8
|
+
# @param [String] msg
|
9
|
+
def initialize(cause, msg = nil)
|
10
|
+
@cause = cause
|
11
|
+
super msg || cause.message
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'friendly_shipping/api_error'
|
4
|
+
|
5
|
+
module FriendlyShipping
|
6
|
+
class ApiErrorHandler
|
7
|
+
include Dry::Monads[:result]
|
8
|
+
|
9
|
+
attr_reader :api_error_class
|
10
|
+
|
11
|
+
# @param [Class] api_error_class
|
12
|
+
def initialize(api_error_class: FriendlyShipping::ApiError)
|
13
|
+
@api_error_class = api_error_class
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [StandardError] error
|
17
|
+
# @param [FriendlyShipping::Request] original_request
|
18
|
+
# @param [RestClient::Response] original_response
|
19
|
+
# @return [Dry::Monads::Failure<FriendlyShipping::ApiFailure>]
|
20
|
+
def call(error, original_request: nil, original_response: nil)
|
21
|
+
Failure(
|
22
|
+
ApiFailure.new(
|
23
|
+
api_error_class.new(error),
|
24
|
+
original_request: original_request,
|
25
|
+
original_response: Response.new_from_rest_client_response(original_response)
|
26
|
+
)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,17 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/monads
|
4
|
-
require 'friendly_shipping/api_failure'
|
3
|
+
require 'dry/monads'
|
5
4
|
require 'rest-client'
|
6
5
|
|
6
|
+
require 'friendly_shipping/api_failure'
|
7
|
+
require 'friendly_shipping/api_error_handler'
|
8
|
+
|
7
9
|
module FriendlyShipping
|
8
10
|
class HttpClient
|
9
|
-
include Dry::Monads
|
11
|
+
include Dry::Monads[:result]
|
10
12
|
|
11
13
|
attr_reader :error_handler
|
12
14
|
|
13
15
|
# @param [Proc] error_handler Called to handle an error if one occurs
|
14
|
-
def initialize(error_handler:
|
16
|
+
def initialize(error_handler: FriendlyShipping::ApiErrorHandler.new)
|
15
17
|
@error_handler = error_handler
|
16
18
|
end
|
17
19
|
|
@@ -20,7 +22,7 @@ module FriendlyShipping
|
|
20
22
|
request.url, request.headers
|
21
23
|
)
|
22
24
|
|
23
|
-
Success(
|
25
|
+
Success(Response.new_from_rest_client_response(http_response))
|
24
26
|
rescue ::RestClient::Exception => e
|
25
27
|
error_handler.call(e, original_request: request, original_response: e.response)
|
26
28
|
end
|
@@ -32,7 +34,7 @@ module FriendlyShipping
|
|
32
34
|
request.headers
|
33
35
|
)
|
34
36
|
|
35
|
-
Success(
|
37
|
+
Success(Response.new_from_rest_client_response(http_response))
|
36
38
|
rescue ::RestClient::Exception => e
|
37
39
|
error_handler.call(e, original_request: request, original_response: e.response)
|
38
40
|
end
|
@@ -44,29 +46,9 @@ module FriendlyShipping
|
|
44
46
|
request.headers
|
45
47
|
)
|
46
48
|
|
47
|
-
Success(
|
49
|
+
Success(Response.new_from_rest_client_response(http_response))
|
48
50
|
rescue ::RestClient::Exception => e
|
49
51
|
error_handler.call(e, original_request: request, original_response: e.response)
|
50
52
|
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
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
|
-
)
|
62
|
-
end
|
63
|
-
|
64
|
-
def convert_to_friendly_response(http_response)
|
65
|
-
FriendlyShipping::Response.new(
|
66
|
-
status: http_response.code,
|
67
|
-
body: http_response.body,
|
68
|
-
headers: http_response.headers
|
69
|
-
)
|
70
|
-
end
|
71
53
|
end
|
72
54
|
end
|
@@ -2,15 +2,17 @@
|
|
2
2
|
|
3
3
|
module FriendlyShipping
|
4
4
|
class Request
|
5
|
-
attr_reader :url, :body, :headers, :debug
|
5
|
+
attr_reader :url, :http_method, :body, :headers, :debug
|
6
6
|
|
7
7
|
# @param [String] url The HTTP request URL
|
8
|
+
# @param [String] http_method The HTTP request method
|
8
9
|
# @param [String] body The HTTP request body
|
9
|
-
#
|
10
|
+
# @param [String] readable_body Human-readable HTTP request body
|
10
11
|
# @param [Hash] headers The HTTP request headers
|
11
12
|
# @param [Boolean] debug Whether to debug the request
|
12
|
-
def initialize(url:, body: nil, readable_body: nil, headers: {}, debug: false)
|
13
|
+
def initialize(url:, http_method: nil, body: nil, readable_body: nil, headers: {}, debug: false)
|
13
14
|
@url = url
|
15
|
+
@http_method = http_method
|
14
16
|
@body = body
|
15
17
|
@readable_body = readable_body
|
16
18
|
@headers = headers
|
@@ -10,7 +10,33 @@ module FriendlyShipping
|
|
10
10
|
def initialize(status:, body:, headers:)
|
11
11
|
@status = status
|
12
12
|
@body = body
|
13
|
-
@headers = headers
|
13
|
+
@headers = headers || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :code, :status
|
17
|
+
|
18
|
+
# @param [RestClient::Response] response
|
19
|
+
# @return [FriendlyShipping::Response]
|
20
|
+
def self.new_from_rest_client_response(response)
|
21
|
+
new(status: response&.code, body: response&.body, headers: response&.headers)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [Object] other
|
25
|
+
def ==(other)
|
26
|
+
other.class == self.class &&
|
27
|
+
other.attributes == attributes
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method :eql?, :==
|
31
|
+
|
32
|
+
def hash
|
33
|
+
attributes.hash
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def attributes
|
39
|
+
[status, body, headers]
|
14
40
|
end
|
15
41
|
end
|
16
42
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'json'
|
4
|
-
require 'data_uri'
|
5
4
|
|
6
5
|
module FriendlyShipping
|
7
6
|
module Services
|
@@ -14,7 +13,14 @@ module FriendlyShipping
|
|
14
13
|
label_data = nil
|
15
14
|
label_url = nil
|
16
15
|
if label_uri_string.starts_with?('data')
|
17
|
-
|
16
|
+
# This URI has the following form:
|
17
|
+
# data:application/zpl;base64,XlhBDQpeTEwxMjE4....
|
18
|
+
# We don't know the content type here, but we can assume Base64
|
19
|
+
# encoding.
|
20
|
+
# This next line splits the URI at the first occurrence of ";base64,",
|
21
|
+
# giving us the desired base64 encoded string.
|
22
|
+
_, base64_encoded = label_uri_string.split(";base64,", 2)
|
23
|
+
label_data = Base64.decode64(base64_encoded)
|
18
24
|
else
|
19
25
|
label_url = label_uri_string
|
20
26
|
end
|
@@ -10,8 +10,14 @@ module FriendlyShipping
|
|
10
10
|
|
11
11
|
class << self
|
12
12
|
def call(response:, request:, options:)
|
13
|
+
error_messages = []
|
13
14
|
parsed_json = JSON.parse(response.body)
|
14
15
|
rates = parsed_json.map do |rate|
|
16
|
+
if rate['validation_status'] == 'invalid'
|
17
|
+
error_messages.concat rate['error_messages']
|
18
|
+
next
|
19
|
+
end
|
20
|
+
|
15
21
|
carrier = options.carriers.detect { |c| c.id == rate['carrier_id'] }
|
16
22
|
next unless carrier
|
17
23
|
|
@@ -31,17 +37,33 @@ module FriendlyShipping
|
|
31
37
|
)
|
32
38
|
end.compact
|
33
39
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
if valid_rates(parsed_json)
|
41
|
+
Success(
|
42
|
+
ApiResult.new(
|
43
|
+
rates,
|
44
|
+
original_request: request,
|
45
|
+
original_response: response
|
46
|
+
)
|
47
|
+
)
|
48
|
+
else
|
49
|
+
Failure(
|
50
|
+
ApiFailure.new(
|
51
|
+
error_messages,
|
52
|
+
original_request: request,
|
53
|
+
original_response: response
|
54
|
+
)
|
39
55
|
)
|
40
|
-
|
56
|
+
end
|
41
57
|
end
|
42
58
|
|
43
59
|
private
|
44
60
|
|
61
|
+
def valid_rates(parsed_json)
|
62
|
+
parsed_json.map do |rate|
|
63
|
+
["valid", "has_warnings", "unknown"].include? rate['validation_status']
|
64
|
+
end.any?
|
65
|
+
end
|
66
|
+
|
45
67
|
def get_amounts(rate_hash)
|
46
68
|
[:shipping, :other, :insurance, :confirmation].map do |name|
|
47
69
|
currency = Money::Currency.new(rate_hash["#{name}_amount"]["currency"])
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/monads
|
3
|
+
require 'dry/monads'
|
4
4
|
require 'friendly_shipping/http_client'
|
5
5
|
require 'friendly_shipping/services/ship_engine/bad_request_handler'
|
6
6
|
require 'friendly_shipping/services/ship_engine/parse_carrier_response'
|
@@ -28,12 +28,13 @@ module FriendlyShipping
|
|
28
28
|
@client = client
|
29
29
|
end
|
30
30
|
|
31
|
-
# Get configured carriers from
|
31
|
+
# Get configured carriers from ShipEngine
|
32
32
|
#
|
33
|
-
# @return [Result<ApiResult<Array<Carrier>>>] Carriers configured in your
|
33
|
+
# @return [Result<ApiResult<Array<Carrier>>>] Carriers configured in your account
|
34
34
|
def carriers(debug: false)
|
35
35
|
request = FriendlyShipping::Request.new(
|
36
36
|
url: API_BASE + API_PATHS[:carriers],
|
37
|
+
http_method: "GET",
|
37
38
|
headers: request_headers,
|
38
39
|
debug: debug
|
39
40
|
)
|
@@ -53,7 +54,8 @@ module FriendlyShipping
|
|
53
54
|
# can be serialized into an error message using `to_s`.
|
54
55
|
def rate_estimates(shipment, options: FriendlyShipping::Services::ShipEngine::RateEstimatesOptions.new, debug: false)
|
55
56
|
request = FriendlyShipping::Request.new(
|
56
|
-
url: API_BASE
|
57
|
+
url: "#{API_BASE}rates/estimate",
|
58
|
+
http_method: "POST",
|
57
59
|
body: SerializeRateEstimateRequest.call(shipment: shipment, options: options).to_json,
|
58
60
|
headers: request_headers,
|
59
61
|
debug: debug
|
@@ -68,13 +70,14 @@ module FriendlyShipping
|
|
68
70
|
# @param [Physical::Shipment] shipment The shipment object we're trying to get labels for
|
69
71
|
# Note: Some ShipEngine carriers, notably USPS, only support one package per shipment, and that's
|
70
72
|
# all that the integration supports at this point.
|
71
|
-
# @param [FriendlyShipping::Services::ShipEngine::LabelOptions] The options relevant to estimating rates. See object description.
|
73
|
+
# @param [FriendlyShipping::Services::ShipEngine::LabelOptions] options The options relevant to estimating rates. See object description.
|
72
74
|
#
|
73
75
|
# @return [Result<ApiResult<Array<FriendlyShipping::Label>>>] The label returned.
|
74
76
|
#
|
75
77
|
def labels(shipment, options:)
|
76
78
|
request = FriendlyShipping::Request.new(
|
77
79
|
url: API_BASE + API_PATHS[:labels],
|
80
|
+
http_method: "POST",
|
78
81
|
body: SerializeLabelShipment.call(shipment: shipment, options: options, test: test).to_json,
|
79
82
|
headers: request_headers
|
80
83
|
)
|
@@ -86,6 +89,7 @@ module FriendlyShipping
|
|
86
89
|
def void(label, debug: false)
|
87
90
|
request = FriendlyShipping::Request.new(
|
88
91
|
url: "#{API_BASE}labels/#{label.id}/void",
|
92
|
+
http_method: "PUT",
|
89
93
|
body: '',
|
90
94
|
headers: request_headers,
|
91
95
|
debug: debug
|
@@ -84,7 +84,7 @@ module FriendlyShipping
|
|
84
84
|
@shipper = shipper
|
85
85
|
@shipping_method = shipping_method
|
86
86
|
@with_time_in_transit = with_time_in_transit
|
87
|
-
super
|
87
|
+
super(**kwargs.merge(package_options_class: package_options_class))
|
88
88
|
end
|
89
89
|
|
90
90
|
def pickup_type_code
|
@@ -39,6 +39,10 @@ module FriendlyShipping
|
|
39
39
|
['US', 'domestic', 'UPS Next Day Air', '01'],
|
40
40
|
['US', 'domestic', 'UPS Next Day Air Early', '14'],
|
41
41
|
['US', 'domestic', 'UPS Next Day Air Saver', '13'],
|
42
|
+
['US', 'domestic', 'UPS SurePost Less than 1LB', '92'],
|
43
|
+
['US', 'domestic', 'UPS SurePost 1LB or greater', '93'],
|
44
|
+
['US', 'domestic', 'UPS SurePost BPM', '94'],
|
45
|
+
['US', 'domestic', 'UPS SurePost Media Mail', '95'],
|
42
46
|
['CA', 'domestic', 'UPS Expedited Canadian domestic shipments', '02'],
|
43
47
|
['CA', 'domestic', 'UPS Express Saver Canadian domestic shipments', '13'],
|
44
48
|
['CA', 'domestic', 'UPS 3 Day Select Shipments originating in Canada to CA and US 48', '12'],
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/monads
|
3
|
+
require 'dry/monads'
|
4
4
|
require 'friendly_shipping/http_client'
|
5
5
|
require 'friendly_shipping/services/ups/serialize_access_request'
|
6
6
|
require 'friendly_shipping/services/ups/serialize_city_state_lookup_request'
|
@@ -26,7 +26,7 @@ require 'friendly_shipping/services/ups/timing_options'
|
|
26
26
|
module FriendlyShipping
|
27
27
|
module Services
|
28
28
|
class Ups
|
29
|
-
include Dry::Monads
|
29
|
+
include Dry::Monads[:result]
|
30
30
|
|
31
31
|
attr_reader :test, :key, :login, :password, :client
|
32
32
|
|
@@ -73,6 +73,7 @@ module FriendlyShipping
|
|
73
73
|
url = base_url + RESOURCES[:rates]
|
74
74
|
request = FriendlyShipping::Request.new(
|
75
75
|
url: url,
|
76
|
+
http_method: "POST",
|
76
77
|
body: access_request_xml + rate_request_xml,
|
77
78
|
readable_body: rate_request_xml,
|
78
79
|
debug: debug
|
@@ -95,6 +96,7 @@ module FriendlyShipping
|
|
95
96
|
|
96
97
|
request = FriendlyShipping::Request.new(
|
97
98
|
url: time_in_transit_url,
|
99
|
+
http_method: "POST",
|
98
100
|
body: access_request_xml + time_in_transit_request_xml,
|
99
101
|
readable_body: time_in_transit_request_xml,
|
100
102
|
debug: debug
|
@@ -115,6 +117,7 @@ module FriendlyShipping
|
|
115
117
|
|
116
118
|
ship_confirm_request = FriendlyShipping::Request.new(
|
117
119
|
url: ship_confirm_url,
|
120
|
+
http_method: "POST",
|
118
121
|
body: access_request_xml + ship_confirm_request_xml,
|
119
122
|
readable_body: ship_confirm_request_xml,
|
120
123
|
debug: debug
|
@@ -134,6 +137,7 @@ module FriendlyShipping
|
|
134
137
|
|
135
138
|
ship_accept_request = FriendlyShipping::Request.new(
|
136
139
|
url: ship_accept_url,
|
140
|
+
http_method: "POST",
|
137
141
|
body: access_request_xml + ship_accept_request_xml,
|
138
142
|
readable_body: ship_accept_request_xml,
|
139
143
|
debug: debug
|
@@ -156,6 +160,7 @@ module FriendlyShipping
|
|
156
160
|
url = base_url + RESOURCES[:address_validation]
|
157
161
|
request = FriendlyShipping::Request.new(
|
158
162
|
url: url,
|
163
|
+
http_method: "POST",
|
159
164
|
body: access_request_xml + address_validation_request_xml,
|
160
165
|
readable_body: address_validation_request_xml,
|
161
166
|
debug: debug
|
@@ -174,6 +179,7 @@ module FriendlyShipping
|
|
174
179
|
url = base_url + RESOURCES[:address_validation]
|
175
180
|
request = FriendlyShipping::Request.new(
|
176
181
|
url: url,
|
182
|
+
http_method: "POST",
|
177
183
|
body: access_request_xml + address_validation_request_xml,
|
178
184
|
readable_body: address_validation_request_xml,
|
179
185
|
debug: debug
|
@@ -193,6 +199,7 @@ module FriendlyShipping
|
|
193
199
|
url = base_url + RESOURCES[:city_state_lookup]
|
194
200
|
request = FriendlyShipping::Request.new(
|
195
201
|
url: url,
|
202
|
+
http_method: "POST",
|
196
203
|
body: access_request_xml + city_state_lookup_request_xml,
|
197
204
|
readable_body: city_state_lookup_request_xml,
|
198
205
|
debug: debug
|
@@ -208,6 +215,7 @@ module FriendlyShipping
|
|
208
215
|
void_request_xml = SerializeVoidShipmentRequest.call(label: label)
|
209
216
|
request = FriendlyShipping::Request.new(
|
210
217
|
url: url,
|
218
|
+
http_method: "POST",
|
211
219
|
body: access_request_xml + void_request_xml,
|
212
220
|
readable_body: void_request_xml,
|
213
221
|
debug: debug
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'friendly_shipping/api_error'
|
4
|
+
|
5
|
+
module FriendlyShipping
|
6
|
+
module Services
|
7
|
+
class UpsFreight
|
8
|
+
class ApiError < FriendlyShipping::ApiError
|
9
|
+
# @param [RestClient::Exception] cause
|
10
|
+
def initialize(cause)
|
11
|
+
super cause, parse_message(cause)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# @param [RestClient::Exception] cause
|
17
|
+
def parse_message(cause)
|
18
|
+
parsed_json = JSON.parse(cause.response.body)
|
19
|
+
|
20
|
+
if parsed_json['httpCode'].present?
|
21
|
+
status = [parsed_json['httpCode'], parsed_json['httpMessage']].compact.join(" ")
|
22
|
+
desc = parsed_json['moreInformation']
|
23
|
+
[status, desc].compact.join(": ")
|
24
|
+
else
|
25
|
+
errors = parsed_json.dig('response', 'errors') || []
|
26
|
+
errors.map do |err|
|
27
|
+
status = err['code']
|
28
|
+
desc = err['message']
|
29
|
+
[status, desc].compact.join(": ").presence || "UPS Freight could not process the request."
|
30
|
+
end.join("\n")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|