zuora_api 1.5.2 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a2562d0e1fc0b764b99527767d97fb9704dca85
4
- data.tar.gz: 00d14264577aa610bbfe43a6ee7a4e6fd96aba78
3
+ metadata.gz: 65fac01cabaf327d7cf9b15fbce13cfb784ecc28
4
+ data.tar.gz: 3d02d5242b1800403685ef3408891337de774f98
5
5
  SHA512:
6
- metadata.gz: 6e798a1b0c0b48b485b07982a08d011d3792806743f10e8f7e897ca532e5ce0044a0ebe9e5a0ba2be8531b692a4a129cb74cfc0fe1a08b0ec024cbab2c517549
7
- data.tar.gz: 59e269e8983d29af0fc7d8ff85ad4b36aa50a9539d90a4e2920c1774d21cb7422b00c64e008ebca18154ebfc80edc64f05549e247410d706f813b4d46fd1563b
6
+ metadata.gz: cb9dc6f29b775a6174470fd1c122da7951ba05a5b43a700cd23001e2b584654d337e2b5489b900f158d9a1ddab7d4eb3efc7ac02139df7925e410e81647159f8
7
+ data.tar.gz: e9f520c636e4c6f7b2a51088af86bd916fd6191102e4f555f16c2bc9af97f70a379af42cc067d5fd2a7a02a09efdc42a7ede6408560e66df11795ae168bb0bb3
@@ -47,17 +47,4 @@ rubygems-deploy:
47
47
  - curl -u $USERNAME:$PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
48
48
  - gem push $version
49
49
  only:
50
- - master
51
-
52
- rubygems-deploy:
53
- stage: deploy
54
- allow_failure: false
55
- when: manual
56
- script:
57
- - bundle install
58
- - gem install rake
59
- - version=$(rake install | grep -o 'pkg/zuora_api-.*gem')
60
- - curl -u $USERNAME:$PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
61
- - gem push $version
62
- only:
63
- - staging
50
+ - master
@@ -1,8 +1,9 @@
1
1
  require 'rails'
2
2
  require "zuora_api/login"
3
+ require "zuora_api/logins/basic"
4
+ require "zuora_api/logins/oauth"
3
5
  require 'zuora_api/exceptions'
4
6
  require "insights_api/login"
5
- require "zuora_api/metrics_helper"
6
7
  module ZuoraAPI
7
8
  # Your code goes here...
8
9
  end
@@ -2,7 +2,6 @@ module ZuoraAPI
2
2
  module Exceptions
3
3
  class Error < StandardError; end
4
4
  class AuthorizationNotPerformed < Error; end
5
-
6
5
  class ZuoraAPISessionError < Error
7
6
  attr_reader :code, :response
8
7
  attr_writer :default_message
@@ -19,6 +18,24 @@ module ZuoraAPI
19
18
  end
20
19
  end
21
20
 
21
+ class BadEntityError < Error
22
+ attr_reader :code, :response, :errors, :successes
23
+ attr_writer :default_message
24
+
25
+ def initialize(message = nil,response=nil, code =nil, errors = [], successes = [])
26
+ @code = code
27
+ @message = message
28
+ @response = response
29
+ @default_message = "Error with Zuora Entity"
30
+ @errors = errors
31
+ @successes = successes
32
+ end
33
+
34
+ def to_s
35
+ @message || @default_message
36
+ end
37
+ end
38
+
22
39
  class ZuoraAPIError < Error
23
40
  attr_reader :code, :response, :errors, :successes
24
41
  attr_writer :default_message
@@ -68,5 +85,22 @@ module ZuoraAPI
68
85
  @message || @default_message
69
86
  end
70
87
  end
88
+
89
+
90
+ class ZuoraAPIAuthenticationTypeError < Error
91
+ attr_reader :code, :response
92
+ attr_writer :default_message
93
+
94
+ def initialize(message = nil,response=nil, code =nil)
95
+ @code = code
96
+ @message = message
97
+ @response = response
98
+ @default_message = "Authentication type is not supported by this Login"
99
+ end
100
+
101
+ def to_s
102
+ @message || @default_message
103
+ end
104
+ end
71
105
  end
72
106
  end
@@ -6,29 +6,26 @@ module ZuoraAPI
6
6
  class Login
7
7
  ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown' ]
8
8
  REGIONS = [EU = 'EU', US = 'US' ]
9
- XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
10
- attr_accessor :username, :password, :region,:url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep
9
+ XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
10
+ attr_accessor :region, :url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep
11
11
 
12
- def initialize(username: nil, password: nil, status: nil, url: nil, entity_id: nil, session: nil, **keyword_args)
13
- @username = username
14
- @password = password
12
+ def initialize(url: nil, entity_id: nil, session: nil, status: nil, **keyword_args)
15
13
  @url = url
16
14
  @entity_id = entity_id
17
- @current_session = session
18
15
  @errors = Hash.new
16
+ @current_session = session
19
17
  @status = status.blank? ? "Active" : status
20
18
  @user_info = Hash.new
21
19
  self.update_environment
22
20
  @timeout_sleep = 5
23
21
  end
24
22
 
25
-
26
23
  def self.environments
27
- %w(Sandbox Production Services Performance)
24
+ %w(Sandbox Production Services Performance Staging)
28
25
  end
29
26
 
30
27
  def self.regions
31
- %w(US EU)
28
+ %w(US EU NA)
32
29
  end
33
30
 
34
31
  def self.endpoints
