eligible 1.0 → 3.0.0.beta17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +76 -0
  3. data/.codeclimate.yml +23 -0
  4. data/.gitignore +3 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +1158 -0
  7. data/.ruby-version +1 -0
  8. data/CHANGELOG.md +170 -0
  9. data/Gemfile +4 -0
  10. data/Gemfile.lock +66 -0
  11. data/LICENSE +1 -1
  12. data/README.md +700 -93
  13. data/Rakefile +12 -2
  14. data/eligible.gemspec +14 -16
  15. data/lib/eligible/api_resource.rb +49 -5
  16. data/lib/eligible/calculator_deploy_url.rb +7 -0
  17. data/lib/eligible/claim.rb +22 -6
  18. data/lib/eligible/coverage.rb +19 -0
  19. data/lib/eligible/coverage_resource.rb +23 -0
  20. data/lib/eligible/customer.rb +19 -0
  21. data/lib/eligible/demographic.rb +6 -35
  22. data/lib/eligible/eligible_object.rb +12 -15
  23. data/lib/eligible/encryptor.rb +121 -0
  24. data/lib/eligible/enrollment.rb +23 -0
  25. data/lib/eligible/errors/eligible_error.rb +6 -3
  26. data/lib/eligible/errors/invalid_request_error.rb +4 -0
  27. data/lib/eligible/icd.rb +16 -0
  28. data/lib/eligible/json.rb +5 -15
  29. data/lib/eligible/lockbox.rb +39 -0
  30. data/lib/eligible/medicare.rb +11 -0
  31. data/lib/eligible/oauth_token.rb +9 -0
  32. data/lib/eligible/ocr.rb +15 -0
  33. data/lib/eligible/original_signature_pdf.rb +45 -0
  34. data/lib/eligible/payer.rb +17 -0
  35. data/lib/eligible/payer_mapping.rb +37 -0
  36. data/lib/eligible/payment.rb +11 -0
  37. data/lib/eligible/preauth_resource.rb +11 -0
  38. data/lib/eligible/precert.rb +15 -0
  39. data/lib/eligible/provider_model.rb +7 -0
  40. data/lib/eligible/public_key.rb +27 -0
  41. data/lib/eligible/received_pdf.rb +26 -0
  42. data/lib/eligible/referral.rb +11 -0
  43. data/lib/eligible/risk_assessment.rb +15 -0
  44. data/lib/eligible/session_token.rb +11 -0
  45. data/lib/eligible/ticket.rb +40 -0
  46. data/lib/eligible/util.rb +29 -38
  47. data/lib/eligible/v1_0/action.rb +9 -0
  48. data/lib/eligible/v1_0/attribute.rb +9 -0
  49. data/lib/eligible/v1_0/charge.rb +13 -0
  50. data/lib/eligible/v1_0/claim.rb +25 -0
  51. data/lib/eligible/v1_0/claim_service_line.rb +9 -0
  52. data/lib/eligible/v1_0/contract.rb +9 -0
  53. data/lib/eligible/v1_0/device.rb +9 -0
  54. data/lib/eligible/v1_0/discount.rb +9 -0
  55. data/lib/eligible/v1_0/enrollment.rb +17 -0
  56. data/lib/eligible/v1_0/estimate.rb +29 -0
  57. data/lib/eligible/v1_0/estimate_service_line.rb +17 -0
  58. data/lib/eligible/v1_0/fee.rb +21 -0
  59. data/lib/eligible/v1_0/fee_refund.rb +29 -0
  60. data/lib/eligible/v1_0/file.rb +17 -0
  61. data/lib/eligible/v1_0/file_link.rb +13 -0
  62. data/lib/eligible/v1_0/insurance_company.rb +21 -0
  63. data/lib/eligible/v1_0/insurance_company_alias.rb +9 -0
  64. data/lib/eligible/v1_0/insurance_policy.rb +9 -0
  65. data/lib/eligible/v1_0/patient_question.rb +9 -0
  66. data/lib/eligible/v1_0/patient_questionnaire.rb +9 -0
  67. data/lib/eligible/v1_0/patient_record.rb +9 -0
  68. data/lib/eligible/v1_0/patient_statement.rb +54 -0
  69. data/lib/eligible/v1_0/patient_statement_service_line.rb +13 -0
  70. data/lib/eligible/v1_0/payment_report.rb +21 -0
  71. data/lib/eligible/v1_0/product.rb +9 -0
  72. data/lib/eligible/v1_0/provider.rb +9 -0
  73. data/lib/eligible/v1_0/remark.rb +21 -0
  74. data/lib/eligible/v1_0/reports/accuracy_stats.rb +23 -0
  75. data/lib/eligible/v1_0/reports/estimate_friction.rb +23 -0
  76. data/lib/eligible/v1_0/reports/in_scope_distribution.rb +23 -0
  77. data/lib/eligible/v1_0/rest_api_base.rb +44 -0
  78. data/lib/eligible/v1_0/rule.rb +13 -0
  79. data/lib/eligible/v1_0/session.rb +21 -0
  80. data/lib/eligible/v1_0/transaction.rb +21 -0
  81. data/lib/eligible/v1_0/treatment.rb +9 -0
  82. data/lib/eligible/v1_0/value_list.rb +9 -0
  83. data/lib/eligible/v1_0/value_list_item.rb +9 -0
  84. data/lib/eligible/v1_0/verification.rb +17 -0
  85. data/lib/eligible/version.rb +1 -1
  86. data/lib/eligible/visit_type.rb +11 -0
  87. data/lib/eligible/x12.rb +8 -0
  88. data/lib/eligible.rb +320 -110
  89. metadata +148 -67
  90. data/CONTRIBUTORS +0 -1
  91. data/lib/eligible/plan.rb +0 -42
  92. data/lib/eligible/service.rb +0 -39
  93. data/test/test_eligible.rb +0 -279
  94. data/test/test_helper.rb +0 -67
