easypost 4.8.1 → 5.1.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/.gitattributes +5 -0
- data/.github/workflows/ci.yml +34 -5
- data/.gitignore +27 -20
- data/CHANGELOG.md +56 -0
- data/Makefile +30 -11
- data/README.md +111 -45
- data/UPGRADE_GUIDE.md +119 -0
- data/VERSION +1 -1
- data/easypost.gemspec +14 -10
- data/lib/easypost/client.rb +178 -0
- data/lib/easypost/connection.rb +2 -4
- data/lib/easypost/constants.rb +15 -0
- data/lib/easypost/errors/api/api_error.rb +108 -0
- data/lib/easypost/errors/api/bad_request_error.rb +6 -0
- data/lib/easypost/errors/api/connection_error.rb +6 -0
- data/lib/easypost/errors/api/external_api_error.rb +18 -0
- data/lib/easypost/errors/api/forbidden_error.rb +6 -0
- data/lib/easypost/errors/api/gateway_timeout_error.rb +6 -0
- data/lib/easypost/errors/api/internal_server_error.rb +6 -0
- data/lib/easypost/errors/api/invalid_request_error.rb +6 -0
- data/lib/easypost/errors/api/method_not_allowed_error.rb +6 -0
- data/lib/easypost/errors/api/not_found_error.rb +6 -0
- data/lib/easypost/errors/api/payment_error.rb +6 -0
- data/lib/easypost/errors/api/proxy_error.rb +6 -0
- data/lib/easypost/errors/api/rate_limit_error.rb +6 -0
- data/lib/easypost/errors/api/redirect_error.rb +6 -0
- data/lib/easypost/errors/api/retry_error.rb +6 -0
- data/lib/easypost/errors/api/service_unavailable_error.rb +6 -0
- data/lib/easypost/errors/api/ssl_error.rb +6 -0
- data/lib/easypost/errors/api/timeout_error.rb +6 -0
- data/lib/easypost/errors/api/unauthorized_error.rb +6 -0
- data/lib/easypost/errors/api/unknown_api_error.rb +6 -0
- data/lib/easypost/errors/easy_post_error.rb +7 -0
- data/lib/easypost/errors/end_of_pagination_error.rb +7 -0
- data/lib/easypost/errors/filtering_error.rb +4 -0
- data/lib/easypost/errors/invalid_object_error.rb +4 -0
- data/lib/easypost/errors/invalid_parameter_error.rb +11 -0
- data/lib/easypost/errors/missing_parameter_error.rb +9 -0
- data/lib/easypost/errors/signature_verification_error.rb +4 -0
- data/lib/easypost/errors.rb +32 -0
- data/lib/easypost/hooks/request_context.rb +16 -0
- data/lib/easypost/hooks/response_context.rb +23 -0
- data/lib/easypost/hooks.rb +34 -0
- data/lib/easypost/http_client.rb +117 -0
- data/lib/easypost/internal_utilities.rb +66 -0
- data/lib/easypost/models/address.rb +5 -0
- data/lib/easypost/models/api_key.rb +5 -0
- data/lib/easypost/models/base.rb +58 -0
- data/lib/easypost/models/batch.rb +5 -0
- data/lib/easypost/models/brand.rb +5 -0
- data/lib/easypost/{carbon_offset.rb → models/carbon_offset.rb} +1 -1
- data/lib/easypost/models/carrier_account.rb +5 -0
- data/lib/easypost/models/customs_info.rb +5 -0
- data/lib/easypost/models/customs_item.rb +5 -0
- data/lib/easypost/models/end_shipper.rb +5 -0
- data/lib/easypost/models/error.rb +21 -0
- data/lib/easypost/models/event.rb +5 -0
- data/lib/easypost/{insurance.rb → models/insurance.rb} +1 -1
- data/lib/easypost/models/order.rb +9 -0
- data/lib/easypost/models/parcel.rb +5 -0
- data/lib/easypost/models/payload.rb +5 -0
- data/lib/easypost/models/payment_method.rb +5 -0
- data/lib/easypost/models/pickup.rb +9 -0
- data/lib/easypost/{pickup_rate.rb → models/pickup_rate.rb} +1 -1
- data/lib/easypost/{postage_label.rb → models/postage_label.rb} +1 -1
- data/lib/easypost/models/rate.rb +5 -0
- data/lib/easypost/models/referral.rb +5 -0
- data/lib/easypost/{refund.rb → models/refund.rb} +1 -1
- data/lib/easypost/models/report.rb +5 -0
- data/lib/easypost/models/scan_form.rb +6 -0
- data/lib/easypost/models/shipment.rb +10 -0
- data/lib/easypost/{tax_identifier.rb → models/tax_identifier.rb} +1 -1
- data/lib/easypost/models/tracker.rb +5 -0
- data/lib/easypost/models/user.rb +5 -0
- data/lib/easypost/models/webhook.rb +6 -0
- data/lib/easypost/models.rb +35 -0
- data/lib/easypost/services/address.rb +50 -0
- data/lib/easypost/services/api_key.rb +8 -0
- data/lib/easypost/services/base.rb +27 -0
- data/lib/easypost/services/batch.rb +53 -0
- data/lib/easypost/services/beta_rate.rb +12 -0
- data/lib/easypost/services/beta_referral_customer.rb +40 -0
- data/lib/easypost/services/billing.rb +75 -0
- data/lib/easypost/services/carrier_account.rb +44 -0
- data/lib/easypost/services/carrier_metadata.rb +22 -0
- data/lib/easypost/services/customs_info.rb +17 -0
- data/lib/easypost/services/customs_item.rb +15 -0
- data/lib/easypost/services/end_shipper.rb +31 -0
- data/lib/easypost/services/event.rb +32 -0
- data/lib/easypost/services/insurance.rb +26 -0
- data/lib/easypost/services/order.rb +30 -0
- data/lib/easypost/services/parcel.rb +16 -0
- data/lib/easypost/services/pickup.rb +40 -0
- data/lib/easypost/services/rate.rb +8 -0
- data/lib/easypost/services/referral_customer.rb +103 -0
- data/lib/easypost/services/refund.rb +26 -0
- data/lib/easypost/services/report.rb +42 -0
- data/lib/easypost/services/scan_form.rb +25 -0
- data/lib/easypost/services/shipment.rb +106 -0
- data/lib/easypost/services/tracker.rb +38 -0
- data/lib/easypost/services/user.rb +66 -0
- data/lib/easypost/services/webhook.rb +34 -0
- data/lib/easypost/services.rb +32 -0
- data/lib/easypost/util.rb +116 -161
- data/lib/easypost/utilities/constants.rb +5 -0
- data/lib/easypost/utilities/json.rb +23 -0
- data/lib/easypost/utilities/static_mapper.rb +73 -0
- data/lib/easypost/utilities/system.rb +36 -0
- data/lib/easypost.rb +14 -136
- metadata +177 -65
- data/.rubocop.yml +0 -11
- data/CODE_OF_CONDUCT.md +0 -16
- data/CONTRIBUTING.md +0 -47
- data/SECURITY.md +0 -7
- data/SUPPORT.md +0 -3
- data/easycop.yml +0 -180
- data/lib/easypost/address.rb +0 -40
- data/lib/easypost/api_key.rb +0 -5
- data/lib/easypost/batch.rb +0 -50
- data/lib/easypost/beta/end_shipper.rb +0 -44
- data/lib/easypost/beta/referral.rb +0 -110
- data/lib/easypost/beta.rb +0 -7
- data/lib/easypost/billing.rb +0 -72
- data/lib/easypost/brand.rb +0 -13
- data/lib/easypost/carrier_account.rb +0 -9
- data/lib/easypost/carrier_type.rb +0 -5
- data/lib/easypost/customs_info.rb +0 -9
- data/lib/easypost/customs_item.rb +0 -9
- data/lib/easypost/end_shipper.rb +0 -24
- data/lib/easypost/error.rb +0 -32
- data/lib/easypost/event.rb +0 -11
- data/lib/easypost/object.rb +0 -171
- data/lib/easypost/order.rb +0 -37
- data/lib/easypost/parcel.rb +0 -9
- data/lib/easypost/payment_method.rb +0 -11
- data/lib/easypost/pickup.rb +0 -37
- data/lib/easypost/rate.rb +0 -9
- data/lib/easypost/referral.rb +0 -102
- data/lib/easypost/report.rb +0 -23
- data/lib/easypost/resource.rb +0 -106
- data/lib/easypost/scan_form.rb +0 -11
- data/lib/easypost/shipment.rb +0 -155
- data/lib/easypost/tracker.rb +0 -12
- data/lib/easypost/user.rb +0 -71
- data/lib/easypost/webhook.rb +0 -57
data/lib/easypost/shipment.rb
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'set'
|
|
4
|
-
|
|
5
|
-
# The workhorse of the EasyPost API, a Shipment is made up of a "to" and "from" Address, the Parcel
|
|
6
|
-
# being shipped, and any customs forms required for international deliveries.
|
|
7
|
-
class EasyPost::Shipment < EasyPost::Resource
|
|
8
|
-
# Create a Shipment.
|
|
9
|
-
def self.create(params = {}, api_key = nil, with_carbon_offset = false)
|
|
10
|
-
wrapped_params = {
|
|
11
|
-
shipment: params,
|
|
12
|
-
carbon_offset: with_carbon_offset,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
response = EasyPost.make_request(:post, url, api_key, wrapped_params)
|
|
16
|
-
EasyPost::Util.convert_to_easypost_object(response, api_key)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Regenerate the rates of a Shipment.
|
|
20
|
-
def regenerate_rates(with_carbon_offset = false)
|
|
21
|
-
params = {}
|
|
22
|
-
params[:carbon_offset] = with_carbon_offset
|
|
23
|
-
|
|
24
|
-
response = EasyPost.make_request(:post, "#{url}/rerate", @api_key, params)
|
|
25
|
-
refresh_from(response, @api_key)
|
|
26
|
-
|
|
27
|
-
self
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Get the SmartRates of a Shipment.
|
|
31
|
-
def get_smartrates # rubocop:disable Naming/AccessorMethodName
|
|
32
|
-
response = EasyPost.make_request(:get, "#{url}/smartrate", @api_key)
|
|
33
|
-
|
|
34
|
-
response.fetch('result', [])
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Buy a Shipment.
|
|
38
|
-
def buy(params = {}, with_carbon_offset = false, end_shipper_id = nil)
|
|
39
|
-
if params.instance_of?(EasyPost::Rate)
|
|
40
|
-
temp = params.clone
|
|
41
|
-
params = {}
|
|
42
|
-
params[:rate] = temp
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
if params[:with_carbon_offset]
|
|
46
|
-
params[:carbon_offset] = params[:with_carbon_offset]
|
|
47
|
-
params.delete(:with_carbon_offset)
|
|
48
|
-
else
|
|
49
|
-
params[:carbon_offset] = with_carbon_offset
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
if end_shipper_id
|
|
53
|
-
params[:end_shipper_id] = end_shipper_id
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
response = EasyPost.make_request(:post, "#{url}/buy", @api_key, params)
|
|
57
|
-
refresh_from(response, @api_key)
|
|
58
|
-
|
|
59
|
-
self
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Insure a Shipment.
|
|
63
|
-
def insure(params = {})
|
|
64
|
-
if params.is_a?(Integer) || params.is_a?(Float)
|
|
65
|
-
temp = params.clone
|
|
66
|
-
params = {}
|
|
67
|
-
params[:amount] = temp
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
response = EasyPost.make_request(:post, "#{url}/insure", @api_key, params)
|
|
71
|
-
refresh_from(response, @api_key)
|
|
72
|
-
|
|
73
|
-
self
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Refund a Shipment.
|
|
77
|
-
def refund(params = {})
|
|
78
|
-
response = EasyPost.make_request(:get, "#{url}/refund", @api_key, params)
|
|
79
|
-
refresh_from(response, @api_key)
|
|
80
|
-
|
|
81
|
-
self
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Convert the label format of a Shipment.
|
|
85
|
-
def label(params = {})
|
|
86
|
-
if params.is_a?(String)
|
|
87
|
-
temp = params.clone
|
|
88
|
-
params = {}
|
|
89
|
-
params[:file_format] = temp
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
response = EasyPost.make_request(:get, "#{url}/label", @api_key, params)
|
|
93
|
-
refresh_from(response, @api_key)
|
|
94
|
-
|
|
95
|
-
self
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Get the lowest rate of a Shipment (can exclude by having `'!'` as the first element of your optional filter lists).
|
|
99
|
-
def lowest_rate(carriers = [], services = [])
|
|
100
|
-
EasyPost::Util.get_lowest_object_rate(self, carriers, services)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Get the lowest smartrate of a Shipment.
|
|
104
|
-
def lowest_smartrate(delivery_days, delivery_accuracy)
|
|
105
|
-
smartrates = get_smartrates
|
|
106
|
-
EasyPost::Shipment.get_lowest_smartrate(smartrates, delivery_days, delivery_accuracy)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Get the lowest smartrate from a list of smartrates.
|
|
110
|
-
def self.get_lowest_smartrate(smartrates, delivery_days, delivery_accuracy)
|
|
111
|
-
valid_delivery_accuracy_values = Set[
|
|
112
|
-
'percentile_50',
|
|
113
|
-
'percentile_75',
|
|
114
|
-
'percentile_85',
|
|
115
|
-
'percentile_90',
|
|
116
|
-
'percentile_95',
|
|
117
|
-
'percentile_97',
|
|
118
|
-
'percentile_99',
|
|
119
|
-
]
|
|
120
|
-
lowest_smartrate = nil
|
|
121
|
-
|
|
122
|
-
unless valid_delivery_accuracy_values.include?(delivery_accuracy.downcase)
|
|
123
|
-
raise EasyPost::Error.new("Invalid delivery accuracy value, must be one of: #{valid_delivery_accuracy_values}")
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
smartrates.each do |rate|
|
|
127
|
-
next if rate['time_in_transit'][delivery_accuracy] > delivery_days.to_i
|
|
128
|
-
|
|
129
|
-
if lowest_smartrate.nil? || rate['rate'].to_f < lowest_smartrate['rate'].to_f
|
|
130
|
-
lowest_smartrate = rate
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
if lowest_smartrate.nil?
|
|
135
|
-
raise EasyPost::Error.new('No rates found.')
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
lowest_smartrate
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Generate a form for a Shipment.
|
|
142
|
-
def generate_form(form_type, form_options = {})
|
|
143
|
-
params = {}
|
|
144
|
-
params[:type] = form_type
|
|
145
|
-
merged_params = params.merge(form_options)
|
|
146
|
-
wrapped_params = {
|
|
147
|
-
form: merged_params,
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
response = EasyPost.make_request(:post, "#{url}/forms", @api_key, wrapped_params)
|
|
151
|
-
refresh_from(response, @api_key)
|
|
152
|
-
|
|
153
|
-
self
|
|
154
|
-
end
|
|
155
|
-
end
|
data/lib/easypost/tracker.rb
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# A Tracker object contains all of the tracking information for a package.
|
|
4
|
-
class EasyPost::Tracker < EasyPost::Resource
|
|
5
|
-
# Create multiple Tracker objects in bulk.
|
|
6
|
-
def self.create_list(params = {}, api_key = nil)
|
|
7
|
-
url = "#{self.url}/create_list"
|
|
8
|
-
new_params = { 'trackers' => params }
|
|
9
|
-
EasyPost.make_request(:post, url, api_key, new_params)
|
|
10
|
-
true # This endpoint does not return a response so we return true here instead
|
|
11
|
-
end
|
|
12
|
-
end
|
data/lib/easypost/user.rb
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# The User object can be used to manage your own account and to create child accounts.
|
|
4
|
-
class EasyPost::User < EasyPost::Resource
|
|
5
|
-
# Create a child User.
|
|
6
|
-
def self.create(params = {}, api_key = nil)
|
|
7
|
-
response = EasyPost.make_request(:post, url, api_key, { class_name.to_sym => params })
|
|
8
|
-
EasyPost::Util.convert_to_easypost_object(response, api_key)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
# Save (update) a User.
|
|
12
|
-
def save
|
|
13
|
-
if @unsaved_values.length.positive?
|
|
14
|
-
values = {}
|
|
15
|
-
@unsaved_values.each { |k| values[k] = @values[k] }
|
|
16
|
-
|
|
17
|
-
wrapped_params = { user: values }
|
|
18
|
-
|
|
19
|
-
response = EasyPost.make_request(:patch, url, @api_key, wrapped_params)
|
|
20
|
-
refresh_from(response, api_key)
|
|
21
|
-
end
|
|
22
|
-
self
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Delete a User.
|
|
26
|
-
def delete
|
|
27
|
-
EasyPost.make_request(:delete, url, @api_key)
|
|
28
|
-
self
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Retrieve the authenticated User.
|
|
32
|
-
def self.retrieve_me
|
|
33
|
-
all
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Retrieve a list of ApiKey objects.
|
|
37
|
-
def self.all_api_keys
|
|
38
|
-
EasyPost::ApiKey.all
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Retrieve a list of ApiKey objects of a child User.
|
|
42
|
-
def api_keys
|
|
43
|
-
api_keys = EasyPost::User.all_api_keys
|
|
44
|
-
|
|
45
|
-
if api_keys.id == id
|
|
46
|
-
my_api_keys = api_keys.keys
|
|
47
|
-
else
|
|
48
|
-
api_keys.children.each do |child|
|
|
49
|
-
if child.id == id
|
|
50
|
-
my_api_keys = child.keys
|
|
51
|
-
break
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
my_api_keys
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Update the Brand of a User.
|
|
60
|
-
def update_brand(**attrs)
|
|
61
|
-
brand = EasyPost::Brand.new
|
|
62
|
-
data = { object: 'Brand', user_id: id, **attrs }
|
|
63
|
-
# Add accessors manually because there's no API to retrieve a brand
|
|
64
|
-
brand.add_accessors(data.keys)
|
|
65
|
-
# Assigning values with accessors defined above
|
|
66
|
-
data.each do |key, val|
|
|
67
|
-
brand.send("#{key}=", val)
|
|
68
|
-
end
|
|
69
|
-
brand.save
|
|
70
|
-
end
|
|
71
|
-
end
|
data/lib/easypost/webhook.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Each Webhook contains the url which EasyPost will notify whenever an object in our system updates. Several types of objects are processed
|
|
4
|
-
# asynchronously in the EasyPost system, so whenever an object updates, an Event is sent via HTTP POST to each configured webhook URL.
|
|
5
|
-
class EasyPost::Webhook < EasyPost::Resource
|
|
6
|
-
# Update a Webhook.
|
|
7
|
-
def update(params = {})
|
|
8
|
-
# NOTE: This method is redefined here since the "url" method conflicts with the objects field
|
|
9
|
-
unless id
|
|
10
|
-
raise EasyPost::Error.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
instance_url = "#{self.class.url}/#{CGI.escape(id)}"
|
|
14
|
-
|
|
15
|
-
response = EasyPost.make_request(:patch, instance_url, @api_key, params)
|
|
16
|
-
refresh_from(response, api_key)
|
|
17
|
-
|
|
18
|
-
self
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Delete a Webhook.
|
|
22
|
-
def delete
|
|
23
|
-
# NOTE: This method is redefined here since the "url" method conflicts with the objects field
|
|
24
|
-
unless id
|
|
25
|
-
raise EasyPost::Error.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}")
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
instance_url = "#{self.class.url}/#{CGI.escape(id)}"
|
|
29
|
-
|
|
30
|
-
response = EasyPost.make_request(:delete, instance_url, @api_key)
|
|
31
|
-
refresh_from(response, api_key)
|
|
32
|
-
|
|
33
|
-
self
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Validate a webhook by comparing the HMAC signature header sent from EasyPost to your shared secret.
|
|
37
|
-
# If the signatures do not match, an error will be raised signifying the webhook either did not originate
|
|
38
|
-
# from EasyPost or the secrets do not match. If the signatures do match, the `event_body` will be returned
|
|
39
|
-
# as JSON.
|
|
40
|
-
def self.validate_webhook(event_body, headers, webhook_secret)
|
|
41
|
-
easypost_hmac_signature = headers['X-Hmac-Signature']
|
|
42
|
-
|
|
43
|
-
if easypost_hmac_signature.nil?
|
|
44
|
-
raise EasyPost::Error.new('Webhook received does not contain an HMAC signature.')
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
encoded_webhook_secret = webhook_secret.unicode_normalize(:nfkd).encode('utf-8')
|
|
48
|
-
|
|
49
|
-
expected_signature = OpenSSL::HMAC.hexdigest('sha256', encoded_webhook_secret, event_body)
|
|
50
|
-
digest = "hmac-sha256-hex=#{expected_signature}"
|
|
51
|
-
unless digest == easypost_hmac_signature
|
|
52
|
-
raise EasyPost::Error.new('Webhook received did not originate from EasyPost or had a webhook secret mismatch.')
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
JSON.parse(event_body)
|
|
56
|
-
end
|
|
57
|
-
end
|