@@ -39,23 +36,28 @@ module ZuoraAPI
39
36
  "EU" => {"Sandbox" => "https://sandbox.eu.zuora.com/apps/services/a/",
40
37
  "Production" => "https://eu.zuora.com/apps/services/a/",
41
38
  "Performance" => "https://pt1.eu.zuora.com/apps/services/a/",
42
- "Services" => "https://services347.eu.zuora.com/apps/services/a/"}
39
+ "Services" => "https://services347.eu.zuora.com/apps/services/a/"},
40
+ "NA" => {"Sandbox" => "https://sandbox.na.zuora.com/apps/services/a/",
41
+ "Production" => "https://na.zuora.com/apps/services/a/",
42
+ "Performance" => "https://pt1.na.zuora.com/apps/services/a/",
43
+ "Services" => "https://services347.na.zuora.com/apps/services/a/"}
43
44
  }
44
45
  end
45
46
 
46
47
  def update_environment
47
48
  if !self.url.blank?
48
49
  env_path = self.url.split('https://').last.split('.zuora.com').first
49
- self.region = self.url.include?("eu.") ? "EU" : "US"
50
+ self.region = self.url.include?("eu.") ? "EU" : self.url.include?("na.") ? "NA" : "US"
50
51
  if env_path == 'apisandbox' || self.url.include?('sandbox')
51
52
  self.environment = 'Sandbox'
52
- elsif env_path == 'www' || env_path == 'api' || self.url.include?('tls10.zuora.com') || self.url.include?('origin-www.zuora.com') || self.url.include?('zforsf.zuora.com') || self.url.include?('https://zuora.com') || self.url.include?('eu.zuora.com')
53
+ elsif env_path == 'www' || env_path == 'api' || self.url.include?('tls10.zuora.com') || self.url.include?('origin-www.zuora.com') || self.url.include?('zforsf.zuora.com') || self.url.include?('https://zuora.com') || self.url.include?('eu.zuora.com') || self.url.include?('https://na.zuora.com')
53
54
  self.environment = 'Production'
54
55
  elsif env_path.include?('service') || env_path.include?('ep-edge')
55
56
  self.environment = 'Services'
56
57
  elsif env_path.include?('pt')
57
58
  self.environment = 'Performance'
58
- elsif env_path.include?('app-0')
59
+ elsif env_path.include?('staging2') || env_path.include?('staging1')
60
+ self.region = 'US'
59
61
  self.environment = 'Staging'
60
62
  else
61
63
  self.environment = 'Unknown'
@@ -69,9 +71,9 @@ module ZuoraAPI
69
71
 
70
72
  def rest_endpoint(url="")
71
73
  if self.environment == 'Sandbox'
72
- return self.region == "US" ? "https://rest.apisandbox.zuora.com/v1/".concat(url) : "https://rest.sandbox.eu.zuora.com/v1/".concat(url)
74
+ return self.region == "US" ? "https://rest.apisandbox.zuora.com/v1/".concat(url) : self.region == "EU" ? "https://rest.sandbox.eu.zuora.com/v1/".concat(url) : "https://rest.sandbox.na.zuora.com/v1/".concat(url)
73
75
  elsif self.environment == 'Production'
74
- return self.region == "US" ? "https://rest.zuora.com/v1/".concat(url) : "https://rest.eu.zuora.com/v1/".concat(url)
76
+ return self.region == "US" ? "https://rest.zuora.com/v1/".concat(url) : self.region == "EU" ? "https://rest.eu.zuora.com/v1/".concat(url) : "https://rest.na.zuora.com/v1/".concat(url)
75
77
  elsif self.environment == 'Services'
76
78
  return self.url.split('/')[0..2].join('/').concat('/apps/v1/').concat(url)
77
79
  elsif self.environment == 'Performance'
@@ -89,130 +91,45 @@ module ZuoraAPI
89
91
  return self.wsdl_number > 68 ? '%Y-%m-%d' : '%Y-%m-%dT%H:%M:%S'
90
92
  end
91
93
 
92
- def new_session(debug: false)
93
- tries ||= 2
94
- request = Nokogiri::XML::Builder.new do |xml|
95
- xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' =>"http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:api' => "http://api.zuora.com/" ) do
96
- if (self.password.blank? && !self.current_session.blank?)
97
- Rails.logger.debug("Method [Session]")
98
- xml['SOAP-ENV'].Header do
99
- xml['api'].SessionHeader do
100
- xml['api'].session self.current_session
101
- end
102
- end
103
- xml['SOAP-ENV'].Body do
104
- xml['api'].getUserInfo
94
+ def new_session(auth_type: :basic, debug: false)
95
+ end
96
+
97
+ def get_session(prefix: false, auth_type: :basic)
98
+ Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}")
99
+ case auth_type
100
+ when :basic
101
+ if self.current_session.blank?
102
+ Rails.logger.debug("Create new session")
103
+ case self.class.to_s
104
+ when 'ZuoraAPI::Oauth'
105
+ if self.bearer_token.blank? || self.oauth_expired?
106
+ self.new_session(auth_type: :bearer)
105
107
  end
108
+ self.get_z_session
109
+ when 'ZuoraAPI::Basic'
110
+ self.new_session(auth_type: :basic)
106
111
  else
107
- xml['SOAP-ENV'].Header
108
- xml['SOAP-ENV'].Body do
109
- xml['api'].login do
110
- xml['api'].username self.username
111
- xml['api'].password self.password
112
- xml['api'].entityId self.entity_id if !self.entity_id.blank?
113
- end
114
- end
112
+ raise "No Zuora Login Specified"
115
113
  end
116
114
  end