data/lib/eligible.rb CHANGED
@@ -2,34 +2,123 @@ require 'cgi'
2
2
  require 'set'
3
3
  require 'rubygems'
4
4
  require 'openssl'
5
+ require 'net/https'
5
6
 
6
- gem 'rest-client', '~> 1.4'
7
7
  require 'rest_client'
8
8
  require 'multi_json'
9
9
 
10
10
  require 'eligible/version'
11
+ require 'eligible/encryptor'
11
12
  require 'eligible/util'
12
13
  require 'eligible/json'
13
14
  require 'eligible/eligible_object'
14
15
  require 'eligible/api_resource'
15
- require 'eligible/plan'
16
- require 'eligible/service'
16
+ require 'eligible/coverage_resource'
17
17
  require 'eligible/demographic'
18
18
  require 'eligible/claim'
19
+ require 'eligible/enrollment'
20
+ require 'eligible/coverage'
21
+ require 'eligible/payment'
22
+ require 'eligible/x12'
23
+ require 'eligible/medicare'
24
+ require 'eligible/ticket'
25
+ require 'eligible/customer'
26
+ require 'eligible/ocr'
27
+ require 'eligible/original_signature_pdf'
28
+ require 'eligible/oauth_token'
29
+ require 'eligible/received_pdf'
30
+ require 'eligible/payer'
31
+ require 'eligible/payer_mapping'
32
+ require 'eligible/preauth_resource'
33
+ require 'eligible/precert'
34
+ require 'eligible/referral'
35
+ require 'eligible/public_key'
36
+ require 'eligible/lockbox'
37
+ require 'eligible/session_token'
38
+ require 'eligible/visit_type'
39
+ require 'eligible/provider_model'
40
+ require 'eligible/calculator_deploy_url'
41
+ require 'eligible/risk_assessment'
42
+ require 'eligible/icd'
43
+
44
+ # New REST API Endpoints
45
+ require 'eligible/v1_0/rest_api_base'
46
+ require 'eligible/v1_0/action'
47
+ require 'eligible/v1_0/attribute'
48
+ require 'eligible/v1_0/charge'
49
+ require 'eligible/v1_0/claim'
50
+ require 'eligible/v1_0/claim_service_line'
51
+ require 'eligible/v1_0/contract'
52
+ require 'eligible/v1_0/device'
53
+ require 'eligible/v1_0/discount'
54
+ require 'eligible/v1_0/enrollment'
55
+ require 'eligible/v1_0/estimate'
56
+ require 'eligible/v1_0/estimate_service_line'
57
+ require 'eligible/v1_0/fee'
58
+ require 'eligible/v1_0/fee_refund'
59
+ require 'eligible/v1_0/file'
60
+ require 'eligible/v1_0/file_link'
61
+ require 'eligible/v1_0/insurance_company'
62
+ require 'eligible/v1_0/insurance_company_alias'
63
+ require 'eligible/v1_0/insurance_policy'
64
+ require 'eligible/v1_0/patient_record'
65
+ require 'eligible/v1_0/patient_statement'
66
+ require 'eligible/v1_0/patient_statement_service_line'
67
+ require 'eligible/v1_0/payment_report'
68
+ require 'eligible/v1_0/patient_question'
69
+ require 'eligible/v1_0/patient_questionnaire'
70
+ require 'eligible/v1_0/product'
71
+ require 'eligible/v1_0/provider'
72
+ require 'eligible/v1_0/remark'
73
+ require 'eligible/v1_0/rule'
74
+ require 'eligible/v1_0/session'
75
+ require 'eligible/v1_0/transaction'
76
+ require 'eligible/v1_0/treatment'
77
+ require 'eligible/v1_0/value_list'
78
+ require 'eligible/v1_0/value_list_item'
79
+ require 'eligible/v1_0/verification'
80
+ require 'eligible/v1_0/reports/accuracy_stats'
81
+ require 'eligible/v1_0/reports/estimate_friction'
82
+ require 'eligible/v1_0/reports/in_scope_distribution'
19
83
 
