aftership-tracking-sdk 7.0.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.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +11 -0
  3. data/LICENSE +21 -0
  4. data/README.md +285 -0
  5. data/aftership-tracking-sdk.gemspec +27 -0
  6. data/lib/aftership-tracking-sdk/api/courier.rb +163 -0
  7. data/lib/aftership-tracking-sdk/api/estimated_delivery_date.rb +67 -0
  8. data/lib/aftership-tracking-sdk/api/last_checkpoint.rb +143 -0
  9. data/lib/aftership-tracking-sdk/api/notification.rb +403 -0
  10. data/lib/aftership-tracking-sdk/api/tracking.rb +793 -0
  11. data/lib/aftership-tracking-sdk/api_client.rb +426 -0
  12. data/lib/aftership-tracking-sdk/configuration.rb +122 -0
  13. data/lib/aftership-tracking-sdk/error.rb +125 -0
  14. data/lib/aftership-tracking-sdk/models/additional_fields_v1.rb +32 -0
  15. data/lib/aftership-tracking-sdk/models/aftership_estimated_delivery_date_tracking.rb +181 -0
  16. data/lib/aftership-tracking-sdk/models/carbon_emissions_tracking.rb +161 -0
  17. data/lib/aftership-tracking-sdk/models/checkpoint.rb +301 -0
  18. data/lib/aftership-tracking-sdk/models/coordinate_checkpoint.rb +161 -0
  19. data/lib/aftership-tracking-sdk/models/courier.rb +241 -0
  20. data/lib/aftership-tracking-sdk/models/courier_response_v1.rb +161 -0
  21. data/lib/aftership-tracking-sdk/models/custom_estimated_delivery_date_tracking.rb +181 -0
  22. data/lib/aftership-tracking-sdk/models/custom_fields_tracking_update_tracking_by_slug_tracking_number_request.rb +139 -0
  23. data/lib/aftership-tracking-sdk/models/data_courier_response_v1.rb +161 -0
  24. data/lib/aftership-tracking-sdk/models/data_notification_response_v1.rb +151 -0
  25. data/lib/aftership-tracking-sdk/models/data_tracking_delete_response_v1.rb +151 -0
  26. data/lib/aftership-tracking-sdk/models/data_tracking_response_get_multiple_v1.rb +281 -0
  27. data/lib/aftership-tracking-sdk/models/data_tracking_response_v1.rb +151 -0
  28. data/lib/aftership-tracking-sdk/models/destination_address_estimated_delivery_date_request.rb +191 -0
  29. data/lib/aftership-tracking-sdk/models/destination_address_estimated_delivery_date_response.rb +191 -0
  30. data/lib/aftership-tracking-sdk/models/detect_courier_response.rb +161 -0
  31. data/lib/aftership-tracking-sdk/models/estimated_delivery_date_request.rb +221 -0
  32. data/lib/aftership-tracking-sdk/models/estimated_delivery_date_response.rb +261 -0
  33. data/lib/aftership-tracking-sdk/models/estimated_pickup_estimated_delivery_date_request.rb +181 -0
  34. data/lib/aftership-tracking-sdk/models/estimated_pickup_estimated_delivery_date_response.rb +191 -0
  35. data/lib/aftership-tracking-sdk/models/events_checkpoint.rb +161 -0
  36. data/lib/aftership-tracking-sdk/models/first_estimated_delivery_tracking.rb +191 -0
  37. data/lib/aftership-tracking-sdk/models/get_all_couriers_response.rb +161 -0
  38. data/lib/aftership-tracking-sdk/models/get_checkpoint_by_slug_tracking_number_response.rb +211 -0
  39. data/lib/aftership-tracking-sdk/models/get_checkpoint_by_tracking_id_response.rb +211 -0
  40. data/lib/aftership-tracking-sdk/models/get_trackings_response.rb +161 -0
  41. data/lib/aftership-tracking-sdk/models/get_user_couriers_response.rb +161 -0
  42. data/lib/aftership-tracking-sdk/models/latest_estimated_delivery_tracking.rb +191 -0
  43. data/lib/aftership-tracking-sdk/models/mark_tracking_completed_by_id_request.rb +151 -0
  44. data/lib/aftership-tracking-sdk/models/mark_tracking_completed_by_slug_tracking_number_request.rb +151 -0
  45. data/lib/aftership-tracking-sdk/models/meta_v1.rb +171 -0
  46. data/lib/aftership-tracking-sdk/models/next_couriers_tracking.rb +171 -0
  47. data/lib/aftership-tracking-sdk/models/next_couriers_tracking_create_tracking_request.rb +161 -0
  48. data/lib/aftership-tracking-sdk/models/notification.rb +161 -0
  49. data/lib/aftership-tracking-sdk/models/notification_request_v1.rb +161 -0
  50. data/lib/aftership-tracking-sdk/models/notification_response_v1.rb +161 -0
  51. data/lib/aftership-tracking-sdk/models/order_processing_time_estimated_pickup_estimated_delivery_date_request.rb +161 -0
  52. data/lib/aftership-tracking-sdk/models/order_processing_time_estimated_pickup_estimated_delivery_date_response.rb +161 -0
  53. data/lib/aftership-tracking-sdk/models/origin_address_estimated_delivery_date_request.rb +191 -0
  54. data/lib/aftership-tracking-sdk/models/origin_address_estimated_delivery_date_response.rb +191 -0
  55. data/lib/aftership-tracking-sdk/models/pagination.rb +156 -0
  56. data/lib/aftership-tracking-sdk/models/partial_delete_tracking.rb +241 -0
  57. data/lib/aftership-tracking-sdk/models/partial_update_tracking.rb +251 -0
  58. data/lib/aftership-tracking-sdk/models/predict_batch_request.rb +151 -0
  59. data/lib/aftership-tracking-sdk/models/predict_batch_response.rb +151 -0
  60. data/lib/aftership-tracking-sdk/models/reason_events_checkpoint.rb +151 -0
  61. data/lib/aftership-tracking-sdk/models/slug_group_v1.rb +37 -0
  62. data/lib/aftership-tracking-sdk/models/tag_v1.rb +34 -0
  63. data/lib/aftership-tracking-sdk/models/tracking.rb +921 -0
  64. data/lib/aftership-tracking-sdk/models/tracking_create_tracking_request.rb +551 -0
  65. data/lib/aftership-tracking-sdk/models/tracking_delete_response_v1.rb +161 -0
  66. data/lib/aftership-tracking-sdk/models/tracking_detect_courier_request.rb +261 -0
  67. data/lib/aftership-tracking-sdk/models/tracking_response_get_multiple_v1.rb +161 -0
  68. data/lib/aftership-tracking-sdk/models/tracking_response_v1.rb +161 -0
  69. data/lib/aftership-tracking-sdk/models/tracking_update_tracking_by_id_request.rb +501 -0
  70. data/lib/aftership-tracking-sdk/models/tracking_update_tracking_by_slug_tracking_number_request.rb +391 -0
  71. data/lib/aftership-tracking-sdk/models/weight_estimated_delivery_date_request.rb +161 -0
  72. data/lib/aftership-tracking-sdk/models/weight_estimated_delivery_date_response.rb +161 -0
  73. data/lib/aftership-tracking-sdk/sign_string.rb +77 -0
  74. data/lib/aftership-tracking-sdk/version.rb +5 -0
  75. data/lib/aftership-tracking-sdk.rb +47 -0
  76. metadata +157 -0
