shipengine_sdk 1.0.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 +7 -0
- data/CHANGELOG.md +8 -0
- data/README.md +96 -0
- data/lib/faraday/raise_http_exception.rb +77 -0
- data/lib/shipengine/configuration.rb +43 -0
- data/lib/shipengine/constants/base.rb +22 -0
- data/lib/shipengine/constants/countries.rb +16 -0
- data/lib/shipengine/constants.rb +4 -0
- data/lib/shipengine/domain/addresses/address_validation.rb +118 -0
- data/lib/shipengine/domain/addresses.rb +76 -0
- data/lib/shipengine/domain/carriers/list_carriers.rb +140 -0
- data/lib/shipengine/domain/carriers.rb +93 -0
- data/lib/shipengine/domain/labels/create_from_rate.rb +163 -0
- data/lib/shipengine/domain/labels/create_from_shipment_details.rb +163 -0
- data/lib/shipengine/domain/labels/void_label.rb +18 -0
- data/lib/shipengine/domain/labels.rb +297 -0
- data/lib/shipengine/domain/rates/get_with_shipment_details.rb +347 -0
- data/lib/shipengine/domain/rates.rb +379 -0
- data/lib/shipengine/domain/tracking/track_using_carrier_code_and_tracking_number.rb +45 -0
- data/lib/shipengine/domain/tracking/track_using_label_id.rb +45 -0
- data/lib/shipengine/domain/tracking.rb +103 -0
- data/lib/shipengine/domain.rb +7 -0
- data/lib/shipengine/exceptions/error_code.rb +254 -0
- data/lib/shipengine/exceptions/error_type.rb +49 -0
- data/lib/shipengine/exceptions.rb +132 -0
- data/lib/shipengine/internal_client.rb +91 -0
- data/lib/shipengine/utils/base58.rb +109 -0
- data/lib/shipengine/utils/pretty_print.rb +29 -0
- data/lib/shipengine/utils/request_id.rb +16 -0
- data/lib/shipengine/utils/user_agent.rb +24 -0
- data/lib/shipengine/utils/validate.rb +106 -0
- data/lib/shipengine/version.rb +5 -0
- data/lib/shipengine.rb +164 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d370ae8b38bb9f56249210fe89f0cbddc5258aee3ab9e820023fadcf90c9f0f5
|
4
|
+
data.tar.gz: de99f00ab5f8c44a9c9efdf051507cf1bc0095c56a4c37cf4480fdb0a1306e05
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fc676b66315b85a71794755904ccc3f97b9bc6b2258b1da034e0f585487dbec81bfd20c0aa84d853e54156996d3656434039395d76245e80bd4506ccd1ad4bbe
|
7
|
+
data.tar.gz: 04d3117b6ae9bf6c19990c1edd34a186c37d94643f771dd1aa0c5e1beee8256e1f3531f3401af9d27cef1602c00340830af33a447e5aca8e22dc0f040a7734d8
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [1.0.3](https://github.com/ShipEngine/shipengine-ruby/compare/v1.0.2...v1.0.3) (2023-06-16)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* Update publish to Gem API Key ([3f9c8e5](https://github.com/ShipEngine/shipengine-ruby/commit/3f9c8e5eec8147e2fb1b38a114fa0e2ff24a5f9e))
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
[](https://shipengine.com)
|
2
|
+
|
3
|
+
ShipEngine Ruby SDK
|
4
|
+
===================
|
5
|
+

|
6
|
+

|
7
|
+
|
8
|
+
The Official Ruby SDK for [ShipEngine API](https://shipengine.com) offering low-level access as well as convenience methods.
|
9
|
+
|
10
|
+
Quick Start
|
11
|
+
===========
|
12
|
+
|
13
|
+
Install ShipEngine via [RubyGems](https://rubygems.org/)
|
14
|
+
```bash
|
15
|
+
gem install shipengine_sdk
|
16
|
+
```
|
17
|
+
- The only configuration requirement is an [API Key](https://www.shipengine.com/docs/auth/#api-keys).
|
18
|
+
|
19
|
+
Methods
|
20
|
+
-------
|
21
|
+
* [`create_label_from_rate`](./docs/create-label-from-rate.md) - When retrieving rates for shipments using the `get_rates` method, the returned information contains a `rate_id` property that can be used to purchase a label without having to refill in the shipment information repeatedly.
|
22
|
+
* [`create_label_from_shipment_details`](./docs/create-label-from-shipment-details.md) - Purchase and print a label for shipment.
|
23
|
+
* [`get_rates`](./docs/get-rates.md) - Given some shipment details and rate options, this method returns a list of rate quotes.
|
24
|
+
* [`list_carrier_accounts`](./docs/list-carrier-accounts.md) - Returns a list of carrier accounts that have been connected through
|
25
|
+
the [ShipEngine dashboard](https://www.shipengine.com/docs/carriers/setup/).
|
26
|
+
* [`track_by_label_id`](./docs/track-by-label-id.md) - Track a package by its associated label ID.
|
27
|
+
* [`track_using_carrier_code_and_tracking_number`](./docs/track-by-tracking-number.md) - Track a package by its associated trackng number.
|
28
|
+
* [`validate_addresses`](./docs/validate-addresses.md) - Indicates whether the provided addresses are valid. If the addresses are valid, the method returns a normalized version based on the standards of the country in which the address resides. If an address cannot be normalized, an error is returned.
|
29
|
+
* [`void_label_by_id`](./docs/void-label-by-id.md) - Void a label by its ID.
|
30
|
+
|
31
|
+
Class Objects
|
32
|
+
-------------
|
33
|
+
- [ShipEngine]() - A configurable entry point to the ShipEngine API SDK, this class provides convenience methods
|
34
|
+
for various ShipEngine API Services.
|
35
|
+
|
36
|
+
Instantiate ShipEngine Class
|
37
|
+
----------------------------
|
38
|
+
```ruby
|
39
|
+
require "shipengine"
|
40
|
+
|
41
|
+
api_key = ENV["SHIPENGINE_API_KEY"]
|
42
|
+
|
43
|
+
shipengine = ShipEngine.new(api_key)
|
44
|
+
```
|
45
|
+
|
46
|
+
Contributing
|
47
|
+
============
|
48
|
+
|
49
|
+
Install dependencies
|
50
|
+
--------------------
|
51
|
+
- You will need to `gem install bundler` before using the following command to install dependencies from the Gemfile.
|
52
|
+
```bash
|
53
|
+
./bin/setup
|
54
|
+
```
|
55
|
+
|
56
|
+
Committing
|
57
|
+
-------------------------
|
58
|
+
This project adheres to the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.
|
59
|
+
|
60
|
+
Pre-Commit/Pre-Push Hooks
|
61
|
+
-------------------------
|
62
|
+
This project makes use of [Overcommit](https://github.com/sds/overcommit#usage) to enforce `pre-commit/push hooks`.
|
63
|
+
Overcommit will be downloaded and initialized as part of running the `./bin/setup` script, as outlined in the previous section.
|
64
|
+
|
65
|
+
- From then on when you commit code `rake lint` will run, and when you push code `rake test` and `rake lint` will run.
|
66
|
+
Upon failure of either of these, you can run `rake fix` to auto-fix lint issues and format code, and re-commit/push.
|
67
|
+
|
68
|
+
Testing & Development
|
69
|
+
---------------------
|
70
|
+
- While you are writing tests as you contribute code you can run tests ad-hoc via `rake` using the following command:
|
71
|
+
```bash
|
72
|
+
rake test
|
73
|
+
```
|
74
|
+
- You can run tests and have them re-run when you save changes to a given file with `guard`.
|
75
|
+
```bash
|
76
|
+
guard
|
77
|
+
```
|
78
|
+
Lastly, you can `format code & auto-fix lint errors` with the following:
|
79
|
+
```bash
|
80
|
+
rake fix
|
81
|
+
```
|
82
|
+
|
83
|
+
> Note: `guard` also provides a repl after tests run for quick repl development.
|
84
|
+
|
85
|
+
Repl Development
|
86
|
+
----------------
|
87
|
+
- You can start a `pry` repl that already has `shipengine` required bun running the following command.
|
88
|
+
```bash
|
89
|
+
./bin/console
|
90
|
+
```
|
91
|
+
> If you prefer `irb` over `pry`, you can follow the instructions in the [./bin/console](./bin/console) file. Please
|
92
|
+
DO NOT commit any changes you make to that file, unless they are improvements to the console workflow.
|
93
|
+
|
94
|
+
Publishing
|
95
|
+
-------------------------
|
96
|
+
Publishing new versions of the SDK to [RubyGems](https://rubygems.org/) is handled on GitHub via the [Release Please](https://github.com/googleapis/release-please) GitHub Actions workflow. Learn more about about Release PRs, updating the changelog, and commit messages [here](https://github.com/googleapis/release-please#how-should-i-write-my-commits).
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
# @private
|
5
|
+
module FaradayMiddleware
|
6
|
+
# @private
|
7
|
+
class RaiseHttpException < Faraday::Middleware
|
8
|
+
def call(env)
|
9
|
+
@app.call(env).on_complete do |response|
|
10
|
+
case response[:status].to_i
|
11
|
+
when 400, 401, 404, 500, 502, 503, 504
|
12
|
+
raise ShipEngine::Exceptions::ShipEngineError.new(
|
13
|
+
message: error_body(response[:body]),
|
14
|
+
source: error_source(response[:body]),
|
15
|
+
type: error_type(response[:body]),
|
16
|
+
code: error_code(response[:body]),
|
17
|
+
request_id: response[:body]['request_id'],
|
18
|
+
url: response[:url].to_s
|
19
|
+
)
|
20
|
+
when 429
|
21
|
+
raise ShipEngine::Exceptions::RateLimitError.new(retries: env.request_headers['Retries'].to_i, source: error_source(response[:body]), request_id: response[:body]['request_id'])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(app)
|
27
|
+
super(app)
|
28
|
+
@parser = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def error_message_400(response) # rubocop:todo Naming/VariableNumber
|
34
|
+
"#{response[:method].to_s.upcase} #{response[:url]}: #{response[:status]}#{error_body(response[:body])}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def error_body(body)
|
38
|
+
body = ::JSON.parse(body) if !body.nil? && !body.empty? && body.is_a?(String)
|
39
|
+
|
40
|
+
if body.nil?
|
41
|
+
nil
|
42
|
+
elsif body['errors'] && !body['errors'].empty?
|
43
|
+
body['errors'][0]['message']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def error_source(body)
|
48
|
+
body = ::JSON.parse(body) if !body.nil? && !body.empty? && body.is_a?(String)
|
49
|
+
|
50
|
+
if body.nil?
|
51
|
+
nil
|
52
|
+
elsif body['errors'] && !body['errors'].empty?
|
53
|
+
body['errors'][0]['error_source']
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def error_type(body)
|
58
|
+
body = ::JSON.parse(body) if !body.nil? && !body.empty? && body.is_a?(String)
|
59
|
+
|
60
|
+
if body.nil?
|
61
|
+
nil
|
62
|
+
elsif body['errors'] && !body['errors'].empty?
|
63
|
+
body['errors'][0]['error_type']
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def error_code(body)
|
68
|
+
body = ::JSON.parse(body) if !body.nil? && !body.empty? && body.is_a?(String)
|
69
|
+
|
70
|
+
if body.nil?
|
71
|
+
nil
|
72
|
+
elsif body['errors'] && !body['errors'].empty?
|
73
|
+
body['errors'][0]['error_code']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShipEngine
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :api_key, :retries, :base_url, :timeout, :page_size
|
6
|
+
|
7
|
+
def initialize(api_key:, retries: nil, timeout: nil, page_size: nil, base_url: nil)
|
8
|
+
@api_key = api_key
|
9
|
+
@base_url = base_url || Constants.base_url
|
10
|
+
@retries = retries || 1
|
11
|
+
@timeout = timeout || 30_000
|
12
|
+
@page_size = page_size || 50
|
13
|
+
validate
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param opts [Hash] the options to create a message with.
|
17
|
+
# @option opts [String] :ap The subject
|
18
|
+
# @option opts [String] :from ('nobody') From address
|
19
|
+
# @option opts [String] :to Recipient email
|
20
|
+
# @option opts [String] :body ('') The email's bod
|
21
|
+
def merge(config)
|
22
|
+
copy = clone
|
23
|
+
copy.api_key = config[:api_key] if config.key?(:api_key)
|
24
|
+
copy.base_url = config[:base_url] if config.key?(:base_url)
|
25
|
+
copy.retries = config[:retries] if config.key?(:retries)
|
26
|
+
copy.timeout = config[:timeout] if config.key?(:timeout)
|
27
|
+
copy.page_size = config[:page_size] if config.key?(:page_size)
|
28
|
+
copy.validate
|
29
|
+
copy
|
30
|
+
end
|
31
|
+
|
32
|
+
# since the fields in the class are mutable, we should be able to validate them at any time.
|
33
|
+
protected
|
34
|
+
|
35
|
+
def validate
|
36
|
+
Utils::Validate.str('A ShipEngine API key', @api_key)
|
37
|
+
Utils::Validate.str('Base URL', @base_url)
|
38
|
+
Utils::Validate.non_neg_int('Retries', @retries)
|
39
|
+
Utils::Validate.positive_int('Timeout', @timeout)
|
40
|
+
Utils::Validate.positive_int('Page size', @page_size)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShipEngine
|
4
|
+
module Constants
|
5
|
+
# A stub API Key to use in the test suite.
|
6
|
+
API_KEY = 'TEST_ycvJAgX6tLB1Awm9WGJmD8mpZ8wXiQ20WhqFowCk32s'
|
7
|
+
|
8
|
+
# The base_url for the ShipEngine SDK - for use in production environment.
|
9
|
+
PROD_URL = 'https://api.shipengine.com'
|
10
|
+
|
11
|
+
# Regex pattern to match a valid *ISO-8601* string with timezone.
|
12
|
+
VALID_ISO_STRING = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$/
|
13
|
+
|
14
|
+
# Regex pattern to match a valid *ISO-8601* string with no timezone.
|
15
|
+
VALID_ISO_STRING_WITH_NO_TZ = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?([+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$/
|
16
|
+
|
17
|
+
# Check env variables to set the appropriate base_url.
|
18
|
+
def self.base_url
|
19
|
+
ShipEngine::Constants::PROD_URL
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShipEngine
|
4
|
+
module Constants
|
5
|
+
class Country
|
6
|
+
# rubocop:disable Layout/LineLength
|
7
|
+
@countries = %w[AF AX AL DZ AS AD AO AI AQ AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM BT BO BA BW BV BR IO BN BG BF BI KH CM CA CV KY CF TD CL CN CX CC CO KM CG CD CK CR CI HR CU CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI FR GF PF TF GA GM GE DE GH GI GR GL GD GP GU GT GG GN GW GY HT HM VA HN HK HU IS IN ID IR IQ IE IM IL IT JM JP JE JO KZ KE KI KR KW KG LA LV LB LS LR LY LI LT LU MO MK MG MW MY MV ML MT MH MQ MR MU YT MX FM MD MC MN ME MS MA MZ MM NA NR NP NL NC NZ NI NE NG NU NF MP NO OM PK PW PS PA PG PY PE PH PN PL PT PR QA RE RO RU RW BL SH KN LC MF PM VC WS SM ST SA SN RS SC SL SG SK SI SB SO ZA GS ES LK SD SR SJ SZ SE CH SY TW TJ TZ TH TL TG TK TO TT TN TR TM TC TV UG UA AE GB US UM UY UZ VU VE VN VG VI WF EH YE ZM ZW].freeze
|
8
|
+
# rubocop:enable Layout/LineLength
|
9
|
+
|
10
|
+
# @param [String] country - 2 letter country code
|
11
|
+
def self.valid?(country)
|
12
|
+
@countries.include?(country.upcase)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShipEngine
|
4
|
+
module Domain
|
5
|
+
class Addresses
|
6
|
+
module AddressValidation
|
7
|
+
class Response
|
8
|
+
attr_reader :status, :original_address, :matched_address, :messages
|
9
|
+
|
10
|
+
# type ["unverified" | "verified" | "warning" | "error"] status
|
11
|
+
# @param [NormalizedAddress] original_address
|
12
|
+
# @param [NormalizedAddress?] matched_address
|
13
|
+
# @param [Array<Response>] messages
|
14
|
+
def initialize(status:, original_address:, matched_address:, messages:)
|
15
|
+
@status = status
|
16
|
+
@original_address = original_address
|
17
|
+
@matched_address = matched_address
|
18
|
+
@messages = messages
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Request
|
23
|
+
attr_reader :address_line1,
|
24
|
+
:address_line2,
|
25
|
+
:address_line3,
|
26
|
+
:name,
|
27
|
+
:company_name,
|
28
|
+
:phone,
|
29
|
+
:city_locality,
|
30
|
+
:state_province,
|
31
|
+
:postal_code,
|
32
|
+
:country_code,
|
33
|
+
:address_residential_indicator
|
34
|
+
|
35
|
+
# @param [String] address_line1 - e.g. ["123 FAKE ST."]
|
36
|
+
# @param [String?] address_line2 - e.g. ["123 FAKE ST."]
|
37
|
+
# @param [String?] address_line3 - e.g. ["123 FAKE ST."]
|
38
|
+
# @param [String] country_code - e.g. "US". @see https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
|
39
|
+
# @param [String] postal_code - e.g "78751"
|
40
|
+
# @param [String?] name - e.g. "John Smith"
|
41
|
+
# @param [String?] company_name - e.g. "ShipEngine"
|
42
|
+
# @param [String?] phone - e.g. 5551234567
|
43
|
+
# @param [String?] city_locality - e.g. "AUSTIN"
|
44
|
+
# @param [String?] state_province - e.g. "TX"
|
45
|
+
# @param [String?] address_residential_indicator
|
46
|
+
def initialize(address_line1:, address_line2:, address_line3:, name:, company_name:, phone:, city_locality:, state_province:, postal_code:, # rubocop:todo Metrics/ParameterLists
|
47
|
+
country_code:, address_residential_indicator:)
|
48
|
+
|
49
|
+
@name = name
|
50
|
+
@company_name = company_name
|
51
|
+
@address_line1 = address_line1
|
52
|
+
@address_line2 = address_line2
|
53
|
+
@address_line3 = address_line3
|
54
|
+
@phone = phone
|
55
|
+
@city_locality = city_locality
|
56
|
+
@state_province = state_province
|
57
|
+
@postal_code = postal_code
|
58
|
+
@country_code = country_code
|
59
|
+
@address_residential_indicator = address_residential_indicator
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Address
|
64
|
+
attr_reader :address_line1,
|
65
|
+
:address_line2,
|
66
|
+
:address_line3,
|
67
|
+
:name,
|
68
|
+
:company_name,
|
69
|
+
:phone,
|
70
|
+
:city_locality,
|
71
|
+
:state_province,
|
72
|
+
:postal_code,
|
73
|
+
:country_code,
|
74
|
+
:address_residential_indicator
|
75
|
+
|
76
|
+
# @param [String] address_line1 - e.g. ["123 FAKE ST."]
|
77
|
+
# @param [String?] address_line2 - e.g. ["123 FAKE ST."]
|
78
|
+
# @param [String?] address_line3 - e.g. ["123 FAKE ST."]
|
79
|
+
# @param [String] country_code - e.g. "US". @see https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
|
80
|
+
# @param [String] postal_code - e.g "78751"
|
81
|
+
# @param [String?] name - e.g. "John Smith"
|
82
|
+
# @param [String?] company_name - e.g. "ShipEngine"
|
83
|
+
# @param [String?] phone - e.g. 5551234567
|
84
|
+
# @param [String?] city_locality - e.g. "AUSTIN"
|
85
|
+
# @param [String?] state_province - e.g. "TX"
|
86
|
+
# @param [String?] address_residential_indicator
|
87
|
+
def initialize(address_line1:, address_line2:, address_line3:, name:, company_name:, phone:, city_locality:, state_province:, postal_code:, # rubocop:todo Metrics/ParameterLists
|
88
|
+
country_code:, address_residential_indicator:)
|
89
|
+
|
90
|
+
@name = name
|
91
|
+
@company_name = company_name
|
92
|
+
@address_line1 = address_line1
|
93
|
+
@address_line2 = address_line2
|
94
|
+
@address_line3 = address_line3
|
95
|
+
@phone = phone
|
96
|
+
@city_locality = city_locality
|
97
|
+
@state_province = state_province
|
98
|
+
@postal_code = postal_code
|
99
|
+
@country_code = country_code
|
100
|
+
@address_residential_indicator = address_residential_indicator
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Message
|
105
|
+
attr_reader :type, :code, :message
|
106
|
+
|
107
|
+
# @param type [:info" | :warning | :error"]
|
108
|
+
# @param code [String] = e.g. "suite_missing"
|
109
|
+
def initialize(type:, code:, message:)
|
110
|
+
@type = type
|
111
|
+
@code = code
|
112
|
+
@message = message
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'hashie'
|
4
|
+
require_relative 'addresses/address_validation'
|
5
|
+
|
6
|
+
module ShipEngine
|
7
|
+
module Domain
|
8
|
+
class Addresses
|
9
|
+
require 'shipengine/constants'
|
10
|
+
|
11
|
+
# @param [ShipEngine::InternalClient] internal_client
|
12
|
+
def initialize(internal_client)
|
13
|
+
@internal_client = internal_client
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param addresses [ShipEngine::Domain::Addresses::AddressValidationRequest]
|
17
|
+
# @param config [Hash?]
|
18
|
+
#
|
19
|
+
# @return [Array<ShipEngine::Domain::Addresses::AddressValidationResponse>]
|
20
|
+
#
|
21
|
+
# @see https://shipengine.github.io/shipengine-openapi/#operation/validate_address
|
22
|
+
def validate(addresses, config)
|
23
|
+
addresses_array = addresses.map(&:compact)
|
24
|
+
|
25
|
+
response = @internal_client.post('/v1/addresses/validate', addresses_array, config)
|
26
|
+
address_api_result = response.body
|
27
|
+
|
28
|
+
address_api_result.map do |result|
|
29
|
+
mash_result = Hashie::Mash.new(result)
|
30
|
+
normalized_original_address_api_result = AddressValidation::Address.new(
|
31
|
+
address_line1: mash_result.original_address.address_line1,
|
32
|
+
address_line2: mash_result.original_address.address_line2,
|
33
|
+
address_line3: mash_result.original_address.address_line3,
|
34
|
+
name: mash_result.original_address.name,
|
35
|
+
company_name: mash_result.original_address.company_name,
|
36
|
+
phone: mash_result.original_address.phone,
|
37
|
+
city_locality: mash_result.original_address.city_locality,
|
38
|
+
state_province: mash_result.original_address.state_province,
|
39
|
+
postal_code: mash_result.original_address.postal_code,
|
40
|
+
country_code: mash_result.original_address.country_code,
|
41
|
+
address_residential_indicator: mash_result.original_address.address_residential_indicator
|
42
|
+
)
|
43
|
+
|
44
|
+
normalized_matched_address_api_result = if mash_result.matched_address
|
45
|
+
AddressValidation::Address.new(
|
46
|
+
address_line1: mash_result.matched_address.address_line1,
|
47
|
+
address_line2: mash_result.matched_address.address_line2,
|
48
|
+
address_line3: mash_result.matched_address.address_line3,
|
49
|
+
name: mash_result.matched_address.name,
|
50
|
+
company_name: mash_result.matched_address.company_name,
|
51
|
+
phone: mash_result.matched_address.phone,
|
52
|
+
city_locality: mash_result.matched_address.city_locality,
|
53
|
+
state_province: mash_result.matched_address.state_province,
|
54
|
+
postal_code: mash_result.matched_address.postal_code,
|
55
|
+
country_code: mash_result.matched_address.country_code,
|
56
|
+
address_residential_indicator: mash_result.matched_address.address_residential_indicator
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
status = mash_result.status
|
61
|
+
|
62
|
+
messages_classes = mash_result.messages.map do |msg|
|
63
|
+
AddressValidation::Message.new(type: msg['type'], code: msg['code'], message: msg['message'])
|
64
|
+
end
|
65
|
+
|
66
|
+
AddressValidation::Response.new(
|
67
|
+
status:,
|
68
|
+
messages: messages_classes,
|
69
|
+
original_address: normalized_original_address_api_result,
|
70
|
+
matched_address: normalized_matched_address_api_result
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShipEngine
|
4
|
+
module Domain
|
5
|
+
class Carriers
|
6
|
+
module ListCarriers
|
7
|
+
class Response
|
8
|
+
attr_reader :carriers, :request_id, :errors
|
9
|
+
|
10
|
+
# @param [Carrier] carriers
|
11
|
+
# @param [String?] request_id
|
12
|
+
# @param [Array<Error>?] carriers
|
13
|
+
def initialize(carriers:, request_id:, errors:)
|
14
|
+
@carriers = carriers
|
15
|
+
@request_id = request_id
|
16
|
+
@errors = errors
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Error
|
21
|
+
attr_reader :error_source, :error_type, :error_code, :message
|
22
|
+
|
23
|
+
# type ["carrier" | "order_source" | "shipengine"] error_source
|
24
|
+
# type ["account_status" | "business_rules" | "validation" | "security" | "system" | "integrations"] error_type
|
25
|
+
# @param [String] error_code
|
26
|
+
# @param [String] message
|
27
|
+
def initialize(error_source:, error_type:, error_code:, message:)
|
28
|
+
@error_source = error_source
|
29
|
+
@error_type = error_type
|
30
|
+
@error_code = error_code
|
31
|
+
@message = message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Carrier
|
36
|
+
attr_reader :carrier_id, :carrier_code, :account_number, :requires_funded_amount, :balance, :nickname, :friendly_name, :primary, :has_multi_package_supporting_services, :supports_label_messages, :services, :packages, :options
|
37
|
+
|
38
|
+
# @param [String] carrier_id - e.g. "se-28529731"
|
39
|
+
# @param [String] carrier_code - e.g. "se-28529731"
|
40
|
+
# @param [String] account_number - e.g. "account_570827"
|
41
|
+
# @param [Boolean] requires_funded_amount - e.g. true
|
42
|
+
# @param [Float] balance - e.g. 3799.52
|
43
|
+
# @param [String] nickname - e.g. "ShipEngine Account - Stamps.com"
|
44
|
+
# @param [String] friendly_name - e.g. "Stamps.com",
|
45
|
+
# @param [Boolean] primary - e.g. true,
|
46
|
+
# @param [Boolean] has_multi_package_supporting_services - e.g. true,
|
47
|
+
# @param [Boolean] supports_label_messages - e.g. true,
|
48
|
+
# @param [Array<Carrier::Service>] services
|
49
|
+
# @param [Array<Carrier::Package>] packages
|
50
|
+
# @param [Array<Carrier::Option>] options
|
51
|
+
def initialize(carrier_id:, carrier_code:, account_number:, requires_funded_amount:, balance:, nickname:, friendly_name:, primary:, has_multi_package_supporting_services:, supports_label_messages:, services:, packages:, options:) # rubocop:todo Metrics/ParameterLists
|
52
|
+
@carrier_id = carrier_id
|
53
|
+
@carrier_code = carrier_code
|
54
|
+
@account_number = account_number
|
55
|
+
@requires_funded_amount = requires_funded_amount
|
56
|
+
@balance = balance
|
57
|
+
@nickname = nickname
|
58
|
+
@friendly_name = friendly_name
|
59
|
+
@primary = primary
|
60
|
+
@has_multi_package_supporting_services = has_multi_package_supporting_services
|
61
|
+
@supports_label_messages = supports_label_messages
|
62
|
+
@services = services
|
63
|
+
@packages = packages
|
64
|
+
@options = options
|
65
|
+
end
|
66
|
+
|
67
|
+
class Service
|
68
|
+
attr_reader :carrier_id, :carrier_code, :service_code, :name, :domestic, :international, :is_multi_package_supported
|
69
|
+
|
70
|
+
# @param [String] carrier_id - e.g. "se-28529731"
|
71
|
+
# @param [String] carrier_code - e.g. "se-28529731"
|
72
|
+
# @param [String] service_code - e.g. "usps_media_mail"
|
73
|
+
# @param [String] name - e.g. "USPS First Class Mail"
|
74
|
+
# @param [Boolean] domestic - e.g. true
|
75
|
+
# @param [Boolean] international - e.g. true
|
76
|
+
# @param [Boolean] is_multi_package_supported - e.g. true
|
77
|
+
|
78
|
+
def initialize(carrier_id:, carrier_code:, service_code:, name:, domestic:, international:, is_multi_package_supported:) # rubocop:todo Metrics/ParameterLists
|
79
|
+
@carrier_id = carrier_id
|
80
|
+
@carrier_code = carrier_code
|
81
|
+
@service_code = service_code
|
82
|
+
@name = name
|
83
|
+
@domestic = domestic
|
84
|
+
@international = international
|
85
|
+
@is_multi_package_supported = is_multi_package_supported
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Package
|
90
|
+
attr_reader :package_id, :package_code, :name, :dimensions, :description
|
91
|
+
|
92
|
+
# @param [String?] package_id - e.g. "se-28529731"
|
93
|
+
# @param [String] package_code - e.g. "small_flat_rate_box"
|
94
|
+
# @param [name] name - e.g. "laptop_box"
|
95
|
+
# @param [Package::Dimensions?] dimensions - e.g. true
|
96
|
+
# @param [String?] description - e.g. true
|
97
|
+
|
98
|
+
def initialize(package_id:, package_code:, name:, dimensions:, description:)
|
99
|
+
@package_id = package_id
|
100
|
+
@package_code = package_code
|
101
|
+
@name = name
|
102
|
+
@dimensions = dimensions
|
103
|
+
@description = description
|
104
|
+
end
|
105
|
+
|
106
|
+
class Dimensions
|
107
|
+
attr_reader :unit, :length, :width, :height
|
108
|
+
|
109
|
+
# type ["inch" | "centimeter"] unit
|
110
|
+
# @param [Double] length - e.g. 1.0
|
111
|
+
# @param [Double] width - e.g. 1.0
|
112
|
+
# @param [Double] height - e.g. 1.0
|
113
|
+
|
114
|
+
def initialize(unit:, length:, width:, height:)
|
115
|
+
@unit = unit
|
116
|
+
@length = length
|
117
|
+
@width = width
|
118
|
+
@height = height
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Option
|
124
|
+
attr_reader :name, :default_value, :description
|
125
|
+
|
126
|
+
# @param [String] name - e.g. "contains_alcohol"
|
127
|
+
# @param [String] default_value - e.g. "false"
|
128
|
+
# @param [String?] description - e.g. "Option"
|
129
|
+
|
130
|
+
def initialize(name:, default_value:, description:)
|
131
|
+
@name = name
|
132
|
+
@default_value = default_value
|
133
|
+
@description = description
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|