20
84
  # Errors
21
85
  require 'eligible/errors/eligible_error'
22
86
  require 'eligible/errors/api_connection_error'
23
87
  require 'eligible/errors/authentication_error'
24
88
  require 'eligible/errors/api_error'
89
+ require 'eligible/errors/invalid_request_error'
25
90
 
26
91
  module Eligible
27
- @@api_key = nil
28
- @@api_base = "https://v1.eligibleapi.net"
29
- @@api_version = 1
92
+ @@api_key = nil
93
+ @@test = false
94
+ @@api_version = '1.5'
95
+ @@api_base = "https://gds.eligibleapi.com/v#{@@api_version}"
96
+ @@fingerprints = %w(a1cd762a9f4be0f3b6bdd6300e52c6ce8d7d67f5
97
+ 36d6b6f98a2b9bcdf4321d1978553e23cf044b53
98
+ d93b7697100fe978ae0f78fbf2a2443cc1958ca3
99
+ 896ce24f7a83eb656c040985fdb50ce39f90b813)
100
+ @@eligible_account = nil
101
+ @@eligible_account_id = nil
102
+
103
+ def self.api_url(url = '', rest_api_version = nil)
104
+ api_base = rest_api_version ? @@api_base.gsub(/v(\d).(\d)/, "v#{rest_api_version}") : @@api_base
105
+ api_base + url.to_s
106
+ end
107
+
108
+ def self.eligible_account
109
+ @@eligible_account
110
+ end
111
+
112
+ def self.eligible_account_id
113
+ @@eligible_account_id
114
+ end
30
115
 
31
- def self.api_url(url='')
32
- @@api_base + url
116
+ def self.eligible_account=(eligible_account)
117
+ @@eligible_account = eligible_account
118
+ end
119
+
120
+ def self.eligible_account_id=(eligible_account_id)
121
+ @@eligible_account_id = eligible_account_id
33
122
  end
34
123
 
35
124
  def self.api_key
@@ -40,161 +129,284 @@ module Eligible
40
129
  @@api_key = api_key
41
130
  end
42
131
 