@@ -0,0 +1,426 @@
1
+ # This code was auto generated by AfterShip SDK Generator.
2
+ # Do not edit the class manually.
3
+ require 'json'
4
+ require 'logger'
5
+ require 'tempfile'
6
+ require 'time'
7
+ require 'typhoeus'
8
+
9
+ module AftershipAPI
10
+ class ApiClient
11
+ BASE_DELAY_SECONDS = 3
12
+
13
+ # The Configuration object holding settings to be used in the API client.
14
+ attr_accessor :config
15
+
16
+ # Defines the headers to be used in HTTP requests of all API calls by default.
17
+ #
18
+ # @return [Hash]
19
+ attr_accessor :default_headers
20
+
21
+ # Initializes the ApiClient
22
+ # @option config [Configuration] Configuration for initializing the object, default to Configuration.default
23
+ def initialize(config = Configuration.default)
24
+ @config = config
25
+ @user_agent = config.user_agent
26
+ @aftership_client = config.aftership_client
27
+ @default_headers = @config.headers.merge({
28
+ 'Content-Type' => 'application/json',
29
+ 'User-Agent' => @user_agent,
30
+ 'aftership-client' => @aftership_client
31
+ })
32
+ end
33
+
34
+ def self.default
35
+ @@default ||= ApiClient.new
36
+ end
37
+
38
+ # Call an API with given options.
39
+ #
40
+ # @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
41
+ # the data deserialized from response body (may be a Tempfile or nil), response status code and response headers.
42
+ def call_api(http_method, path, opts = {})
43
+ retries = @config.max_retry || 0
44
+ begin
45
+ call_api_internal(http_method, path, opts)
46
+ rescue ApiError => e
47
+ if retries > 0 && (e.error_code == AftershipAPI::TIMED_OUT || e.status_code >= 500)
48
+ retries -= 1
49
+ delay_with_jitter
50
+ retry
51
+ else
52
+ raise e
53
+ end
54
+ end
55
+ end
56
+
57
+ # base delay is 3 seconds
58
+ def delay_with_jitter
59
+ delay = rand((BASE_DELAY_SECONDS / 2.0)..(BASE_DELAY_SECONDS * 2.0))
60
+ sleep delay
61
+ end
62
+
63
+ def call_api_internal(http_method, path, opts = {})
64
+ request = build_request(http_method, path, opts)
65
+ tempfile = download_file(request) if opts[:return_type] == 'File'
66
+ response = request.run
67
+
68
+ raise ApiError.new(:error_code => AftershipAPI::TIMED_OUT, :status_code => 0, :message => 'No response received') if response.timed_out?
69
+
70
+ if @config.debugging
71
+ @config.logger.debug "HTTP response body ~BEGIN~\n#{response.body}\n~END~\n"
72
+ end
73
+
74
+ unless response.success?
75
+ if response.timed_out?
76
+ fail ApiError.new(:error_code => AftershipAPI::TIMED_OUT, :message => 'Request timed out!')
77
+ elsif response.code == 0
78
+ # Errors from libcurl will be made visible here
79
+ fail ApiError.new(:status_code => 0,
80
+ :message => response.return_message)
81
+ else
82
+ fail ApiError.new(:status_code => response.code,
83
+ :response_headers => response.headers,
84
+ :response_body => response.body),
85
+ response.status_message
86
+ end
87
+ end
88
+
89
+ if opts[:return_type] == 'File'
90
+ data = tempfile
91
+ elsif opts[:return_type]
92
+ data = deserialize(response, opts[:return_type], opts[:response_legacy_tag], opts[:is_paging])
93
+ else
94
+ data = nil
95
+ end
96
+ return data, response.code, response.headers
97
+ end
98
+
99
+ # Builds the HTTP request
100
+ #
101
+ # @param [String] http_method HTTP method/verb (e.g. POST)
102
+ # @param [String] path URL path (e.g. /account/new)
103
+ # @option opts [Hash] :header_params Header parameters
104
+ # @option opts [Hash] :query_params Query parameters
105
+ # @option opts [Hash] :form_params Query parameters
106
+ # @option opts [Object] :body HTTP body (JSON/XML)
107
+ # @return [Typhoeus::Request] A Typhoeus Request
108
+ def build_request(http_method, path, opts = {})
109
+ url = build_request_url(path, opts)
110
+ http_method = http_method.to_sym.downcase
111
+
112
+ header_params = @default_headers.merge(opts[:header_params] || {}).merge({ 'as-api-key' => config.as_api_key })
113
+ query_params = opts[:query_params] || {}
114
+ form_params = opts[:form_params] || {}
115
+ follow_location = opts[:follow_location] || true
116
+
117
+ header_params['date'] = Time.now.httpdate
118
+
119
+ req_opts = {
120
+ :method => http_method,
121
+ :headers => header_params,
122
+ :params => query_params,
123
+ :timeout => @config.timeout,
124
+ :verbose => @config.debugging,
125
+ :followlocation => follow_location,
126
+ :proxy => @config.proxy
127
+ }
128
+
129
+ if [:post, :patch, :put, :delete].include?(http_method)
130
+ req_body = build_request_body(header_params, form_params, opts[:body])
131
+ req_opts.update :body => req_body
132
+ if req_body.to_s.size == 0
133
+ req_opts[:headers]['Content-Type'] = ''
134
+ end
135
+ if @config.debugging
136
+ @config.logger.debug "HTTP request body param ~BEGIN~\n#{req_body}\n~END~\n"
137
+ end
138
+ end
139
+
140
+ if @config.authentication_type == AUTHENTICATION_TYPE_AES || @config.authentication_type == AUTHENTICATION_TYPE_RSA
141
+ signature_header = @config.authentication_type == AUTHENTICATION_TYPE_AES ? "as-signature-hmac-sha256" : "as-signature-rsa-sha256"
142
+ req_opts[:headers][signature_header] = SignString.sign({
143
+ 'method' => http_method,
144
+ 'headers' => req_opts[:headers],
145
+ 'body' => req_opts[:body] || '',
146
+ 'content_type' => header_params['Content-Type'],
147
+ 'date' => header_params['date'],
148
+ 'url' => url,
149
+ 'query' => query_params,
150
+ 'auth_type' => @config.authentication_type,
151
+ 'secret' => @config.as_api_secret
152
+ })
153
+ end
154
+
155
+ Typhoeus::Request.new(url, req_opts)
156
+ end
157
+
158
+ # Builds the HTTP request body
159
+ #
160
+ # @param [Hash] header_params Header parameters
161
+ # @param [Hash] form_params Query parameters
162
+ # @param [Object] body HTTP body (JSON/XML)
163
+ # @return [String] HTTP body data in the form of string
164
+ def build_request_body(header_params, form_params, body)
165
+ # http form
166
+ if header_params['Content-Type'] == 'application/x-www-form-urlencoded' ||
167
+ header_params['Content-Type'] == 'multipart/form-data'
168
+ data = {}
169
+ form_params.each do |key, value|
170
+ case value
171
+ when ::File, ::Array, nil
172
+ # let typhoeus handle File, Array and nil parameters
173
+ data[key] = value
174
+ else
175
+ data[key] = value.to_s
176
+ end
177
+ end
178
+ elsif body
179
+ data = body.is_a?(String) ? body : body.to_json
180
+ else
181
+ data = nil
182
+ end
183
+ data
184
+ end
185
+
186
+ # Save response body into a file in (the defined) temporary folder, using the filename
187
+ # from the "Content-Disposition" header if provided, otherwise a random filename.
188
+ # The response body is written to the file in chunks in order to handle files which
189
+ # size is larger than maximum Ruby String or even larger than the maximum memory a Ruby
190
+ # process can use.
191
+ #
192
+ # @see Configuration#temp_folder_path
193
+ #
194
+ # @return [Tempfile] the tempfile generated
195
+ def download_file(request)
196
+ tempfile = nil
197
+ encoding = nil
198
+ request.on_headers do |response|
199
+ content_disposition = response.headers['Content-Disposition']
200
+ if content_disposition && content_disposition =~ /filename=/i
201
+ filename = content_disposition[/filename=['"]?([^'"\s]+)['"]?/, 1]
202
+ prefix = sanitize_filename(filename)
203
+ else
204
+ prefix = 'download-'
205
+ end
206
+ prefix = prefix + '-' unless prefix.end_with?('-')
207
+ encoding = response.body.encoding
208
+ tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding)
209
+ end
210
+ request.on_body do |chunk|
211
+ chunk.force_encoding(encoding)
212
+ tempfile.write(chunk)
213
+ end
214
+ # run the request to ensure the tempfile is created successfully before returning it
215
+ request.run
216
+ if tempfile
217
+ tempfile.close
218
+ @config.logger.info "Temp file written to #{tempfile.path}, please copy the file to a proper folder "\
219
+ "with e.g. `FileUtils.cp(tempfile.path, '/new/file/path')` otherwise the temp file "\
220
+ "will be deleted automatically with GC. It's also recommended to delete the temp file "\
221
+ "explicitly with `tempfile.delete`"
222
+ else
223
+ fail ApiError.new("Failed to create the tempfile based on the HTTP response from the server: #{request.inspect}")
224
+ end
225
+
226
+ tempfile
227
+ end
228
+
229
+ # Check if the given MIME is a JSON MIME.
230
+ # JSON MIME examples:
231
+ # application/json
232
+ # application/json; charset=UTF8
233
+ # APPLICATION/JSON
234
+ # */*
235
+ # @param [String] mime MIME
236
+ # @return [Boolean] True if the MIME is application/json
237
+ def json_mime?(mime)
238
+ (mime == '*/*') || !(mime =~ /Application\/.*json(?!p)(;.*)?/i).nil?
239
+ end
240
+
241
+ # Deserialize the response to the given return type.
242
+ #
243
+ # @param [Response] response HTTP response
244
+ # @param [String] return_type some examples: "User", "Array<User>", "Hash<String, Integer>"
245
+ # @param [String] response_legacy_tag {tracking: Tracking{}} where response_legacy_tag is "tracking"
246
+ # @param [Boolean] is_paging
247
+ def deserialize(response, return_type, response_legacy_tag, is_paging)
248
+ body = response.body
249
+ return nil if body.nil? || body.empty?
250
+
251
+ # return response body directly for String return type
252
+ return body.to_s if return_type == 'String'
253
+
254
+ # ensuring a default content type
255
+ content_type = response.headers['Content-Type'] || 'application/json'
256
+
257
+ fail "Content-Type is not supported: #{content_type}" unless json_mime?(content_type)
258
+
259
+ begin
260
+ data = JSON.parse("[#{body}]", :symbolize_names => true)[0]
261
+ rescue JSON::ParserError => e
262
+ if %w(String Date Time).include?(return_type)
263
+ data = body
264
+ else
265
+ raise e
266
+ end
267
+ end
268
+
269
+ convert_to_type handle_data(response_legacy_tag, is_paging, data), return_type
270
+ end
271
+
272
+ def handle_data(response_legacy_tag, is_paging, data)
273
+ if response_legacy_tag.to_s != "" && !is_paging
274
+ return data[:data][response_legacy_tag.to_sym]
275
+ end
276
+
277
+ if response_legacy_tag.to_s != "" && is_paging
278
+ pagination = {
279
+ page: data[:data][:page],
280
+ limit: data[:data][:limit],
281
+ has_next_page: data[:data][:has_next_page],
282
+ }
283
+
284
+ total = data[:data][:total]
285
+ total = data[:data][:count] if total.nil?
286
+ pagination[:total] = total
287
+ return {
288
+ pagination: pagination,
289
+ response_legacy_tag.to_sym => data[:data][response_legacy_tag.to_sym]
290
+ }
291
+ end
292
+
293
+ data[:data]
294
+ end
295
+
296
+ # Convert data to the given return type.
297
+ # @param [Object] data Data to be converted
298
+ # @param [String] return_type Return type
299
+ # @return [Mixed] Data in a particular type
300
+ def convert_to_type(data, return_type)
301
+ return nil if data.nil?
302
+ case return_type
303
+ when 'String'
304
+ data.to_s
305
+ when 'Integer'
306
+ data.to_i
307
+ when 'Float'
308
+ data.to_f
309
+ when 'Boolean'
310
+ data == true
311
+ when 'Time'
312
+ # parse date time (expecting ISO 8601 format)
313
+ Time.parse data
314
+ when 'Date'
315
+ # parse date time (expecting ISO 8601 format)
316
+ Date.parse data
317
+ when 'Object'
318
+ # generic object (usually a Hash), return directly
319
+ data
320
+ when /\AArray<(.+)>\z/
321
+ # e.g. Array<Pet>
322
+ sub_type = $1
323
+ data.map { |item| convert_to_type(item, sub_type) }
324
+ when /\AHash\<String, (.+)\>\z/
325
+ # e.g. Hash<String, Integer>
326
+ sub_type = $1
327
+ {}.tap do |hash|
328
+ data.each { |k, v| hash[k] = convert_to_type(v, sub_type) }
329
+ end
330
+ else
331
+ # models (e.g. Pet) or oneOf
332
+ klass = AftershipAPI::Model.const_get(return_type)
333
+ klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
334
+ end
335
+ end
336
+
337
+ # Sanitize filename by removing path.
338
+ # e.g. ../../sun.gif becomes sun.gif
339
+ #
340
+ # @param [String] filename the filename to be sanitized
341
+ # @return [String] the sanitized filename
342
+ def sanitize_filename(filename)
343
+ filename.gsub(/.*[\/\\]/, '')
344
+ end
345
+
346
+ def build_request_url(path, opts = {})
347
+ # Add leading and trailing slashes to path
348
+ path = "/#{path}".gsub(/\/+/, '/')
349
+ @config.domain + path
350
+ end
351
+
352
+ # Sets user agent in HTTP header
353
+ #
354
+ # @param [String] user_agent User agent (e.g. openapi-generator/ruby/1.0.0)
355
+ def user_agent=(user_agent)
356
+ @user_agent = user_agent
357
+ @default_headers['User-Agent'] = @user_agent
358
+ end
359
+
360
+ # Return Accept header based on an array of accepts provided.
361
+ # @param [Array] accepts array for Accept
362
+ # @return [String] the Accept header (e.g. application/json)
363
+ def select_header_accept(accepts)
364
+ return nil if accepts.nil? || accepts.empty?
365
+ # use JSON when present, otherwise use all of the provided
366
+ json_accept = accepts.find { |s| json_mime?(s) }
367
+ json_accept || accepts.join(',')
368
+ end
369
+
370
+ # Return Content-Type header based on an array of content types provided.
371
+ # @param [Array] content_types array for Content-Type
372
+ # @return [String] the Content-Type header (e.g. application/json)
373
+ def select_header_content_type(content_types)
374
+ # return nil by default
375
+ return if content_types.nil? || content_types.empty?
376
+ # use JSON when present, otherwise use the first one
377
+ json_content_type = content_types.find { |s| json_mime?(s) }
378
+ json_content_type || content_types.first
379
+ end
380
+
381
+ # Convert object (array, hash, object, etc) to JSON string.
382
+ # @param [Object] model object to be converted into JSON string
383
+ # @return [String] JSON string representation of the object
384
+ def object_to_http_body(model)
385
+ return model if model.nil? || model.is_a?(String)
386
+ local_body = nil
387
+ if model.is_a?(Array)
388
+ local_body = model.map { |m| object_to_hash(m) }
389
+ else
390
+ local_body = object_to_hash(model)
391
+ end
392
+ local_body.to_json
393
+ end
394
+
395
+ # Convert object(non-array) to hash.
396
+ # @param [Object] obj object to be converted into JSON string
397
+ # @return [String] JSON string representation of the object
398
+ def object_to_hash(obj)
399
+ if obj.respond_to?(:to_hash)
400
+ obj.to_hash
401
+ else
402
+ obj
403
+ end
404
+ end
405
+
406
+ # Build parameter value according to the given collection format.
407
+ # @param [String] collection_format one of :csv, :ssv, :tsv, :pipes and :multi
408
+ def build_collection_param(param, collection_format)
409
+ case collection_format
410
+ when :csv
411
+ param.join(',')
412
+ when :ssv
413
+ param.join(' ')
414
+ when :tsv
415
+ param.join("\t")
416
+ when :pipes
417
+ param.join('|')
418
+ when :multi
419
+ # return the array directly as typhoeus will handle it as expected
420
+ param
421
+ else
422
+ fail "unknown collection format: #{collection_format.inspect}"
423
+ end
424
+ end
425
+ end
426
+ end
@@ -0,0 +1,122 @@
1
+ # This code was auto generated by AfterShip SDK Generator.
2
+ # Do not edit the class manually.
3
+ require 'uri'
4
+ require 'typhoeus'
5
+
6
+ module AftershipAPI
7
+ AUTHENTICATION_TYPE_API_KEY = 'API_KEY'
8
+ AUTHENTICATION_TYPE_AES = 'AES'
9
+ AUTHENTICATION_TYPE_RSA = 'RSA'
10
+
11
+ SDK_PREFIX = 'AFTERSHIP_TRACKING_SDK'
12
+
13
+
14
+ class Configuration
15
+ def get_env(key)
16
+ ENV[SDK_PREFIX + '_' + key]
17
+ end
18
+
19
+ # Defines domain
20
+ attr_accessor :domain
21
+
22
+ # Defines the authentication type used in the API.
23
+ #
24
+ # @return ["API_KEY", "AES", "RSA"]
25
+ attr_accessor :authentication_type
26
+
27
+ # Defines API keys used with API Key authentications.
28
+ #
29
+ # @return [string]
30
+ attr_accessor :as_api_key
31
+
32
+ # Defines AES secret or RSA private key used with AES or RSA authentications.
33
+ #
34
+ # @return [string]
35
+ attr_accessor :as_api_secret
36
+
37
+ # Defines the user agent used in the API requests.
38
+ # Default to 'aftership-sdk-ruby/$VERSION'
39
+ #
40
+ # @return [string]
41
+ attr_accessor :user_agent
42
+
43
+ # Set this to enable/disable debugging. When enabled (set to true), HTTP request/response
44
+ # details will be logged with `logger.debug` (see the `logger` attribute).
45
+ # Default to false.
46
+ #
47
+ # @return [true, false]
48
+ attr_accessor :debugging
49
+
50
+ # Defines the logger used for debugging.
51
+ # Default to `Rails.logger` (when in Rails) or logging to STDOUT.
52
+ #
53
+ # @return [#debug]
54
+ attr_accessor :logger
55
+
56
+ # The time limit for HTTP request in seconds.
57
+ # Default to 30
58
+ attr_accessor :timeout
59
+
60
+ # When response is a retryable error, retry current request
61
+ # Default to 2
62
+ attr_accessor :max_retry
63
+
64
+ # HTTP proxy
65
+ attr_accessor :proxy
66
+
67
+ attr_accessor :aftership_client
68
+
69
+ attr_accessor :headers
70
+
71
+
72
+ def initialize
73
+ default_user_agent = "aftership-sdk-ruby/#{AftershipAPI::VERSION} (https://www.aftership.com) typhoeus/#{Typhoeus::VERSION}"
74
+
75
+ @domain = get_env('DOMAIN') || 'https://api.aftership.com'
76
+ @authentication_type = get_env('AUTHENTICATION_TYPE') || AUTHENTICATION_TYPE_API_KEY
77
+ @as_api_key = get_env('API_KEY') || ''
78
+ @as_api_secret = get_env('API_SECRET') || ''
79
+ @user_agent = get_env('USER_AGENT') || default_user_agent
80
+ @aftership_client = default_user_agent
81
+ @timeout = (get_env('TIMEOUT') || 30).to_i
82
+ @max_retry = (get_env('MAX_RETRY') || 2).to_i
83
+ @proxy = get_env('PROXY')
84
+ @debugging = get_env('DEBUGGING') || false
85
+ @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
86
+ @headers = {}
87
+
88
+ yield(self) if block_given?
89
+ end
90
+
91
+ # The default Configuration object.
92
+ def self.default
93
+ @@default ||= Configuration.new
94
+ end
95
+
96
+ def configure
97
+ yield(self) if block_given?
98
+ end
99
+
100
+ def domain=(domain)
101
+ @domain = domain.sub(/\/+\z/, '')
102
+ end
103
+
104
+ def check
105
+ fail InvalidOptionError.new("Invalid authentication type: #{authentication_type}") unless [AUTHENTICATION_TYPE_API_KEY, AUTHENTICATION_TYPE_AES, AUTHENTICATION_TYPE_RSA].include?(authentication_type)
106
+ fail InvalidOptionError.new("as_api_key cannot be empty") unless as_api_key.to_s.size > 0
107
+ fail InvalidOptionError.new("Invalid base URL: #{domain}") unless valid_url?(domain)
108
+ fail InvalidOptionError.new("authentication type must not be API_KEY if as_api_secret is set") if as_api_secret.to_s.size > 0 && authentication_type == AUTHENTICATION_TYPE_API_KEY
109
+ fail InvalidOptionError.new("timeout cannot be negative, value #{timeout}") unless timeout.to_i >= 0
110
+ fail InvalidOptionError.new("max_retry must be in range 0..10, value #{max_retry}") unless (max_retry.to_i >= 0) && (max_retry.to_i <= 10)
111
+ fail InvalidOptionError.new("max_retry cannot be negative, value #{max_retry}") unless max_retry.to_i >= 0
112
+ end
113
+
114
+ def valid_url?(url)
115
+ uri = URI.parse(url)
116
+ uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS)
117
+ rescue URI::InvalidURIError
118
+ false
119
+ end
120
+ end
121
+ end
122
+
@@ -0,0 +1,125 @@
1
+ # This code was auto generated by AfterShip SDK Generator.
2
+ # Do not edit the class manually.
3
+ require 'json'
4
+
5
+ module AftershipAPI
6
+ REQUEST_ERROR = 'REQUEST_ERROR'
7
+
8
+ # Common AfterShipError
9
+ INVALID_API_KEY = 'INVALID_API_KEY'.freeze
10
+ INVALID_OPTION = 'INVALID_OPTION'.freeze
11
+ RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED'.freeze
12
+ TIMED_OUT = "TIMED_OUT".freeze
13
+
14
+ INVALID_REQUEST = "INVALID_REQUEST".freeze
15
+ INVALID_JSON = "INVALID_JSON".freeze
16
+ TRACKING_ALREADY_EXIST = "TRACKING_ALREADY_EXIST".freeze
17
+ TRACKING_DOES_NOT_EXIST = "TRACKING_DOES_NOT_EXIST".freeze
18
+ TRACKING_NUMBER_INVALID = "TRACKING_NUMBER_INVALID".freeze
19
+ TRACKING_REQUIRED = "TRACKING_REQUIRED".freeze
20
+ TRACKING_NUMBER_REQUIRED = "TRACKING_NUMBER_REQUIRED".freeze
21
+ VALUE_INVALID = "VALUE_INVALID".freeze
22
+ VALUE_REQUIRED = "VALUE_REQUIRED".freeze
23
+ SLUG_INVALID = "SLUG_INVALID".freeze
24
+ MISSING_OR_INVALID_REQUIRED_FIELD = "MISSING_OR_INVALID_REQUIRED_FIELD".freeze
25
+ BAD_COURIER = "BAD_COURIER".freeze
26
+ INACTIVE_RETRACK_NOT_ALLOWED = "INACTIVE_RETRACK_NOT_ALLOWED".freeze
27
+ NOTIFICATION_REUQIRED = "NOTIFICATION_REUQIRED".freeze
28
+ ID_INVALID = "ID_INVALID".freeze
29
+ RETRACK_ONCE_ALLOWED = "RETRACK_ONCE_ALLOWED".freeze
30
+ TRACKING_NUMBER_FORMAT_INVALID = "TRACKING_NUMBER_FORMAT_INVALID".freeze
31
+ API_KEY_INVALID = "API_KEY_INVALID".freeze
32
+ REQUEST_NOT_ALLOWED = "REQUEST_NOT_ALLOWED".freeze
33
+ NOT_FOUND = "NOT_FOUND".freeze
34
+ TOO_MANY_REQUEST = "TOO_MANY_REQUEST".freeze
35
+ INTERNAL_ERROR = "INTERNAL_ERROR".freeze
36
+
37
+ ERROR_MAP = {
38
+ # Format: metaCode => ErrorCode
39
+ 400 => INVALID_REQUEST,
40
+ 4001 => INVALID_JSON,
41
+ 4003 => TRACKING_ALREADY_EXIST,
42
+ 4004 => TRACKING_DOES_NOT_EXIST,
43
+ 4005 => TRACKING_NUMBER_INVALID,
44
+ 4006 => TRACKING_REQUIRED,
45
+ 4007 => TRACKING_NUMBER_REQUIRED,
46
+ 4008 => VALUE_INVALID,
47
+ 4009 => VALUE_REQUIRED,
48
+ 4010 => SLUG_INVALID,
49
+ 4011 => MISSING_OR_INVALID_REQUIRED_FIELD,
50
+ 4012 => BAD_COURIER,
51
+ 4013 => INACTIVE_RETRACK_NOT_ALLOWED,
52
+ 4014 => NOTIFICATION_REUQIRED,
53
+ 4015 => ID_INVALID,
54
+ 4016 => RETRACK_ONCE_ALLOWED,
55
+ 4017 => TRACKING_NUMBER_FORMAT_INVALID,
56
+ 401 => API_KEY_INVALID,
57
+ 403 => REQUEST_NOT_ALLOWED,
58
+ 404 => NOT_FOUND,
59
+ 429 => TOO_MANY_REQUEST,
60
+ 500 => INTERNAL_ERROR,
61
+ 502 => INTERNAL_ERROR,
62
+ 503 => INTERNAL_ERROR,
63
+ 504 => INTERNAL_ERROR,
64
+ }
65
+
66
+
67
+ class ApiError < StandardError
68
+ attr_reader :status_code, :response_headers, :response_body, :meta_code, :error_code
69
+
70
+ # Usage examples:
71
+ # ApiError.new
72
+ # ApiError.new("message")
73
+ # ApiError.new(:status_code => 500, :response_headers => {}, :response_body => "")
74
+ # ApiError.new(:status_code => 404, :message => "Not Found")
75
+ def initialize(arg = nil)
76
+ if arg.is_a? Hash
77
+ if arg.key?(:message) || arg.key?('message')
78
+ super(arg[:message] || arg['message'])
79
+ else
80
+ super arg
81
+ end
82
+
83
+ response_body = JSON.parse(arg[:response_body], :symbolize_names => true) rescue nil
84
+ @message = REQUEST_ERROR
85
+ if response_body && response_body[:meta] && response_body[:meta][:code]
86
+ @meta_code = response_body[:meta][:code]
87
+ @error_code = ERROR_MAP[@meta_code] || REQUEST_ERROR
88
+ @message = response_body[:meta][:message] || REQUEST_ERROR
89
+ end
90
+ arg.each do |k, v|
91
+ instance_variable_set "@#{k}", v
92
+ end
93
+ else
94
+ super arg
95
+ @message = arg
96
+ end
97
+ end
98
+
99
+ # Override to_s to display a friendly error message
100
+ def to_s
101
+ message
102
+ end
103
+
104
+ def message
105
+ if @message.nil?
106
+ msg = "Error message: the server returns an error"
107
+ else
108
+ msg = @message
109
+ end
110
+
111
+ msg += "\nHTTP status code: #{status_code}" if status_code
112
+ msg += "\nError Code #{error_code}" if error_code
113
+ msg += "\nResponse headers: #{response_headers}" if response_headers
114
+ msg += "\nResponse body: #{response_body}" if response_body
115
+
116
+ msg
117
+ end
118
+ end
119
+
120
+ class InvalidOptionError < StandardError
121
+ end
122
+
123
+ class InvalidParamError < StandardError
124
+ end
125
+ end
@@ -0,0 +1,32 @@
1
+ # This code was auto generated by AfterShip SDK Generator.
2
+ # Do not edit the class manually.
3
+
4
+ module AftershipAPI::Model
5
+ class AdditionalFieldsV1
6
+ TRACKING_ACCOUNT_NUMBER = "tracking_account_number".freeze
7
+ TRACKING_POSTAL_CODE = "tracking_postal_code".freeze
8
+ TRACKING_SHIP_DATE = "tracking_ship_date".freeze
9
+ TRACKING_KEY = "tracking_key".freeze
10
+ TRACKING_ORIGIN_COUNTRY = "tracking_origin_country".freeze
11
+ TRACKING_DESTINATION_COUNTRY = "tracking_destination_country".freeze
12
+ TRACKING_STATE = "tracking_state".freeze
13
+ def self.all_vars
14
+ @all_vars ||= [TRACKING_ACCOUNT_NUMBER, TRACKING_POSTAL_CODE, TRACKING_SHIP_DATE, TRACKING_KEY, TRACKING_ORIGIN_COUNTRY, TRACKING_DESTINATION_COUNTRY, TRACKING_STATE,].freeze
15
+ end
16
+
17
+ # Builds the enum from string
18
+ # @param value [String] The enum value in the form of the string
19
+ # @return [String] The enum value
20
+ def self.build_from_hash(value)
21
+ new.build_from_hash(value)
22
+ end
23
+
24
+ # Builds the enum from string
25
+ # @param value [String] The enum value in the form of the string
26
+ # @return [String] The enum value
27
+ def build_from_hash(value)
28
+ return value if AdditionalFieldsV1.all_vars.include?(value)
29
+ raise "Invalid ENUM value #{value} for class #AdditionalFieldsV1"
30
+ end
31
+ end
32
+ end