zuora_api 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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