132
+ def self.api_base
133
+ @@api_base
134
+ end
135
+
136
+ def self.api_base=(api_base)
137
+ @@api_base = api_base
138
+ end
139
+
140
+ def self.test
141
+ @@test ? 'true' : 'false'
142
+ end
143
+
144
+ def self.test=(is_test)
145
+ @@test = is_test
146
+ end
147
+
43
148
  def self.api_version=(version)
44
149
  @@api_version = version
45
150
  end
46
151
 
47
152
  def self.api_version
48
153
  @@api_version
49
- end
50
-
51
- def self.request(method, url, api_key, params={}, headers={})
52
- api_key ||= @@api_key
53
- raise AuthenticationError.new('No API key provided. (HINT: set your API key using "Eligible.api_key = <API-KEY>".') unless api_key
54
-
55
- # if !verify_ssl_certs
56
- # unless @no_verify
57
- # $stderr.puts "WARNING: Running without SSL cert verification. Execute 'Eligible.verify_ssl_certs = true' to enable verification."
58
- # @no_verify = true
59
- # end
60
- # ssl_opts = { :verify_ssl => false }
61
- # elsif !Util.file_readable(@@ssl_bundle_path)
62
- # unless @no_bundle
63
- # $stderr.puts "WARNING: Running without SSL cert verification because #{@@ssl_bundle_path} isn't readable"
64
- # @no_bundle = true
65
- # end
66
- # ssl_opts = { :verify_ssl => false }
67
- # else
68
- # ssl_opts = {
69
- # :verify_ssl => OpenSSL::SSL::VERIFY_PEER,
70
- # :ssl_ca_file => @@ssl_bundle_path
71
- # }
72
- # end
73
- uname = (@@uname ||= RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil)
74
- lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
75
- ua = {
76
- :bindings_version => Eligible::VERSION,
77
- :lang => 'ruby',
78
- :lang_version => lang_version,
79
- :platform => RUBY_PLATFORM,
80
- :publisher => 'eligible',
81
- :uname => uname
82
- }
154
+ end
83
155
 
84
- # params = Util.objects_to_ids(params)
85
- url = self.api_url(url)
86
- case method.to_s.downcase.to_sym
87
- when :get, :head, :delete
88
- # Make params into GET parameters
89
- url += "?api_key=#{api_key}"
90
- if params && params.count > 0
91
- query_string = Util.flatten_params(params).collect{|key, value| "#{key}=#{Util.url_encode(value)}"}.join('&')
92
- url += "&#{query_string}"
93
- end
94
- payload = nil
95
- else
96
- payload = Util.flatten_params(params).collect{|(key, value)| "#{key}=#{Util.url_encode(value)}"}.join('&')
97
- end
156
+ def self.fingerprints
157
+ @@fingerprints
158
+ end
98
159
 
99
- begin
100
- headers = { :x_eligible_client_user_agent => Eligible::JSON.dump(ua) }.merge(headers)
101
- rescue => e
102
- headers = {
103
- :x_eligible_client_raw_user_agent => ua.inspect,
104
- :error => "#{e} (#{e.class})"
105
- }.merge(headers)
106
- end
160
+ def self.add_fingerprint(digest)
161
+ $stderr.puts 'The embedded certificate fingerprint was modified. This should only be done if instructed to by eligible support staff'
162
+ @@fingerprints << digest
163
+ end
107
164
 
108
- headers = {
109
- :user_agent => "Eligible/v1 RubyBindings/#{Eligible::VERSION}",
110
- :authorization => "Bearer #{api_key}",
111
- :content_type => 'application/x-www-form-urlencoded'
112
- }.merge(headers)
165
+ def self.direct_response?(params)
166
+ params[:format].is_a?(String) && params[:format].downcase == 'x12'
167
+ end
113
168
 