117
- end
118
-
119
-
120
- input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
121
- input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
122
- Rails.logger.debug('Connect') {"Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
123
-
124
- @response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => 10)
125
- @output_xml = Nokogiri::XML(@response_query.body)
126
- Rails.logger.debug('Connect') {"Response SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
127
-
128
-
129
- if !@response_query.success?
130
- self.current_session = nil
131
- if @output_xml.namespaces.size > 0 && @output_xml.xpath('//soapenv:Fault').size > 0
132
- self.current_error = @output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
133
- if self.current_error.include?('deactivated')
134
- self.status = 'Deactivated'
135
- self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
136
- self.errors[:username] = self.current_error
137
- elsif self.current_error.include?('inactive')
138
- self.status = 'Inactive'
139
- self.current_error = 'Inactive user login, please check with Zuora tenant administrator'
140
- self.errors[:username] = self.current_error
141
- elsif self.current_error.include?("invalid username or password") || self.current_error.include?("Invalid login. User name and password do not match.")
142
- self.status = 'Invalid Login'
143
- self.current_error = 'Invalid login, please check username and password or URL endpoint'
144
- self.errors[:username] = self.current_error
145
- self.errors[:password] = self.current_error
146
- elsif self.current_error.include?('unsupported version')
147
- self.status = 'Unsupported API Version'
148
- self.current_error = 'Unsupported API version, please verify URL endpoint'
149
- self.errors[:url] = self.current_error
150
- elsif self.current_error.include?('invalid api version')
151
- self.status = 'Invalid API Version'
152
- self.current_error = 'Invalid API version, please verify URL endpoint'
153
- self.errors[:url] = self.current_error
154
- elsif self.current_error.include?('invalid session')
155
- self.status = 'Invalid Session'
156
- self.current_error = 'Session invalid, please update session and verify URL endpoint'
157
- self.errors[:session] = self.current_error
158
- elsif self.current_error.include?('Your IP address')
159
- self.status = 'Restricted IP'
160
- self.current_error = 'IP restricted, contact Zuora tenant administrator and remove IP restriction'
161
- self.errors[:base] = self.current_error
162
- elsif self.current_error.include?('This account has been locked')
163
- self.status = 'Locked'
164
- self.current_error = 'Locked user login, please wait or navigate to Zuora to unlock user'
165
- self.errors[:username] = self.current_error
166
- else
167
- self.status = 'Unknown'
168
- self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
169
- self.errors[:base] = self.current_error
115
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
116
+ return prefix ? "ZSession #{self.current_session}" : self.current_session.to_s
117
+ when :bearer
118
+ case self.class.to_s
119
+ when 'ZuoraAPI::Oauth'
120
+ if self.bearer_token.blank? || self.oauth_expired?
121
+ self.new_session(auth_type: :bearer)
170
122
  end
171
- else
172
- self.current_error = "Code = #{@response_query.code} Message = #{@response_query.body.to_s}"
173
- self.status = 'No Service'
123
+ when 'ZuoraAPI::Basic'
124
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}")
174
125
  end
175
- else
176
- #If Session only is used for Gem TODO Depercate
177
- if (self.password.blank? && self.current_session.present?)
178
- self.current_session = self.current_session
179
- self.username = @output_xml.xpath('//ns1:Username', 'ns1' =>'http://api.zuora.com/').text if self.username.blank?
180
-
181
- #Username & password combo
182
- elsif (self.password.present? && self.username.present?)
183
- retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
184
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
185
- self.current_session = retrieved_session
186
- end
187
-
188
- self.current_error = nil
189
- self.status = 'Active'
126
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
127
+ return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
190
128
  end
191
- return self.status
192
- rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
193
- if !(tries -= 1).zero?
194
- Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
195
- sleep(self.timeout_sleep)
196
- retry
197
- else
198
- self.current_error = "Request timed out. Try again"
199
- self.status = 'Timeout'
200
- return self.status
201
- end
202
- end
203
-
204
- def get_session
205
- Rails.logger.debug("Create new session") if self.current_session.blank?
206
- self.new_session if self.current_session.blank?
207
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
208
- return self.current_session
209
129
  end
210
130
 
211
- def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug: true, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError, ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition], z_session: true, timeout_retry: false, timeout: 120,**keyword_args)
131
+ def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError, ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition], z_session: true, timeout_retry: false, timeout: 120,**keyword_args)
212
132
  tries ||= 2
213
- error_type = ""
214
- start_time = Time.now
215
-
216
133
  xml = Nokogiri::XML::Builder.new do |xml|
217
134
  xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/",
218
135
  "xmlns:#{ns2}" => "http://object.api.zuora.com/",
@@ -221,7 +138,7 @@ module ZuoraAPI
221
138
  "xmlns:#{ns1}" => "http://api.zuora.com/") do
222
139
  xml['SOAP-ENV'].Header do
223
140
  xml["#{ns1}"].SessionHeader do
224
- xml["#{ns1}"].session self.get_session
141
+ xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic)
225
142
  end
226
143
  if single_transaction
227
144
  xml["#{ns1}"].CallOptions do
@@ -242,19 +159,17 @@ module ZuoraAPI
242
159
 
243
160
  input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
244
161
  input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
