easypost 4.8.1 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +5 -0
  3. data/.github/workflows/ci.yml +34 -5
  4. data/.gitignore +27 -20
  5. data/CHANGELOG.md +56 -0
  6. data/Makefile +30 -11
  7. data/README.md +111 -45
  8. data/UPGRADE_GUIDE.md +119 -0
  9. data/VERSION +1 -1
  10. data/easypost.gemspec +14 -10
  11. data/lib/easypost/client.rb +178 -0
  12. data/lib/easypost/connection.rb +2 -4
  13. data/lib/easypost/constants.rb +15 -0
  14. data/lib/easypost/errors/api/api_error.rb +108 -0
  15. data/lib/easypost/errors/api/bad_request_error.rb +6 -0
  16. data/lib/easypost/errors/api/connection_error.rb +6 -0
  17. data/lib/easypost/errors/api/external_api_error.rb +18 -0
  18. data/lib/easypost/errors/api/forbidden_error.rb +6 -0
  19. data/lib/easypost/errors/api/gateway_timeout_error.rb +6 -0
  20. data/lib/easypost/errors/api/internal_server_error.rb +6 -0
  21. data/lib/easypost/errors/api/invalid_request_error.rb +6 -0
  22. data/lib/easypost/errors/api/method_not_allowed_error.rb +6 -0
  23. data/lib/easypost/errors/api/not_found_error.rb +6 -0
  24. data/lib/easypost/errors/api/payment_error.rb +6 -0
  25. data/lib/easypost/errors/api/proxy_error.rb +6 -0
  26. data/lib/easypost/errors/api/rate_limit_error.rb +6 -0
  27. data/lib/easypost/errors/api/redirect_error.rb +6 -0
  28. data/lib/easypost/errors/api/retry_error.rb +6 -0
  29. data/lib/easypost/errors/api/service_unavailable_error.rb +6 -0
  30. data/lib/easypost/errors/api/ssl_error.rb +6 -0
  31. data/lib/easypost/errors/api/timeout_error.rb +6 -0
  32. data/lib/easypost/errors/api/unauthorized_error.rb +6 -0
  33. data/lib/easypost/errors/api/unknown_api_error.rb +6 -0
  34. data/lib/easypost/errors/easy_post_error.rb +7 -0
  35. data/lib/easypost/errors/end_of_pagination_error.rb +7 -0
  36. data/lib/easypost/errors/filtering_error.rb +4 -0
  37. data/lib/easypost/errors/invalid_object_error.rb +4 -0
  38. data/lib/easypost/errors/invalid_parameter_error.rb +11 -0
  39. data/lib/easypost/errors/missing_parameter_error.rb +9 -0
  40. data/lib/easypost/errors/signature_verification_error.rb +4 -0
  41. data/lib/easypost/errors.rb +32 -0
  42. data/lib/easypost/hooks/request_context.rb +16 -0
  43. data/lib/easypost/hooks/response_context.rb +23 -0
  44. data/lib/easypost/hooks.rb +34 -0
  45. data/lib/easypost/http_client.rb +117 -0
  46. data/lib/easypost/internal_utilities.rb +66 -0
  47. data/lib/easypost/models/address.rb +5 -0
  48. data/lib/easypost/models/api_key.rb +5 -0
  49. data/lib/easypost/models/base.rb +58 -0
  50. data/lib/easypost/models/batch.rb +5 -0
  51. data/lib/easypost/models/brand.rb +5 -0
  52. data/lib/easypost/{carbon_offset.rb → models/carbon_offset.rb} +1 -1
  53. data/lib/easypost/models/carrier_account.rb +5 -0
  54. data/lib/easypost/models/customs_info.rb +5 -0
  55. data/lib/easypost/models/customs_item.rb +5 -0
  56. data/lib/easypost/models/end_shipper.rb +5 -0
  57. data/lib/easypost/models/error.rb +21 -0
  58. data/lib/easypost/models/event.rb +5 -0
  59. data/lib/easypost/{insurance.rb → models/insurance.rb} +1 -1
  60. data/lib/easypost/models/order.rb +9 -0
  61. data/lib/easypost/models/parcel.rb +5 -0
  62. data/lib/easypost/models/payload.rb +5 -0
  63. data/lib/easypost/models/payment_method.rb +5 -0
  64. data/lib/easypost/models/pickup.rb +9 -0
  65. data/lib/easypost/{pickup_rate.rb → models/pickup_rate.rb} +1 -1
  66. data/lib/easypost/{postage_label.rb → models/postage_label.rb} +1 -1
  67. data/lib/easypost/models/rate.rb +5 -0
  68. data/lib/easypost/models/referral.rb +5 -0
  69. data/lib/easypost/{refund.rb → models/refund.rb} +1 -1
  70. data/lib/easypost/models/report.rb +5 -0
  71. data/lib/easypost/models/scan_form.rb +6 -0
  72. data/lib/easypost/models/shipment.rb +10 -0
  73. data/lib/easypost/{tax_identifier.rb → models/tax_identifier.rb} +1 -1
  74. data/lib/easypost/models/tracker.rb +5 -0
  75. data/lib/easypost/models/user.rb +5 -0
  76. data/lib/easypost/models/webhook.rb +6 -0
  77. data/lib/easypost/models.rb +35 -0
  78. data/lib/easypost/services/address.rb +50 -0
  79. data/lib/easypost/services/api_key.rb +8 -0
  80. data/lib/easypost/services/base.rb +27 -0
  81. data/lib/easypost/services/batch.rb +53 -0
  82. data/lib/easypost/services/beta_rate.rb +12 -0
  83. data/lib/easypost/services/beta_referral_customer.rb +40 -0
  84. data/lib/easypost/services/billing.rb +75 -0
  85. data/lib/easypost/services/carrier_account.rb +44 -0
  86. data/lib/easypost/services/carrier_metadata.rb +22 -0
  87. data/lib/easypost/services/customs_info.rb +17 -0
  88. data/lib/easypost/services/customs_item.rb +15 -0
  89. data/lib/easypost/services/end_shipper.rb +31 -0
  90. data/lib/easypost/services/event.rb +32 -0
  91. data/lib/easypost/services/insurance.rb +26 -0
  92. data/lib/easypost/services/order.rb +30 -0
  93. data/lib/easypost/services/parcel.rb +16 -0
  94. data/lib/easypost/services/pickup.rb +40 -0
  95. data/lib/easypost/services/rate.rb +8 -0
  96. data/lib/easypost/services/referral_customer.rb +103 -0
  97. data/lib/easypost/services/refund.rb +26 -0
  98. data/lib/easypost/services/report.rb +42 -0
  99. data/lib/easypost/services/scan_form.rb +25 -0
  100. data/lib/easypost/services/shipment.rb +106 -0
  101. data/lib/easypost/services/tracker.rb +38 -0
  102. data/lib/easypost/services/user.rb +66 -0
  103. data/lib/easypost/services/webhook.rb +34 -0
  104. data/lib/easypost/services.rb +32 -0
  105. data/lib/easypost/util.rb +116 -161
  106. data/lib/easypost/utilities/constants.rb +5 -0
  107. data/lib/easypost/utilities/json.rb +23 -0
  108. data/lib/easypost/utilities/static_mapper.rb +73 -0
  109. data/lib/easypost/utilities/system.rb +36 -0
  110. data/lib/easypost.rb +14 -136
  111. metadata +177 -65
  112. data/.rubocop.yml +0 -11
  113. data/CODE_OF_CONDUCT.md +0 -16
  114. data/CONTRIBUTING.md +0 -47
  115. data/SECURITY.md +0 -7
  116. data/SUPPORT.md +0 -3
  117. data/easycop.yml +0 -180
  118. data/lib/easypost/address.rb +0 -40
  119. data/lib/easypost/api_key.rb +0 -5
  120. data/lib/easypost/batch.rb +0 -50
  121. data/lib/easypost/beta/end_shipper.rb +0 -44
  122. data/lib/easypost/beta/referral.rb +0 -110
  123. data/lib/easypost/beta.rb +0 -7
  124. data/lib/easypost/billing.rb +0 -72
  125. data/lib/easypost/brand.rb +0 -13
  126. data/lib/easypost/carrier_account.rb +0 -9
  127. data/lib/easypost/carrier_type.rb +0 -5
  128. data/lib/easypost/customs_info.rb +0 -9
  129. data/lib/easypost/customs_item.rb +0 -9
  130. data/lib/easypost/end_shipper.rb +0 -24
  131. data/lib/easypost/error.rb +0 -32
  132. data/lib/easypost/event.rb +0 -11
  133. data/lib/easypost/object.rb +0 -171
  134. data/lib/easypost/order.rb +0 -37
  135. data/lib/easypost/parcel.rb +0 -9
  136. data/lib/easypost/payment_method.rb +0 -11
  137. data/lib/easypost/pickup.rb +0 -37
  138. data/lib/easypost/rate.rb +0 -9
  139. data/lib/easypost/referral.rb +0 -102
  140. data/lib/easypost/report.rb +0 -23
  141. data/lib/easypost/resource.rb +0 -106
  142. data/lib/easypost/scan_form.rb +0 -11
  143. data/lib/easypost/shipment.rb +0 -155
  144. data/lib/easypost/tracker.rb +0 -12
  145. data/lib/easypost/user.rb +0 -71
  146. data/lib/easypost/webhook.rb +0 -57
@@ -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
@@ -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
@@ -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