114
- if self.api_version
115
- headers[:eligible_version] = self.api_version
116
- end
169
+ def self.test_key?(params)
170
+ Util.key?(params, :test)
171
+ end
172
+
173
+ def self.api_key?(params)
174
+ Util.key?(params, :api_key)
175
+ end
176
+
177
+ def self.rest_api_version?(params)
178
+ Util.key?(params, :rest_api_version)
179
+ end
180
+
181
+ def self.request(method, url, api_key, params = {}, headers = {})
182
+ session_token = Util.value(params, :session_token)
183
+ api_key ||= @@api_key unless session_token
184
+ test = self.test
185
+ api_key = Util.value(params, :api_key) if api_key?(params)
186
+ test = Util.value(params, :test) if test_key?(params)
187
+ rest_api_version = Util.value(params, :rest_api_version) if rest_api_version?(params)
188
+ basic_auth = true if rest_api_version?(params)
189
+
190
+ fail AuthenticationError, 'No API key provided. (HINT: set your API key using "Eligible.api_key = <API-KEY>".' unless api_key || session_token
191
+
192
+ lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
193
+ debug_info = {
194
+ bindings_version: Eligible::VERSION,
195
+ lang: 'ruby',
196
+ lang_version: lang_version,
197
+ platform: RUBY_PLATFORM,
198
+ publisher: 'eligible',
199
+ uname: uname
200
+ }
201
+
202
+ # Set request URL and Payload based on new and old endpoints version
203
+ url, payload = generate_request_url_and_payload(
204
+ method, url, params, { test: test, rest_api_version: rest_api_version, api_key: api_key, basic_auth: basic_auth },
205
+ )
206
+
207
+ # Set request Headers and Authorization based on new and old endpoints version
208
+ headers = generate_request_headers(headers, debug_info, basic_auth, { api_key: api_key, session_token: session_token })
117
209
 
118
210
  opts = {
119
- :method => method,
120
- :url => url,
121
- :headers => headers,
122
- :open_timeout => 30,
123
- :payload => payload,
124
- :timeout => 80
125
- }#.merge(ssl_opts)
126
-
211
+ method: method,
212
+ url: url,
213
+ headers: headers,
214
+ open_timeout: 30,
215
+ payload: payload,
216
+ timeout: 80,
217
+ ssl_verify_callback: verify_certificate,
218
+ ssl_verify_callback_warnings: false
219
+ }
220
+
127
221
  begin
128
222
  response = execute_request(opts)
223
+
129
224
  rescue SocketError => e
130
- self.handle_restclient_error(e)
225
+ handle_restclient_error(e)
226
+
131
227
  rescue NoMethodError => e
132
228
  # Work around RestClient bug
133
- if e.message =~ /\WRequestFailed\W/
134
- e = APIConnectionError.new('Unexpected HTTP response code')
135
- self.handle_restclient_error(e)
136
- else
137
- raise
138
- end
229
+ raise unless e.message =~ /\WRequestFailed\W/
230
+
231
+ e = APIConnectionError.new('Unexpected HTTP response code')
232
+ handle_restclient_error(e)
233
+
139
234
  rescue RestClient::ExceptionWithResponse => e
140
- if rcode = e.http_code and rbody = e.http_body
141
- self.handle_api_error(rcode, rbody)
235
+ err_rcode = e.http_code
236
+ err_rbody = e.http_body
237
+
238
+ if err_rcode && err_rbody
239
+ handle_api_error(err_rcode, err_rbody)
142
240
  else
143
- self.handle_restclient_error(e)
241
+ handle_restclient_error(e)
144
242
  end
243
+
145
244
  rescue RestClient::Exception, Errno::ECONNREFUSED => e
146
- self.handle_restclient_error(e)
245
+ handle_restclient_error(e)
147
246
  end
148
247
 
149
248
  rbody = response.body
150
249
  rcode = response.code
250
+
151
251
  begin
152
252
  # Would use :symbolize_names => true, but apparently there is
153
253
  # some library out there that makes symbolize_names not work.
154
- resp = Eligible::JSON.load(rbody)
254
+ resp = direct_response?(params) ? rbody : Eligible::JSON.load(rbody)
155
255
  rescue MultiJson::DecodeError
156
256
  raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
157
257
  end
158
258
 
159
259
  resp = Util.symbolize_names(resp)