245
- Rails.logger.debug('Connect') {"Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
162
+ Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
246
163
 
247
164
  response = HTTParty.post(self.url,:body => xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => timeout)
248
165
  output_xml = Nokogiri::XML(response.body)
249
- Rails.logger.debug('Connect') {"Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
166
+ Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
250
167
 
251
168
  raise_errors(type: :SOAP, body: output_xml, response: response)
252
-
253
169
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
254
- error_type = "#{ex.class}"
255
170
  if !(tries -= 1).zero? && z_session
256
- Rails.logger.debug {"Session Invalid"}
257
- self.new_session
171
+ Rails.logger.debug("SOAP Call - Session Invalid")
172
+ self.new_session(auth_type: :basic)
258
173
  retry
259
174
  else
260
175
  if errors.include?(ex.class)
@@ -264,37 +179,23 @@ module ZuoraAPI
264
179
  end
265
180
  end
266
181
  rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
267
- error_type = "#{ex.class}"
268
182
  if errors.include?(ex.class)
269
183
  raise ex
270
184
  else
271
185
  return output_xml, input_xml, response
272
186
  end
273
187
  rescue Net::OpenTimeout, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
274
- error_type = "#{ex.class}"
275
188
  if !(tries -= 1).zero? && timeout_retry
276
- Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
189
+ Rails.logger.info("SOAP Call - #{ex.class} Timed out will retry after 5 seconds")
277
190
  sleep(self.timeout_sleep)
278
191
  retry
279
192
  else
280
193
  raise ex
281
194
  end
282
195
  rescue => ex
283
- error_type = "#{ex.class}"
284
196
  raise ex
285
197
  else
286
198
  return output_xml, input_xml, response
287
- ensure
288
- # Writing to telegraf
289
- begin
290
- end_time = Time.now
291
- response_time = end_time - start_time
292
- status_code = response.code if response
293
- endpoint_name = url.present? ? URI(url).host : url
294
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
295
- rescue => ex
296
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
297
- end
298
199
  end
299
200
 
300
201
  def raise_errors(type: :SOAP, body: nil, response: nil)
@@ -344,7 +245,11 @@ module ZuoraAPI
344
245
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code)
345
246
  end
346
247
  elsif error.class == Array
347
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), body, response.code, error, success)
248
+ if error[0].include?("LOCK_COMPETITION") && error.count == 1
249
+ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), body, response.code)
250
+ else
251
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), body, response.code, error, success)
252
+ end
348
253
  end
349
254
  end
350
255
 
@@ -357,6 +262,17 @@ module ZuoraAPI
357
262
  messages_array = (body["reasons"] || []).map {|error| error['message']}.compact
358
263
  codes_array = (body["reasons"] || []).map {|error| error['code']}.compact
359
264
 
265
+ if body['message'] == "No bearer token" && response.code == 400
266
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new()
267
+ end
268
+
269
+ if body.dig("reasons").nil? ? false : body.dig("reasons")[0].dig("code") == 90000020
270
+ raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", body, response.code)
271
+ end
272
+
273
+ if body['error'] == 'Unauthorized' && body['status'] = 401
274
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
275
+ end
360
276
  #Authentication failed
361
277
  if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401
362
278
  raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
@@ -470,14 +386,10 @@ module ZuoraAPI
470
386
  def describe_call(object = nil)
471
387
  tries ||= 2
472
388
 
473
- error_type = ""
474
- start_time = Time.now
475
-
476
- self.get_session
477
389
  base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
478
390
  url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
479
391
  headers = !self.entity_id.blank? ? {"entityId" => self.entity_id, 'Content-Type' => "text/xml; charset=utf-8"} : {'Content-Type' => "text/xml; charset=utf-8"}
480
- response = HTTParty.get(url, :headers => headers , basic_auth: {:username => self.username, :password => self.password}, :timeout => 120)
392
+ response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
481
393
 
482
394
  output_xml = Nokogiri::XML(response.body)
483
395
  des_hash = Hash.new
@@ -509,55 +421,48 @@ module ZuoraAPI
509
421
  des_hash[:related_objects] = output_xml.xpath(".//related-objects").xpath(".//object").map{ |x| [x.xpath(".//name").text.to_sym, [ [:url, x.attributes["href"].value], [:label, x.xpath(".//name").text ] ].to_h] }.to_h
510
422
  end
511
423
  rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
512
- error_type = "#{ex.class}"
513
424
  if !(tries -= 1).zero?
514
- Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
425
+ Rails.logger.info("Describe - #{ex.class} Timed out will retry after 5 seconds")
515
426
  sleep(self.timeout_sleep)
516
427
  retry
517
428
  else
518
429
  raise ex
519
430
  end
520
431
  rescue => ex
521
- error_type = "#{ex.class}"
522
432
  raise ex
523
433
  else
524
434
  return des_hash
525
- ensure
526
- # Writing to telegraf
527
- begin
528
- end_time = Time.now
529
- response_time = end_time - start_time
530
- status_code = response.code if response
531
- endpoint_name = url.present? ? URI(url).host : url
532
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET")
533
- rescue => ex
534
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
535
- end
536
435
  end
537
436
 
538
- def rest_call(method: :get, body: {},headers: {}, url: rest_endpoint("catalog/products?pageSize=4"), debug: true, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError, ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition], z_session: true, timeout_retry: false, timeout: 120, **keyword_args)
437
+ def rest_call(method: :get, body: nil,headers: {}, url: rest_endpoint("catalog/products?pageSize=4"), debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError, ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition], z_session: true, session_type: :basic, timeout_retry: false, timeout: 120, **keyword_args)
539
438
  tries ||= 2
540
439
  headers["entityId"] = self.entity_id if !self.entity_id.blank?
541
440
  raise "Method not supported, supported methods include: :get, :post, :put, :delete, :patch, :head, :options" if ![:get, :post, :put, :delete, :patch, :head, :options].include?(method)
441
+
442
+ authentication_headers = z_session ? {"Authorization" => self.get_session(prefix: true, auth_type: session_type) } : {}
443
+ headers = {'Content_Type' => "application/json; charset=utf-8"}.merge(headers).merge(authentication_headers)
542
444
 