160
- [resp, api_key]
260
+ return [ resp, api_key ]
261
+ end
262
+
263
+ def self.generate_request_url_and_payload(method, url, params, options)
264
+ # GET requests, parameters on the query string
265
+ # POST requests, parameters as json in the body
266
+ url = api_url(url, options[:rest_api_version])
267
+ # Used rest_api_version param only to identify new REST API version, and is not required to make calls for new REST api endpoints
268
+ params.delete(:rest_api_version)
269
+ case method.to_s.downcase.to_sym
270
+ when :get, :head, :delete
271
+ url = fetch_url_with_query_string(params, url, options)
272
+ payload = nil
273
+ else
274
+ payload = request_payload(options, params)
275
+ end
276
+
277
+ [url, payload]
278
+ end
279
+
280
+ def self.fetch_url_with_query_string(params, url, options)
281
+ url += options_query_string(options)
282
+ return url unless params || params.count == 0
283
+
284
+ query_string = params_query_string(params)
285
+ url += options[:basic_auth] ? "?#{query_string}" : "&#{query_string}"
286
+ url
287
+ end
288
+
289
+ def self.options_query_string(options)
290
+ options[:basic_auth] ? '' : "?test=#{options[:test]}&api_key=#{options[:api_key]}"
291
+ end
292
+
293
+ def self.params_query_string(params)
294
+ Util.flatten_params(params).collect { |key, value| "#{key}=#{Util.url_encode(value)}" }.join('&')
295
+ end
296
+
297
+ def self.request_payload(options, params)
298
+ params.merge!('test' => options[:test], 'api_key' => options[:api_key]) unless options[:basic_auth]
299
+ Util.key?(params, :file) ? params : Eligible::JSON.dump(params)
300
+ end
301
+
302
+ def self.generate_request_headers(headers, debug_info, basic_auth, auth_options)
303
+ begin
304
+ headers = { x_eligible_debuginfo: Eligible::JSON.dump(debug_info) }.merge(headers)
305
+ rescue => e
306
+ headers = {
307
+ x_eligible_client_raw_user_agent: debug_info.inspect,
308
+ error: "#{e} (#{e.class})"
309
+ }.merge(headers)
310
+ end
311
+
312
+ headers = {
313
+ user_agent: "eligible-ruby/#{Eligible::VERSION}",
314
+ content_type: 'application/json'
315
+ }.merge(headers)
316
+
317
+ headers[:authorization] = authorization_header(basic_auth, auth_options)
318
+ headers[:eligible_version] = api_version if api_version
319
+ headers[:eligible_account] = eligible_account if eligible_account
320
+ headers[:eligible_account_id] = eligible_account_id if eligible_account_id
321
+ headers
322
+ end
323
+
324
+ def self.authorization_header(basic_auth, auth_options)
325
+ # Using Bearer scheme for Session Token Auth for new REST API endpoints (v1.0)
326
+ return "Bearer #{auth_options[:session_token]}" if basic_auth && auth_options[:session_token]
327
+
328
+ # Using Basic Auth for new REST API endpoints (v1.0)
329
+ basic_auth_token = Base64.strict_encode64("#{auth_options[:api_key]}:")
330
+ "Basic #{basic_auth_token}" if basic_auth
331
+ end
332
+
333
+ def self.verify_certificate
334
+ lambda do |preverify_ok, certificate_store|
335
+ return true if test == 'true'
336
+ return false unless preverify_ok
337
+ received = certificate_store.chain.first
338
+ return true unless received.to_der == certificate_store.current_cert.to_der
339
+ valid_fingerprint?(received)
340
+ end
341
+ end
342
+
343
+ def self.valid_fingerprint?(received)
344
+ fingerprints.include?(OpenSSL::Digest::SHA1.hexdigest(received.to_der))
161
345
  end
162
346
 
163
347
  private
164
348
 
349
+ def self.uname
350
+ @@uname ||= RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil
351
+ end
352
+
165
353
  def self.execute_request(opts)
166
354
  RestClient::Request.execute(opts)
167
355
  end
168
356
 
357
+ def self.error_message(error, errors)
358
+ message = compose_message_from_errors(errors)
359
+ return message if message
360
+
361
+ return compose_message_from_error(error)
362
+ end
363
+
364
+ def self.compose_message_from_errors(errors)
365
+ return unless errors.is_a?(Array)
366
+
367
+ return errors.first[:message] if errors.size == 1
368
+ return errors.each_with_index.map { |error, index| "#{index + 1}. #{error[:message]}" }.join("\n")
369
+ end
370
+
371
+ def self.compose_message_from_error(error)
372
+ return error.to_s unless error.is_a?(Hash)
373
+ result = error[:details] || error[:reject_reason_description] || error
374
+ return result.to_s
375
+ end
376
+
169
377
  def self.handle_api_error(rcode, rbody)
170
378
  begin
171
- error_obj = Eligible::JSON.load(rbody)
172
- error_obj = Util.symbolize_names(error_obj)
173
- error = error_obj[:error] or raise EligibleError.new # escape from parsing
379
+ error_obj = Util.symbolize_names(Eligible::JSON.load(rbody))
380
+ fail EligibleError unless error_obj.keys.any? { |k| [:error, :errors].include? k }
381
+ error = error_obj[:error]
382
+ errors = error_obj[:errors]
383
+
174
384
  rescue MultiJson::DecodeError, EligibleError
175
385
  raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
176
386
  end
177
387
 
388
+ error_msg = error_message(error, errors)
389
+
178
390
  case rcode
179
391
  when 400, 404 then
180
- raise invalid_request_error(error, rcode, rbody, error_obj)
392
+ raise invalid_request_error(error_msg, rcode, rbody, error_obj)
181
393
  when 401
182
- raise authentication_error(error, rcode, rbody, error_obj)
394
+ raise authentication_error(error_msg, rcode, rbody, error_obj)
183
395
  else
184
- raise api_error(error, rcode, rbody, error_obj)
396
+ raise api_error(error_msg, rcode, rbody, error_obj)
185
397
  end
186
398
  end
187
399
 
188
- def self.invalid_request_error(error, rcode, rbody, error_obj)
189
- InvalidRequestError.new(error[0][:message], error[:param], rcode, rbody, error_obj)
400
+ def self.invalid_request_error(error_msg, rcode, rbody, error_obj)
401
+ InvalidRequestError.new(error_msg, rcode, rbody, error_obj)
190
402
  end
191
403
 
192
- def self.authentication_error(error, rcode, rbody, error_obj)
193
- AuthenticationError.new(error[0][:message], rcode, rbody, error_obj)
404
+ def self.authentication_error(error_msg, rcode, rbody, error_obj)
405
+ AuthenticationError.new(error_msg, rcode, rbody, error_obj)
194
406
  end
195
407
 
196
- def self.api_error(error, rcode, rbody, error_obj)
197
- APIError.new(error[0][:message], rcode, rbody, error_obj)
408
+ def self.api_error(error_msg, rcode, rbody, error_obj)
409
+ APIError.new(error_msg, rcode, rbody, error_obj)
198
410
  end
199
411
 
200
412
  def self.handle_restclient_error(e)
@@ -204,12 +416,10 @@ module Eligible
204
416
  when RestClient::SSLCertificateNotVerified
205
417
  message = "Could not verify Eligible's SSL certificate."
206
418
  when SocketError
207
- message = "Unexpected error communicating when trying to connect to Eligible."
419
+ message = 'Unexpected error communicating when trying to connect to Eligible.'
208
420
  else
209
- message = "Unexpected error communicating with Eligible. If this problem persists, let us know at support@eligible.com."
421
+ message = 'Unexpected error communicating with Eligible. If this problem persists, let us know at support@eligible.com.'
210
422
  end
211
- message += "\n\n(Network error: #{e.message})"
212
- raise APIConnectionError.new(message)
423
+ fail APIConnectionError, "#{message}\n\n(Network error: #{e.message})"
213
424
  end
214
-
215
425
  end