543
- error_type = ""
544
- start_time = Time.now
545
- response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: {'Content-Type' => "application/json; charset=utf-8"}.merge(z_session ? {"Authorization" => "ZSession #{self.get_session}"} : {}).merge(headers), timeout: timeout).perform
546
-
445
+ response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: headers, timeout: timeout).perform
446
+ Rails.logger.debug("Response Code: #{response.code}") if debug
547
447
  begin
548
448
  output_json = JSON.parse(response.body)
549
449
  rescue JSON::ParserError => ex
550
450
  output_json = {}
551
451
  end
552
- Rails.logger.debug('Connect') {"Response JSON: #{output_json}"} if debug && output_json.present?
452
+ Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
553
453
 
554
454
  raise_errors(type: :JSON, body: output_json, response: response)
555
-
455
+ rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
456
+ if self.class.to_s == 'ZuoraAPI::Oauth'
457
+ self.rest_call(method: method.to_sym, url: url, debug: debug, errors: errors, z_session: z_session, session_type: :bearer, timeout_retry: timeout_retry, timeout: timeout)
458
+ else
459
+ Rails.logger.debug("Rest Call - Session Bad Auth type")
460
+ raise ex
461
+ end
556
462
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
557
- error_type = "#{ex.class}"
558
463
  if !(tries -= 1).zero? && z_session
559
- Rails.logger.debug {"Session Invalid"}
560
- self.new_session
464
+ Rails.logger.debug("Rest Call - Session Invalid")
465
+ self.new_session(auth_type: session_type)
561
466
  retry
562
467
  else
563
468
  if errors.include?(ex.class)
@@ -567,37 +472,25 @@ module ZuoraAPI
567
472
  end
568
473
  end
569
474
  rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
570
- error_type = "#{ex.class}"
571
475
  if errors.include?(ex.class)
572
476
  raise ex
573
477
  else
574
478
  return [output_json, response]
575
479
  end
480
+ rescue ZuoraAPI::Exceptions::BadEntityError => ex
481
+ raise ex
576
482
  rescue Net::OpenTimeout, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
577
- error_type = "#{ex.class}"
578
483
  if !(tries -= 1).zero? && timeout_retry
579
- Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
484
+ Rails.logger.info("Rest Call - #{ex.class} Timed out will retry after 5 seconds")
580
485
  sleep(self.timeout_sleep)
581
486
  retry
582
487
  else
583
488
  raise ex
584
489
  end
585
490
  rescue => ex
586
- error_type = "#{ex.class}"
587
491
  raise ex
588
492
  else
589
493
  return [output_json, response]
590
- ensure
591
- # Writing to telegraf
592
- begin
593
- end_time = Time.now
594
- response_time = end_time - start_time
595
- status_code = response.code if response
596
- endpoint_name = url.present? ? URI(url).host : url
597
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "#{method.upcase}")
598
- rescue => ex
599
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
600
- end
601
494
  end
602
495
 
603
496
  def update_create_tenant
@@ -653,16 +546,13 @@ module ZuoraAPI
653
546
  require 'fileutils'
654
547
  FileUtils.mkdir_p(file_path) unless File.exists?(file_path)
655
548
 
656
- error_type = ""
657
- start_time = Time.now
658
-
659
549
  begin
660
550
  status_code = nil
661
551
  uri = URI.parse(url)
662
552
  http = Net::HTTP.new(uri.host, uri.port)
663
553
  http.read_timeout = timeout #Seconds
664
554
  http.use_ssl = true if uri.scheme.downcase == 'https'
665
- headers = headers.merge({"Authorization" => "ZSession #{self.get_session}"}) if z_session
555
+ headers = headers.merge({"Authorization" => self.get_session(prefix: true)}) if z_session
666
556
 
667
557
  response_save = nil
668
558
  http.request_get(uri.path, headers) do |response|
@@ -753,40 +643,26 @@ module ZuoraAPI
753
643
  end
754
644
 
755
645
  file_handle.close
756
- Rails.logger.info("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb")
646
+ Rails.logger.debug("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb")
757
647
 
758
648
  return file_handle
759
649
  end
760
650
  end
761
651
  rescue Exception => e
762
- error_type = "#{e.class}"
763
- Rails.logger.fatal('GetFile') {"Download Failed: #{response_save} - #{e.class} : #{e.message}"}
764
- Rails.logger.fatal('GetFile') {"Download Failed: #{e.backtrace.join("\n")}"}
652
+ Rails.logger.fatal("Download Failed: #{response_save} - #{e.class} : #{e.message}")
653
+ Rails.logger.fatal("Download Failed: #{e.backtrace.join("\n")}")
765
654
  raise
766
- ensure
767
- # Writing to telegraf
768
- begin
769
- end_time = Time.now
770
- response_time = end_time - start_time
771
- status_code = response.code if response
772
- endpoint_name = url.present? ? URI(url).host : url
773
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET")
774
- rescue => ex
775
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
776
- end
777
655
  end
778
656
  end
779
657
 
780
658
  def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
781
- error_type = ""
782
- start_time = Time.now
783
- Rails.logger.info('Export') {"Build export"}
784
- Rails.logger.debug('Export query') {"#{query}"}
659
+ Rails.logger.debug("Build export")
660
+ Rails.logger.debug("#{query}")
785
661
  request = Nokogiri::XML::Builder.new do |xml|
786
662
  xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:ns2' => "http://object.api.zuora.com/", 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", 'xmlns:ns1' => "http://api.zuora.com/") do
787
663
  xml['SOAP-ENV'].Header do
788
664
  xml['ns1'].SessionHeader do
789
- xml['ns1'].session self.current_session
665
+ xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
790
666
  end
791
667
  end
792
668
  xml['SOAP-ENV'].Body do
@@ -803,24 +679,9 @@ module ZuoraAPI
803
679
  end
804
680
  end
805
681
 
806
- begin
807
- response_query = HTTParty.post(self.url, body: request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8"}, :timeout => 120)
808
- rescue => e
809
- error_type = "#{e.class}"
810
- ensure
811
- begin
812
- end_time = Time.now
813
- response_time = end_time - start_time
814
- status_code = response.code if response
815
- endpoint_name = url.present? ? URI(url).host : url
816
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
817
- rescue => ex
818
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
819
- end
820
- end
821
-
682
+ response_query = HTTParty.post(self.url, body: request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8"}, :timeout => 120)
683
+
822
684
  output_xml = Nokogiri::XML(response_query.body)
823
-
824
685
  raise 'Export Creation Unsuccessful : ' + output_xml.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
825
686
  id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
826
687
 
@@ -828,7 +689,7 @@ module ZuoraAPI
828
689
  xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:ns2' => "http://object.api.zuora.com/", 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", 'xmlns:ns1' => "http://api.zuora.com/") do
829
690
  xml['SOAP-ENV'].Header do
830
691
  xml['ns1'].SessionHeader do
831
- xml['ns1'].session self.current_session
692
+ xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
832
693
  end
833
694
  end
834
695
  xml['SOAP-ENV'].Body do
@@ -840,39 +701,21 @@ module ZuoraAPI
840
701
  end
841
702
  result = 'Waiting'
842
703
 
843
- start_time = Time.now
844
- error_type = ""
845
-
846
704
  while result != "Completed"
847
705
  sleep 3
848
- begin
849
- response_query = HTTParty.post(self.url, body: confirmRequest.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8"}, :timeout => 120)
850
- rescue => e
851
- error_type = "#{e.class}"
852
- end
706
+ response_query = HTTParty.post(self.url, body: confirmRequest.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8"}, :timeout => 120)
707
+
853
708
  output_xml = Nokogiri::XML(response_query.body)
854
709
  result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
855
710
  status_code = response_query.code if response_query
856
711
  raise "Export Creation Unsuccessful : #{output_xml.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text}" if result.blank? || result == "Failed"
857
712
  end
858
713
 
859
- begin
860
- end_time = Time.now
861
- response_time = end_time - start_time
862
- status_code = response.code if response
863
- endpoint_name = url.present? ? URI(url).host : url
864
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
865
- rescue => ex
866
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
867
- end
868
-
869
-
870
-
871
714
  file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
872
- Rails.logger.info('Export') {'=====> Export finished'}
715
+ Rails.logger.debug('=====> Export finished')
873
716
  export_file = get_file(:url => self.fileURL(file_id))
874
717
  export_file_path = export_file.path
875
- Rails.logger.info('Export') {"=====> Export path #{export_file.path}"}
718
+ Rails.logger.debug("=====> Export path #{export_file.path}")
876
719
 
877
720
  if extract && zip
878
721
  require "zip"
@@ -888,7 +731,7 @@ module ZuoraAPI
888
731
  end
889
732
 
890
733
  def query(query, parse = false)
891
- Rails.logger.debug('query') {"Querying Zuora for #{query}"}
734
+ Rails.logger.debug("Querying Zuora for #{query}")
892
735
  output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
893
736
  xml['ns1'].query do
894
737
  xml['ns1'].queryString query
@@ -904,35 +747,17 @@ module ZuoraAPI
904
747
  end
905
748
 
906
749
  def createJournalRun(call)
907
- error_type = ""
908
- start_time = Time.now
909
-
910
750
  url = rest_endpoint("/journal-runs")
911
751
  uri = URI(url)
912
752
  req = Net::HTTP::Post.new(uri,initheader = {'Content-Type' =>'application/json'})
913
- req.basic_auth self.username, self.password
753
+ req["Authorization"] = self.get_session(prefix: true)
914
754
  req.body = call
915
755
 
916
- begin
917
- response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
918
- http.request req
919
- end
920
- rescue => e
921
- error_type = "#{e.class}"
922
- ensure
923
- begin
924
- end_time = Time.now
925
- response_time = end_time - start_time
926
- status_code = response.code if response
927
- endpoint_name = url.present? ? URI(url).host : url
928
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
929
- rescue => ex
930
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
931
- end
756
+ response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
757
+ http.request req
932
758
  end
933
-
934
- Rails.logger.debug('Journal Run') {"Response #{response.code} #{response.message}:
935
- #{response.body}"}
759
+
760
+ Rails.logger.debug("Response #{response.code} #{response.message}: #{response.body}")
936
761
 
937
762
  result = JSON.parse(response.body)
938
763
  if result["success"]
@@ -940,44 +765,24 @@ module ZuoraAPI
940
765
  return jrNumber
941
766
  else
942
767
  message = result["reasons"][0]["message"]
943
- Rails.logger.debug('Journal Run') {"Journal Run failed with message #{message}"}
768
+ Rails.logger.error("Journal Run failed with message #{message}")
944
769
  return result
945
770
  end
946
771
 
947
772
  end
948
773
 
949
774
  def checkJRStatus(jrNumber)
950
- error_type = ""
951
-
952
- Rails.logger.info('Journal Run') {"Check for completion"}
953
-
954
- start_time = Time.now
955
-
775
+ Rails.logger.info("Check for completion")
956
776
  url = rest_endpoint("/journal-runs/#{jrNumber}")
957
777
  uri = URI(url)
958
778
  req = Net::HTTP::Get.new(uri,initheader = {'Content-Type' =>'application/json'})
959
- req.basic_auth self.username, self.password
779
+ req["Authorization"] = self.get_session(prefix: true)
960
780
 
961
- begin
962
- response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
963
- http.request req
964
- end
965
- rescue => e
966
- error_type = "#{e.class}"
967
- ensure
968
- begin
969
- end_time = Time.now
970
- response_time = end_time - start_time
971
- status_code = response.code if response
972
- endpoint_name = url.present? ? URI(url).host : url
973
- ::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET")
974
- rescue => ex
975
- Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
976
- end
781
+ response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
782
+ http.request req
977
783
  end
978
784
 
979
785
  result = JSON.parse(response.body)
980
-
981
786
  if result["success"]
982
787
  if !(result["status"].eql? "Completed")
983
788
  sleep(20.seconds)
@@ -985,7 +790,7 @@ module ZuoraAPI
985
790
  return result["status"]
986
791
  else
987
792
  message = result["reasons"][0]["message"]
988
- Rails.logger.info('Journal Run') {"Checking status of journal run failed with message #{message}"}
793
+ Rails.logger.info("Checking status of journal run failed with message #{message}")
989
794
  end
990
795
  return "failure"
991
796
  end
@@ -0,0 +1,103 @@
1
+ module ZuoraAPI
2
+ class Basic < Login
3
+ attr_accessor :username, :password
4
+ def initialize(username: nil, password: nil, **keyword_args)
5
+ @username = username
6
+ @password = password
7
+ super
8
+ end
9
+
10
+ def new_session(auth_type: :basic, debug: false)
11
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
12
+ tries ||= 2
13
+ request = Nokogiri::XML::Builder.new do |xml|
14
+ xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' =>"http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:api' => "http://api.zuora.com/" ) do
15
+ xml['SOAP-ENV'].Header
16
+ xml['SOAP-ENV'].Body do
17
+ xml['api'].login do
18
+ xml['api'].username self.username
19
+ xml['api'].password self.password
20
+ xml['api'].entityId self.entity_id if !self.entity_id.blank?
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
27
+ input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
28
+ Rails.logger.debug('Connect') {"Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
29
+
30
+ @response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => 10)
31
+ @output_xml = Nokogiri::XML(@response_query.body)
32
+ Rails.logger.debug('Connect') {"Response SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
33
+
34
+ if !@response_query.success?
35
+ self.current_session = nil
36
+ if @output_xml.namespaces.size > 0 && @output_xml.xpath('//soapenv:Fault').size > 0
37
+ self.current_error = @output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
38
+ if self.current_error.include?('deactivated')
39
+ self.status = 'Deactivated'
40
+ self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
41
+ self.errors[:username] = self.current_error
42
+ elsif self.current_error.include?('inactive')
43
+ self.status = 'Inactive'
44
+ self.current_error = 'Inactive user login, please check with Zuora tenant administrator'
45
+ self.errors[:username] = self.current_error
46
+ elsif self.current_error.include?("invalid username or password") || self.current_error.include?("Invalid login. User name and password do not match.")
47
+ self.status = 'Invalid Login'
48
+ self.current_error = 'Invalid login, please check username and password or URL endpoint'
49
+ self.errors[:username] = self.current_error
50
+ self.errors[:password] = self.current_error
51
+ elsif self.current_error.include?('unsupported version')
52
+ self.status = 'Unsupported API Version'
53
+ self.current_error = 'Unsupported API version, please verify URL endpoint'
54
+ self.errors[:url] = self.current_error
55
+ elsif self.current_error.include?('invalid api version')
56
+ self.status = 'Invalid API Version'
57
+ self.current_error = 'Invalid API version, please verify URL endpoint'
58
+ self.errors[:url] = self.current_error
59
+ elsif self.current_error.include?('invalid session')
60
+ self.status = 'Invalid Session'
61
+ self.current_error = 'Session invalid, please update session and verify URL endpoint'
62
+ self.errors[:session] = self.current_error
63
+ elsif self.current_error.include?('Your IP address')
64
+ self.status = 'Restricted IP'
65
+ self.current_error = 'IP restricted, contact Zuora tenant administrator and remove IP restriction'
66
+ self.errors[:base] = self.current_error
67
+ elsif self.current_error.include?('This account has been locked')
68
+ self.status = 'Locked'
69
+ self.current_error = 'Locked user login, please wait or navigate to Zuora to unlock user'
70
+ self.errors[:username] = self.current_error
71
+ else
72
+ self.status = 'Unknown'
73
+ self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
74
+ self.errors[:base] = self.current_error
75
+ end
76
+
77
+ else
78
+ self.status = 'Unknown'
79
+ self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
80
+ self.errors[:base] = self.current_error
81
+ end
82
+ else
83
+ #Username & password combo
84
+ if (self.password.present? && self.username.present?)
85
+ retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
86
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
87
+ self.current_session = retrieved_session
88
+ end
89
+ end
90
+ return self.status
91
+ rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
92
+ if !(tries -= 1).zero?
93
+ Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
94
+ sleep(self.timeout_sleep)
95
+ retry
96
+ else
97
+ self.current_error = "Request timed out. Try again"
98
+ self.status = 'Timeout'
99
+ return self.status
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,106 @@
1
+ module ZuoraAPI
2
+ class Oauth < Login
3
+ attr_accessor :oauth_client_id, :oauth_secret, :bearer_token, :oauth_session_expires_at
4
+
5
+ def initialize(oauth_client_id: nil, oauth_secret: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args)
6
+ self.oauth_client_id = oauth_client_id
7
+ self.oauth_secret = oauth_secret
8
+ self.bearer_token = bearer_token if !bearer_token.blank?
9
+ self.oauth_session_expires_at = oauth_session_expires_at if !oauth_session_expires_at.blank?
10
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if @oauth_client_id.blank? || @oauth_secret.blank?
11
+ super
12
+ end
13
+
14
+ def new_session(auth_type: nil)
15
+ if auth_type == :bearer
16
+ get_bearer_token()
17
+ elsif auth_type == :basic
18
+ get_bearer_token() if self.oauth_expired?
19
+ get_z_session()
20
+ else
21
+ get_bearer_token()
22
+ get_z_session()
23
+ end
24
+ return self.status
25
+ end
26
+
27
+ def get_z_session(debug: false)
28
+ tries ||= 2
29
+ headers = self.entity_id.present? ? {:entityId => self.entity_id } : {}
30
+ output_json, response = self.rest_call(:url => self.rest_endpoint("connections"), :session_type => :bearer, :headers => headers)
31
+ self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=')
32
+ rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
33
+ if !(tries -= 1).zero?
34
+ Rails.logger.debug {"Session Invalid"}
35
+ self.new_session(auth_type: :bearer)
36
+ retry
37
+ else
38
+ if errors.include?(ex.class)
39
+ raise ex
40
+ else
41
+ return [output_json, response]
42
+ end
43
+ end
44
+ rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
45
+ if errors.include?(ex.class)
46
+ raise ex
47
+ else
48
+ return [output_json, response]
49
+ end
50
+ rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
51
+ if !(tries -= 1).zero?
52
+ Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
53
+ sleep(self.timeout_sleep)
54
+ retry
55
+ else
56
+ self.current_error = "Request timed out. Try again"
57
+ self.status = 'Timeout'
58
+ return self.status
59
+ end
60
+ end
61
+
62
+ def get_bearer_token
63
+ tries ||= 2
64
+ output_json, response = self.rest_call(:method => :post,
65
+ :url => self.rest_endpoint.chomp('v1/').concat("oauth/token"),
66
+ :z_session => false,
67
+ :session_type => :bearer,
68
+ :headers => {"content_type" => "application/x-www-form-urlencoded"},
69
+ :body => {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"}
70
+ )
71
+
72
+ self.bearer_token = output_json["access_token"]
73
+ self.oauth_session_expires_at = Time.now.to_i + output_json["expires_in"].to_i
74
+ self.current_error = nil
75
+ self.status = 'Active'
76
+
77
+ return self.status
78
+ rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
79
+ self.bearer_token = nil
80
+ self.oauth_session_expires_at = nil
81
+ self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
82
+ self.status = 'Invalid Login'
83
+ return self.status
84
+ rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
85
+ if errors.include?(ex.class)
86
+ raise ex
87
+ else
88
+ return [output_json, response]
89
+ end
90
+ rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
91
+ if !(tries -= 1).zero?
92
+ Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
93
+ sleep(self.timeout_sleep)
94
+ retry
95
+ else
96
+ self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
97
+ self.status = 'Timeout'
98
+ return self.status
99
+ end
100
+ end
101
+
102
+ def oauth_expired?
103
+ return (self.oauth_session_expires_at.blank? || self.bearer_token.blank?) ? true : (self.oauth_session_expires_at.to_i < Time.now.to_i)
104
+ end
105
+ end
106
+ end
@@ -1,3 +1,3 @@
1
1
  module ZuoraAPI
2
- VERSION = "1.5.2"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -26,5 +26,5 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency("nokogiri")
27
27
  spec.add_dependency("httparty")
28
28
  spec.add_dependency("rubyzip")
29
- spec.add_dependency("railties", ">= 4.1.0", "< 5.1")
29
+ spec.add_dependency("railties", ">= 4.1.0", "< 5.2")
30
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zuora_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zuora Strategic Solutions Group
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-29 00:00:00.000000000 Z
11
+ date: 2018-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: 4.1.0
132
132
  - - "<"
133
133
  - !ruby/object:Gem::Version
134
- version: '5.1'
134
+ version: '5.2'
135
135
  type: :runtime
136
136
  prerelease: false
137
137
  version_requirements: !ruby/object:Gem::Requirement
@@ -141,7 +141,7 @@ dependencies:
141
141
  version: 4.1.0
142
142
  - - "<"
143
143
  - !ruby/object:Gem::Version
144
- version: '5.1'
144
+ version: '5.2'
145
145
  description: Gem that provides easy integration to Zuora
146
146
  email:
147
147
  - connect@zuora.com
@@ -163,7 +163,8 @@ files:
163
163
  - lib/zuora_api.rb
164
164
  - lib/zuora_api/exceptions.rb
165
165
  - lib/zuora_api/login.rb
166
- - lib/zuora_api/metrics_helper.rb
166
+ - lib/zuora_api/logins/basic.rb
167
+ - lib/zuora_api/logins/oauth.rb
167
168
  - lib/zuora_api/version.rb
168
169
  - zuora_api.gemspec
169
170
  homepage: https://connect.zuora.com
@@ -1,12 +0,0 @@
1
- module MetricsHelpers
2
-
3
- class MetricsHelpers
4
- def self.write_to_telegraf(response_time: nil, status_code: nil, endpoint_name: nil, direction: nil, error_type: nil, function_name: nil, method_name: nil)
5
- if Gem.loaded_specs.has_key?('zuora_connect') && defined?(::ZuoraConnect::AppInstance.write_to_telegraf)
6
- Thread.current[:appinstance].present? ? app_instance = Thread.current[:appinstance].id : app_instance = 0
7
- ZuoraConnect::AppInstanceBase.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "app_instance": app_instance, "function_name": function_name, "method_name": method_name)
8
- end
9
- end
10
- end
11
-
12
- end