zuora_api 1.7.66l → 1.8.2
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 +4 -4
- data/.gitlab-ci.yml +16 -17
- data/Gemfile +1 -1
- data/gemfiles/Gemfile-rails.5.0.x +5 -0
- data/gemfiles/Gemfile-rails.5.1.x +5 -0
- data/gemfiles/Gemfile-rails.5.2.x +5 -0
- data/gemfiles/Gemfile-rails.6.0.x +5 -0
- data/lib/zuora_api/exceptions.rb +2 -16
- data/lib/zuora_api/login.rb +232 -364
- data/lib/zuora_api/logins/basic.rb +101 -10
- data/lib/zuora_api/logins/oauth.rb +84 -24
- data/lib/zuora_api/version.rb +1 -1
- data/zuora_api.gemspec +3 -4
- metadata +16 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20af4f6a1a2d5f135800a45899d3ba43b2de122167125289566db95d2ba436fb
|
|
4
|
+
data.tar.gz: 5eb24a5103ae70624155431cbf897f36c1ccb82c4b089220132ec16fe816da2b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0742d058bdf5b53dae3273c4d5d6c9c45a5644b47bc71445cf50c59d0bd2bf33007536a7bdeac8ddd27b4a62119ef83e590f50efb157a982c0ce8d7567222443
|
|
7
|
+
data.tar.gz: 6ced43d141d096b80cad77c641c171e6088af0f4ac2254021b2a61e086708a13bc77a6f2ce043cb9d94d72a72987edc7986ed7301ed6f4e7a8a33161714565cc
|
data/.gitlab-ci.yml
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
|
-
image: ruby:2.
|
|
1
|
+
image: ruby:2.6
|
|
2
2
|
stages:
|
|
3
|
-
- setup
|
|
4
3
|
- test
|
|
5
4
|
- deploy
|
|
6
5
|
|
|
7
|
-
setup:
|
|
8
|
-
stage: setup
|
|
9
|
-
allow_failure: true
|
|
10
|
-
cache:
|
|
11
|
-
key: gems
|
|
12
|
-
paths:
|
|
13
|
-
- vendor/bundle
|
|
14
|
-
script:
|
|
15
|
-
- apt-get update -qy
|
|
16
|
-
- apt-get install -y nodejs
|
|
17
|
-
- bundle install
|
|
18
|
-
|
|
19
6
|
rubocop-testing:
|
|
20
7
|
stage: test
|
|
21
8
|
allow_failure: true
|
|
@@ -30,11 +17,23 @@ security-testing:
|
|
|
30
17
|
- gem install brakeman
|
|
31
18
|
- brakeman
|
|
32
19
|
|
|
33
|
-
|
|
20
|
+
ruby:test:
|
|
34
21
|
stage: test
|
|
22
|
+
cache:
|
|
23
|
+
key: ruby:$RUBY_VERSION-rails:$RAILS_VERSION
|
|
24
|
+
paths:
|
|
25
|
+
- vendor/ruby
|
|
26
|
+
parallel:
|
|
27
|
+
matrix:
|
|
28
|
+
- RUBY_VERSION: "2.7"
|
|
29
|
+
RAILS_VERSION: ["5.0", "5.1", "5.2", "6.0"]
|
|
30
|
+
before_script:
|
|
31
|
+
- bundle config set path 'vendor/ruby'
|
|
32
|
+
- bundle config --global gemfile "gemfiles/Gemfile-rails.$RAILS_VERSION.x"
|
|
33
|
+
- bundle install
|
|
35
34
|
script:
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
- bundle exec rails -v
|
|
36
|
+
- bundle exec rspec
|
|
38
37
|
coverage: '/\(\d+.\d+\%\) covered/'
|
|
39
38
|
|
|
40
39
|
rubygems-deploy:
|
data/Gemfile
CHANGED
data/lib/zuora_api/exceptions.rb
CHANGED
|
@@ -40,19 +40,6 @@ module ZuoraAPI
|
|
|
40
40
|
def to_s
|
|
41
41
|
@message || @default_message
|
|
42
42
|
end
|
|
43
|
-
|
|
44
|
-
def parse_message(message)
|
|
45
|
-
case message
|
|
46
|
-
when /^Invalid Oauth Client Id$/, /^Unable to generate token.$/
|
|
47
|
-
@message = "Invalid login, please check client ID and Client Secret or URL endpoint"
|
|
48
|
-
when /^Forbidden$/
|
|
49
|
-
@message = "The user associated to OAuth credential set has been deactivated."
|
|
50
|
-
when /^Invalid login. User name and password do not match.$/
|
|
51
|
-
@message = "Invalid login, please check username and password or URL endpoint"
|
|
52
|
-
else
|
|
53
|
-
@message = message
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
43
|
end
|
|
57
44
|
|
|
58
45
|
class BadEntityError < Error
|
|
@@ -190,15 +177,14 @@ module ZuoraAPI
|
|
|
190
177
|
end
|
|
191
178
|
|
|
192
179
|
class ZuoraAPITemporaryError < Error
|
|
193
|
-
attr_reader :code, :response
|
|
180
|
+
attr_reader :code, :response
|
|
194
181
|
attr_writer :default_message
|
|
195
182
|
|
|
196
|
-
def initialize(message = nil,
|
|
183
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
197
184
|
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
198
185
|
@message = parse_message(message)
|
|
199
186
|
@response = response
|
|
200
187
|
@default_message = "There is a temporary error with zuora system."
|
|
201
|
-
@errors = errors
|
|
202
188
|
end
|
|
203
189
|
|
|
204
190
|
def to_s
|
data/lib/zuora_api/login.rb
CHANGED
|
@@ -39,8 +39,8 @@ module ZuoraAPI
|
|
|
39
39
|
|
|
40
40
|
ZUORA_SERVER_ERRORS = [
|
|
41
41
|
ZuoraAPI::Exceptions::ZuoraAPIInternalServerError,
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout,
|
|
43
|
+
ZuoraAPI::Exceptions::ZuoraAPIReadTimeout,
|
|
44
44
|
ZuoraAPI::Exceptions::ZuoraUnexpectedError
|
|
45
45
|
].freeze
|
|
46
46
|
|
|
@@ -72,29 +72,12 @@ module ZuoraAPI
|
|
|
72
72
|
|
|
73
73
|
def get_identity(cookies)
|
|
74
74
|
zsession = cookies["ZSession"]
|
|
75
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
76
75
|
begin
|
|
77
76
|
if !zsession.blank?
|
|
78
77
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
79
78
|
output_json = JSON.parse(response.body)
|
|
80
|
-
elsif zconnect_accesstoken.present?
|
|
81
|
-
begin
|
|
82
|
-
code = zconnect_accesstoken.split("#!").last
|
|
83
|
-
encrypted_token, tenant_id = Base64.decode64(code).split(":")
|
|
84
|
-
body = {'token' => encrypted_token}.to_json
|
|
85
|
-
rescue => ex
|
|
86
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie")
|
|
87
|
-
end
|
|
88
|
-
Rails.logger.info("Using ZConnect cookie in get_identity method")
|
|
89
|
-
|
|
90
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
|
|
91
|
-
output_json = JSON.parse(response.body)
|
|
92
79
|
else
|
|
93
|
-
|
|
94
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
95
|
-
else
|
|
96
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
97
|
-
end
|
|
80
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
98
81
|
end
|
|
99
82
|
rescue JSON::ParserError => ex
|
|
100
83
|
output_json = {}
|
|
@@ -105,21 +88,12 @@ module ZuoraAPI
|
|
|
105
88
|
|
|
106
89
|
def get_full_nav(cookies)
|
|
107
90
|
zsession = cookies["ZSession"]
|
|
108
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
109
91
|
begin
|
|
110
92
|
if zsession.present?
|
|
111
93
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
112
94
|
output_json = JSON.parse(response.body)
|
|
113
|
-
elsif zconnect_accesstoken.present?
|
|
114
|
-
Rails.logger.info("Using ZConnect cookie in get_full_nav method")
|
|
115
|
-
response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
|
|
116
|
-
output_json = JSON.parse(response.body)
|
|
117
95
|
else
|
|
118
|
-
|
|
119
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
120
|
-
else
|
|
121
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
122
|
-
end
|
|
96
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
123
97
|
end
|
|
124
98
|
rescue JSON::ParserError => ex
|
|
125
99
|
output_json = {}
|
|
@@ -130,21 +104,12 @@ module ZuoraAPI
|
|
|
130
104
|
|
|
131
105
|
def set_nav(state, cookies)
|
|
132
106
|
zsession = cookies["ZSession"]
|
|
133
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
134
107
|
begin
|
|
135
108
|
if !zsession.blank?
|
|
136
109
|
response = HTTParty.put("https://#{self.hostname}/apps/v1/preference/navigation", :body => state.to_json, :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
137
110
|
output_json = JSON.parse(response.body)
|
|
138
|
-
elsif !zconnect_accesstoken.blank?
|
|
139
|
-
Rails.logger.info("Using ZConnect cookie in set_nav method")
|
|
140
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/navigationstate", :body => state.to_json, :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
|
141
|
-
output_json = JSON.parse(response.body)
|
|
142
111
|
else
|
|
143
|
-
|
|
144
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
145
|
-
else
|
|
146
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
147
|
-
end
|
|
112
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
148
113
|
end
|
|
149
114
|
rescue JSON::ParserError => ex
|
|
150
115
|
output_json = {}
|
|
@@ -155,21 +120,12 @@ module ZuoraAPI
|
|
|
155
120
|
|
|
156
121
|
def refresh_nav(cookies)
|
|
157
122
|
zsession = cookies["ZSession"]
|
|
158
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
159
123
|
begin
|
|
160
124
|
if !zsession.blank?
|
|
161
125
|
response = HTTParty.post("https://#{self.hostname}/apps/v1/navigation/fetch", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
162
126
|
output_json = JSON.parse(response.body)
|
|
163
|
-
elsif !zconnect_accesstoken.blank?
|
|
164
|
-
Rails.logger.info("Using ZConnect cookie in refresh_nav method")
|
|
165
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/refresh-navbarcache", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
|
166
|
-
output_json = JSON.parse(response.body)
|
|
167
127
|
else
|
|
168
|
-
|
|
169
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
170
|
-
else
|
|
171
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
172
|
-
end
|
|
128
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
173
129
|
end
|
|
174
130
|
rescue JSON::ParserError => ex
|
|
175
131
|
output_json = {}
|
|
@@ -178,15 +134,6 @@ module ZuoraAPI
|
|
|
178
134
|
return output_json
|
|
179
135
|
end
|
|
180
136
|
|
|
181
|
-
def get_zconnect_accesstoken(cookies)
|
|
182
|
-
accesstoken = nil
|
|
183
|
-
self.update_zconnect_provider
|
|
184
|
-
if !cookies[self.zconnect_provider].nil? && !cookies[self.zconnect_provider].empty?
|
|
185
|
-
accesstoken = cookies[self.zconnect_provider]
|
|
186
|
-
end
|
|
187
|
-
return accesstoken
|
|
188
|
-
end
|
|
189
|
-
|
|
190
137
|
def reporting_url(path)
|
|
191
138
|
map = {"US" => {"Sandbox" => "https://zconnectsandbox.zuora.com/api/rest/v1/",
|
|
192
139
|
"Production" => "https://zconnect.zuora.com/api/rest/v1/",
|
|
@@ -208,7 +155,7 @@ module ZuoraAPI
|
|
|
208
155
|
# 1. Pass in cookies and optionally custom_authorities, name, and description
|
|
209
156
|
# 2. Pass in user_id, entity_ids, client_id, client_secret, and optionally custom_authorities, name, and description
|
|
210
157
|
# https://intranet.zuora.com/confluence/display/Sunburst/Create+an+OAuth+Client+through+API+Gateway#CreateanOAuthClientthroughAPIGateway-ZSession
|
|
211
|
-
def get_oauth_client (custom_authorities = [], info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, new_client_id: nil, new_client_secret: nil, cookies: nil)
|
|
158
|
+
def get_oauth_client (custom_authorities = [], info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, new_client_id: nil, new_client_secret: nil, cookies: nil, chomp_v1_from_genesis_endpoint: false, use_api_generated_client_secret: false)
|
|
212
159
|
authorization = ""
|
|
213
160
|
new_client_id = SecureRandom.uuid if new_client_id.blank?
|
|
214
161
|
new_client_secret = SecureRandom.hex(10) if new_client_secret.blank?
|
|
@@ -234,11 +181,11 @@ module ZuoraAPI
|
|
|
234
181
|
end
|
|
235
182
|
|
|
236
183
|
if !authorization.blank? && !user_id.blank? && !entity_ids.blank?
|
|
237
|
-
endpoint = self.rest_endpoint("genesis/clients")
|
|
184
|
+
endpoint = chomp_v1_from_genesis_endpoint ? self.rest_endpoint.chomp("v1/").concat("genesis/clients") : self.rest_endpoint("genesis/clients")
|
|
238
185
|
oauth_response = HTTParty.post(endpoint, :headers => {'authorization' => authorization, 'Content-Type' => 'application/json'}, :body => {'clientId' => new_client_id, 'clientSecret' => new_client_secret, 'userId' => user_id, 'entityIds' => entity_ids, 'customAuthorities' => custom_authorities, 'additionalInformation' => {'description' => info_desc, 'name' => info_name}}.to_json)
|
|
239
186
|
output_json = JSON.parse(oauth_response.body)
|
|
240
187
|
if oauth_response.code == 201
|
|
241
|
-
output_json["clientSecret"] = new_client_secret
|
|
188
|
+
output_json["clientSecret"] = new_client_secret if !use_api_generated_client_secret
|
|
242
189
|
return output_json
|
|
243
190
|
elsif oauth_response.code == 401 && !oauth_response.message.blank?
|
|
244
191
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], oauth_response)
|
|
@@ -374,8 +321,8 @@ module ZuoraAPI
|
|
|
374
321
|
return domain ? endpoint.concat(prefix).concat(url) : prefix.concat(url)
|
|
375
322
|
end
|
|
376
323
|
|
|
377
|
-
def rest_domain
|
|
378
|
-
return URI(
|
|
324
|
+
def rest_domain
|
|
325
|
+
return URI(self.rest_endpoint).host
|
|
379
326
|
end
|
|
380
327
|
|
|
381
328
|
def fileURL(url="")
|
|
@@ -387,41 +334,10 @@ module ZuoraAPI
|
|
|
387
334
|
end
|
|
388
335
|
|
|
389
336
|
def new_session(auth_type: :basic, debug: false, zuora_track_id: nil)
|
|
390
|
-
tries ||= 2
|
|
391
|
-
yield
|
|
392
|
-
|
|
393
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
394
|
-
self.status = 'Inactive/Invalid'
|
|
395
|
-
self.current_error = ex.message
|
|
396
|
-
raise
|
|
397
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIError => ex
|
|
398
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(ex.message, ex.response)
|
|
399
|
-
|
|
400
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex
|
|
401
|
-
raise ex if tries.zero?
|
|
402
|
-
|
|
403
|
-
tries -= 1
|
|
404
|
-
sleep(self.timeout_sleep)
|
|
405
|
-
retry
|
|
406
|
-
|
|
407
|
-
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
408
|
-
self.log(location: "BasicLogin", exception: ex, message: "Timed out", level: :error)
|
|
409
|
-
|
|
410
|
-
self.current_error = "Request timed out. Try again"
|
|
411
|
-
self.status = 'Timeout'
|
|
412
|
-
|
|
413
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
414
|
-
|
|
415
|
-
rescue EOFError
|
|
416
|
-
if self.url.match?(/.*services\d{1,}.zuora.com*/)
|
|
417
|
-
self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available."
|
|
418
|
-
self.status = 'Not Available'
|
|
419
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
420
|
-
end
|
|
421
|
-
|
|
422
337
|
end
|
|
423
338
|
|
|
424
339
|
def get_session(prefix: false, auth_type: :basic, zuora_track_id: nil)
|
|
340
|
+
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}") if Rails.env.to_s == 'development'
|
|
425
341
|
case auth_type
|
|
426
342
|
when :basic
|
|
427
343
|
if self.current_session.blank?
|
|
@@ -430,13 +346,14 @@ module ZuoraAPI
|
|
|
430
346
|
if self.bearer_token.blank? || self.oauth_expired?
|
|
431
347
|
self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id)
|
|
432
348
|
end
|
|
433
|
-
self.get_z_session(zuora_track_id: zuora_track_id)
|
|
349
|
+
self.get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
|
|
434
350
|
when 'ZuoraAPI::Basic'
|
|
435
351
|
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
436
352
|
else
|
|
437
353
|
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
438
354
|
end
|
|
439
355
|
end
|
|
356
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
|
440
357
|
return prefix ? "ZSession #{self.current_session}" : self.current_session.to_s
|
|
441
358
|
when :bearer
|
|
442
359
|
case self.class.to_s
|
|
@@ -449,6 +366,8 @@ module ZuoraAPI
|
|
|
449
366
|
else
|
|
450
367
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Unknown Login, does not support Authentication of Type: #{auth_type}")
|
|
451
368
|
end
|
|
369
|
+
|
|
370
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
|
452
371
|
return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
|
|
453
372
|
end
|
|
454
373
|
end
|
|
@@ -456,18 +375,16 @@ module ZuoraAPI
|
|
|
456
375
|
def soap_call(
|
|
457
376
|
ns1: 'ns1',
|
|
458
377
|
ns2: 'ns2',
|
|
459
|
-
batch_size: nil,
|
|
460
|
-
headers: {},
|
|
378
|
+
batch_size: nil,
|
|
461
379
|
single_transaction: false,
|
|
462
380
|
debug: false,
|
|
463
381
|
zuora_track_id: nil,
|
|
464
382
|
errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
|
|
465
383
|
z_session: true,
|
|
466
384
|
timeout_retry: false,
|
|
467
|
-
timeout:
|
|
385
|
+
timeout: 120,
|
|
468
386
|
timeout_sleep_interval: self.timeout_sleep,
|
|
469
387
|
output_exception_messages: true,
|
|
470
|
-
skip_session: false,
|
|
471
388
|
**keyword_args)
|
|
472
389
|
tries ||= 2
|
|
473
390
|
xml = Nokogiri::XML::Builder.new do |xml|
|
|
@@ -477,10 +394,8 @@ module ZuoraAPI
|
|
|
477
394
|
'xmlns:api' => "http://api.zuora.com/",
|
|
478
395
|
"xmlns:#{ns1}" => "http://api.zuora.com/") do
|
|
479
396
|
xml['SOAP-ENV'].Header do
|
|
480
|
-
|
|
481
|
-
xml["#{ns1}"].
|
|
482
|
-
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
483
|
-
end
|
|
397
|
+
xml["#{ns1}"].SessionHeader do
|
|
398
|
+
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
484
399
|
end
|
|
485
400
|
if single_transaction
|
|
486
401
|
xml["#{ns1}"].CallOptions do
|
|
@@ -498,11 +413,12 @@ module ZuoraAPI
|
|
|
498
413
|
end
|
|
499
414
|
end
|
|
500
415
|
end
|
|
416
|
+
|
|
501
417
|
input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
|
502
418
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
|
503
419
|
Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
504
420
|
|
|
505
|
-
headers
|
|
421
|
+
headers = { 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'}
|
|
506
422
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
507
423
|
|
|
508
424
|
request = HTTParty::Request.new(
|
|
@@ -519,11 +435,7 @@ module ZuoraAPI
|
|
|
519
435
|
Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
520
436
|
|
|
521
437
|
raise_errors(type: :SOAP, body: output_xml, response: response)
|
|
522
|
-
|
|
523
|
-
return output_xml, input_xml, response
|
|
524
|
-
|
|
525
438
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
526
|
-
raise if skip_session
|
|
527
439
|
if !tries.zero? && z_session
|
|
528
440
|
tries -= 1
|
|
529
441
|
Rails.logger.debug("SOAP Call - Session Invalid")
|
|
@@ -535,33 +447,39 @@ module ZuoraAPI
|
|
|
535
447
|
end
|
|
536
448
|
|
|
537
449
|
retry
|
|
450
|
+
else
|
|
451
|
+
if errors.include?(ex.class)
|
|
452
|
+
raise ex
|
|
453
|
+
else
|
|
454
|
+
return output_xml, input_xml, response
|
|
455
|
+
end
|
|
538
456
|
end
|
|
539
|
-
|
|
540
|
-
raise ex if errors.include?(ex.class)
|
|
541
|
-
|
|
542
|
-
return output_xml, input_xml, response
|
|
543
|
-
|
|
544
457
|
rescue *ZUORA_API_ERRORS => ex
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
458
|
+
if errors.include?(ex.class)
|
|
459
|
+
raise ex
|
|
460
|
+
else
|
|
461
|
+
response = ex.response unless response
|
|
462
|
+
return output_xml, input_xml, response
|
|
463
|
+
end
|
|
550
464
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
551
|
-
if
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
465
|
+
if tries.zero?
|
|
466
|
+
if output_exception_messages
|
|
467
|
+
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
468
|
+
Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
469
|
+
else
|
|
470
|
+
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
raise ex
|
|
556
474
|
end
|
|
557
475
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
476
|
+
tries -= 1
|
|
477
|
+
sleep(timeout_sleep_interval)
|
|
478
|
+
retry
|
|
561
479
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
562
480
|
if !tries.zero?
|
|
563
481
|
tries -= 1
|
|
564
|
-
|
|
482
|
+
|
|
565
483
|
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
566
484
|
retry
|
|
567
485
|
elsif timeout_retry
|
|
@@ -570,79 +488,19 @@ module ZuoraAPI
|
|
|
570
488
|
end
|
|
571
489
|
end
|
|
572
490
|
|
|
573
|
-
|
|
574
|
-
|
|
491
|
+
if output_exception_messages
|
|
492
|
+
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
493
|
+
Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
494
|
+
else
|
|
495
|
+
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
575
499
|
raise ex
|
|
576
|
-
|
|
577
500
|
rescue => ex
|
|
578
501
|
raise ex
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
end
|
|
582
|
-
|
|
583
|
-
def error_logger(ex)
|
|
584
|
-
exception_args = Rails.logger.with_fields.merge(self.exception_args(ex))
|
|
585
|
-
case ex
|
|
586
|
-
when ZuoraAPI::Exceptions::ZuoraAPIUnkownError, ZuoraAPI::Exceptions::ZuoraDataIntegrity
|
|
587
|
-
Rails.logger.error('Zuora Unknown/Integrity Error', ex, exception_args)
|
|
588
|
-
when ZuoraAPI::Exceptions::ZuoraAPIRequestLimit
|
|
589
|
-
Rails.logger.info('Zuora APILimit Reached', exception_args)
|
|
590
|
-
when *(ZuoraAPI::Login::ZUORA_API_ERRORS-ZuoraAPI::Login::ZUORA_SERVER_ERRORS)
|
|
591
|
-
#Rails.logger.debug('Zuora API Error', ex, self.exception_args(ex))
|
|
592
|
-
when *ZuoraAPI::Login::ZUORA_SERVER_ERRORS
|
|
593
|
-
Rails.logger.error('Zuora Server Error', ex, exception_args)
|
|
594
|
-
end
|
|
595
|
-
end
|
|
596
|
-
|
|
597
|
-
def log(location: "Rest Call", exception: nil, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :info )
|
|
598
|
-
level = :debug if ![:debug, :info, :warn, :error, :fatal].include?(level)
|
|
599
|
-
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
600
|
-
Rails.logger.send(level.to_sym, "#{location} - #{message}", exception)
|
|
601
|
-
else
|
|
602
|
-
Rails.logger.send(level.to_sym, "#{location} - #{exception.class} #{message}")
|
|
603
|
-
end
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
def exception_args(ex)
|
|
607
|
-
args = {}
|
|
608
|
-
if ex.class == ZuoraAPI::Exceptions::ZuoraAPIRequestLimit
|
|
609
|
-
args.merge!({
|
|
610
|
-
zuora_trace_id: ex.response.headers["zuora-request-id"],
|
|
611
|
-
zuora_track_id: ex.response.request.options[:headers]["Zuora-Track-Id"]
|
|
612
|
-
})
|
|
613
|
-
elsif defined?(ex.response) && ex.response.present?
|
|
614
|
-
args.merge!({
|
|
615
|
-
request: {
|
|
616
|
-
path: ex.response.request.path.to_s,
|
|
617
|
-
method: ex.response.request.http_method.to_s.split("Net::HTTP::").last.upcase,
|
|
618
|
-
params: ex.response.request.raw_body.to_s,
|
|
619
|
-
headers: ex.response.request.options[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h.to_s,
|
|
620
|
-
},
|
|
621
|
-
response: {
|
|
622
|
-
status: ex.response.code,
|
|
623
|
-
params: ex.response.body.to_s,
|
|
624
|
-
headers: ex.response.headers.to_s,
|
|
625
|
-
},
|
|
626
|
-
zuora_trace_id: ex.response.headers["zuora-request-id"],
|
|
627
|
-
zuora_track_id: ex.response.request.options[:headers]["Zuora-Track-Id"],
|
|
628
|
-
})
|
|
629
|
-
elsif defined?(ex.request) && ex.request.present?
|
|
630
|
-
args.merge!({
|
|
631
|
-
request: {
|
|
632
|
-
path: ex.request.path.to_s,
|
|
633
|
-
method: ex.request.http_method.to_s.split("Net::HTTP::").last.upcase,
|
|
634
|
-
params: ex.request.options[:body],
|
|
635
|
-
headers: ex.request.options[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h.to_s
|
|
636
|
-
}
|
|
637
|
-
})
|
|
638
|
-
args.merge!({
|
|
639
|
-
zuora_track_id: ex.request.options[:headers]["Zuora-Track-Id"]
|
|
640
|
-
}) if ex.request.options[:headers]["Zuora-Track-Id"].present?
|
|
641
|
-
end
|
|
642
|
-
rescue => ex
|
|
643
|
-
Rails.logger.error("Failed to create exception arguments", ex, args)
|
|
644
|
-
ensure
|
|
645
|
-
return args
|
|
502
|
+
else
|
|
503
|
+
return output_xml, input_xml, response
|
|
646
504
|
end
|
|
647
505
|
|
|
648
506
|
def raise_errors(type: :SOAP, body: nil, response: nil)
|
|
@@ -659,13 +517,13 @@ module ZuoraAPI
|
|
|
659
517
|
end
|
|
660
518
|
|
|
661
519
|
if [502,503].include?(response.code)
|
|
662
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from
|
|
520
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from #{request_uri}", response)
|
|
663
521
|
end
|
|
664
522
|
|
|
665
523
|
# Check failure response code
|
|
666
524
|
case response.code
|
|
667
525
|
when 504
|
|
668
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from
|
|
526
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{request_uri}", response)
|
|
669
527
|
when 429
|
|
670
528
|
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("The total number of concurrent requests has exceeded the limit allowed by the system. Please resubmit your request later.", response)
|
|
671
529
|
when 401
|
|
@@ -686,10 +544,6 @@ module ZuoraAPI
|
|
|
686
544
|
when :SOAP
|
|
687
545
|
error, success, message = get_soap_error_and_message(body)
|
|
688
546
|
|
|
689
|
-
if body.xpath('//fns:LoginFault', 'fns' =>'http://fault.api.zuora.com/').present?
|
|
690
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response)
|
|
691
|
-
end
|
|
692
|
-
|
|
693
547
|
if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
|
|
694
548
|
body.xpath(
|
|
695
549
|
'//ns1:records[@xsi:type="ns2:Export"]',
|
|
@@ -697,12 +551,12 @@ module ZuoraAPI
|
|
|
697
551
|
).present?
|
|
698
552
|
result = body.xpath('//ns2:Status', 'ns2' => 'http://object.api.zuora.com/').text
|
|
699
553
|
if result == 'Failed'
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
error, message = ['UNEXPECTED_ERROR', new_message] if new_message.present?
|
|
554
|
+
reason = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
|
|
555
|
+
if reason.present?
|
|
556
|
+
message = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
|
|
557
|
+
error = message.match(/^[\w\d]{16}\: (Unexpected error.|No HTTP Response|Socket Timeout|There is an internal error, please try again later)/).present? ? 'UNEXPECTED_ERROR' : 'FATAL_ERROR'
|
|
705
558
|
else
|
|
559
|
+
error = 'FATAL_ERROR'
|
|
706
560
|
message = 'Export failed due to unknown reason. Consult api logs.'
|
|
707
561
|
end
|
|
708
562
|
end
|
|
@@ -751,10 +605,6 @@ module ZuoraAPI
|
|
|
751
605
|
when /^GET::400::\/api\/rest\/v1\/reports\/(reportlabels\/)?([a-zA-Z0-9\-_]+)\/report-details$/ # Get report, capture of the id is present if needed in future error responses.
|
|
752
606
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
|
|
753
607
|
end
|
|
754
|
-
when /\/objects\/batch\//
|
|
755
|
-
if body['code'].present? && /61$/.match(body['code'].to_s).present? # if last 2 digits of code are 61
|
|
756
|
-
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body['message'], nil, body['details'])
|
|
757
|
-
end
|
|
758
608
|
end
|
|
759
609
|
|
|
760
610
|
body = body.dig("results").present? ? body["results"] : body if body.class == Hash
|
|
@@ -794,11 +644,7 @@ module ZuoraAPI
|
|
|
794
644
|
end
|
|
795
645
|
|
|
796
646
|
if body['error'] == 'Unauthorized' && body['status'] == 401
|
|
797
|
-
|
|
798
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(body['message'], response)
|
|
799
|
-
else
|
|
800
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
|
|
801
|
-
end
|
|
647
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
|
|
802
648
|
end
|
|
803
649
|
#Authentication failed
|
|
804
650
|
if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
|
|
@@ -925,8 +771,6 @@ module ZuoraAPI
|
|
|
925
771
|
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
|
|
926
772
|
when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
|
|
927
773
|
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
928
|
-
when /414 Request-URI Too Large/
|
|
929
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Request URL is too long", response)
|
|
930
774
|
else
|
|
931
775
|
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
932
776
|
end
|
|
@@ -996,7 +840,7 @@ module ZuoraAPI
|
|
|
996
840
|
raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
|
|
997
841
|
end
|
|
998
842
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
999
|
-
when
|
|
843
|
+
when /invalid/, /^DUPLICATE_VALUE/, /^REQUEST_REJECTED/, /INVALID_ID/, /MAX_RECORDS_EXCEEDED/, /INVALID_FIELD/, /MALFORMED_QUERY/, /NO_PERMISSION/, /PDF_QUERY_ERROR/, /MISSING_REQUIRED_VALUE/, /INVALID_TYPE/, /TRANSACTION_FAILED/, /API_DISABLED/, /CANNOT_DELETE/, /ACCOUNTING_PERIOD_CLOSED/
|
|
1000
844
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
1001
845
|
when /.*UNEXPECTED_ERROR/
|
|
1002
846
|
raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
|
|
@@ -1056,7 +900,7 @@ module ZuoraAPI
|
|
|
1056
900
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
|
1057
901
|
url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
|
|
1058
902
|
headers = self.entity_id.present? ? {"Zuora-Entity-Ids" => self.entity_id, 'Content-Type' => "text/xml; charset=utf-8"} : {'Content-Type' => "text/xml; charset=utf-8"}
|
|
1059
|
-
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout =>
|
|
903
|
+
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
|
|
1060
904
|
|
|
1061
905
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
|
|
1062
906
|
|
|
@@ -1089,31 +933,35 @@ module ZuoraAPI
|
|
|
1089
933
|
end
|
|
1090
934
|
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
|
|
1091
935
|
end
|
|
1092
|
-
|
|
1093
|
-
return des_hash
|
|
1094
936
|
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
1095
|
-
if
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
937
|
+
if tries.zero?
|
|
938
|
+
if log_errors
|
|
939
|
+
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
940
|
+
Rails.logger.error("Describe - Timed out will retry after #{self.timeout_sleep} seconds", ex)
|
|
941
|
+
else
|
|
942
|
+
Rails.logger.error("Describe - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
|
|
943
|
+
end
|
|
944
|
+
end
|
|
945
|
+
raise ex
|
|
1100
946
|
end
|
|
1101
947
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
948
|
+
tries -= 1
|
|
949
|
+
sleep(self.timeout_sleep)
|
|
950
|
+
retry
|
|
1105
951
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1106
952
|
if !tries.zero? && self.status == 'Active'
|
|
1107
953
|
tries -= 1
|
|
1108
954
|
Rails.logger.debug("Describe session expired. Starting new session.")
|
|
1109
955
|
self.new_session
|
|
1110
956
|
retry
|
|
957
|
+
else
|
|
958
|
+
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
959
|
+
raise ex
|
|
1111
960
|
end
|
|
1112
|
-
|
|
1113
|
-
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1114
|
-
raise ex
|
|
1115
961
|
rescue => ex
|
|
1116
962
|
raise ex
|
|
963
|
+
else
|
|
964
|
+
return des_hash
|
|
1117
965
|
end
|
|
1118
966
|
|
|
1119
967
|
def rest_call(
|
|
@@ -1126,12 +974,11 @@ module ZuoraAPI
|
|
|
1126
974
|
z_session: true,
|
|
1127
975
|
session_type: :basic,
|
|
1128
976
|
timeout_retry: false,
|
|
1129
|
-
timeout:
|
|
977
|
+
timeout: 120,
|
|
1130
978
|
timeout_sleep_interval: self.timeout_sleep,
|
|
1131
979
|
multipart: false,
|
|
1132
980
|
stream_body: false,
|
|
1133
981
|
output_exception_messages: true,
|
|
1134
|
-
zuora_track_id: nil,
|
|
1135
982
|
**keyword_args,
|
|
1136
983
|
&block
|
|
1137
984
|
)
|
|
@@ -1141,13 +988,12 @@ module ZuoraAPI
|
|
|
1141
988
|
|
|
1142
989
|
authentication_headers = {}
|
|
1143
990
|
if z_session
|
|
1144
|
-
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type
|
|
991
|
+
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type) }
|
|
1145
992
|
if self.entity_id.present?
|
|
1146
993
|
authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
|
1147
994
|
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
|
1148
995
|
end
|
|
1149
996
|
end
|
|
1150
|
-
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
1151
997
|
|
|
1152
998
|
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
|
1153
999
|
|
|
@@ -1173,20 +1019,18 @@ module ZuoraAPI
|
|
|
1173
1019
|
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
|
1174
1020
|
|
|
1175
1021
|
raise_errors(type: :JSON, body: output_json, response: response)
|
|
1176
|
-
rescue
|
|
1022
|
+
rescue
|
|
1177
1023
|
reset_files(body) if multipart
|
|
1178
1024
|
raise
|
|
1179
1025
|
end
|
|
1180
|
-
|
|
1181
|
-
return [output_json, response]
|
|
1182
1026
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
|
1183
1027
|
if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
|
|
1184
1028
|
session_type = :bearer
|
|
1185
1029
|
retry
|
|
1030
|
+
else
|
|
1031
|
+
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
|
1032
|
+
raise ex
|
|
1186
1033
|
end
|
|
1187
|
-
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
|
1188
|
-
raise ex
|
|
1189
|
-
|
|
1190
1034
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1191
1035
|
if !tries.zero? && z_session
|
|
1192
1036
|
tries -= 1
|
|
@@ -1199,35 +1043,40 @@ module ZuoraAPI
|
|
|
1199
1043
|
end
|
|
1200
1044
|
|
|
1201
1045
|
retry
|
|
1046
|
+
else
|
|
1047
|
+
if errors.include?(ex.class)
|
|
1048
|
+
raise ex
|
|
1049
|
+
else
|
|
1050
|
+
return [output_json, response]
|
|
1051
|
+
end
|
|
1202
1052
|
end
|
|
1203
|
-
|
|
1204
|
-
raise ex if errors.include?(ex.class)
|
|
1205
|
-
return [output_json, response]
|
|
1206
|
-
|
|
1207
1053
|
rescue *ZUORA_API_ERRORS => ex
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1054
|
+
if errors.include?(ex.class)
|
|
1055
|
+
raise ex
|
|
1056
|
+
else
|
|
1057
|
+
response = ex.response unless response
|
|
1058
|
+
return [output_json, response]
|
|
1059
|
+
end
|
|
1213
1060
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1214
1061
|
raise ex
|
|
1215
1062
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
1216
|
-
if
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1063
|
+
if tries.zero?
|
|
1064
|
+
if output_exception_messages
|
|
1065
|
+
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
1066
|
+
Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
1067
|
+
else
|
|
1068
|
+
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1069
|
+
end
|
|
1070
|
+
end
|
|
1071
|
+
raise ex
|
|
1221
1072
|
end
|
|
1222
1073
|
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1074
|
+
tries -= 1
|
|
1075
|
+
sleep(timeout_sleep_interval)
|
|
1076
|
+
retry
|
|
1226
1077
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
1227
|
-
|
|
1228
1078
|
if !tries.zero?
|
|
1229
1079
|
tries -= 1
|
|
1230
|
-
self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
1231
1080
|
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
1232
1081
|
retry
|
|
1233
1082
|
elsif timeout_retry
|
|
@@ -1235,15 +1084,20 @@ module ZuoraAPI
|
|
|
1235
1084
|
retry
|
|
1236
1085
|
end
|
|
1237
1086
|
end
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1087
|
+
|
|
1088
|
+
if output_exception_messages
|
|
1089
|
+
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
1090
|
+
Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
1091
|
+
else
|
|
1092
|
+
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1093
|
+
end
|
|
1094
|
+
end
|
|
1095
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
1241
1096
|
raise ex
|
|
1242
|
-
|
|
1243
1097
|
rescue => ex
|
|
1244
1098
|
raise ex
|
|
1245
|
-
|
|
1246
|
-
|
|
1099
|
+
else
|
|
1100
|
+
return [output_json, response]
|
|
1247
1101
|
end
|
|
1248
1102
|
|
|
1249
1103
|
def update_create_tenant
|
|
@@ -1265,9 +1119,8 @@ module ZuoraAPI
|
|
|
1265
1119
|
while !response["nextPage"].blank?
|
|
1266
1120
|
url = self.rest_endpoint(response["nextPage"].split('/v1/').last)
|
|
1267
1121
|
Rails.logger.debug("Fetch Catalog URL #{url}")
|
|
1268
|
-
output_json, response = self.rest_call(debug
|
|
1269
|
-
|
|
1270
|
-
if !/(true|t|yes|y|1)$/.match(output_json['success'].to_s) || output_json['success'].class != TrueClass
|
|
1122
|
+
output_json, response = self.rest_call(:debug => false, :url => url, :errors => [ZuoraAPI::Exceptions::ZuoraAPISessionError], :timeout_retry => true )
|
|
1123
|
+
if !output_json['success'] =~ (/(true|t|yes|y|1)$/i) || output_json['success'].class != TrueClass
|
|
1271
1124
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
|
|
1272
1125
|
end
|
|
1273
1126
|
output_json["products"].each do |product|
|
|
@@ -1293,7 +1146,7 @@ module ZuoraAPI
|
|
|
1293
1146
|
return products, catalog_map
|
|
1294
1147
|
end
|
|
1295
1148
|
|
|
1296
|
-
def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout:
|
|
1149
|
+
def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout: 120, session_type: :basic, **execute_params)
|
|
1297
1150
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
|
1298
1151
|
|
|
1299
1152
|
retry_count ||= timeout_retries
|
|
@@ -1401,12 +1254,14 @@ module ZuoraAPI
|
|
|
1401
1254
|
if !(retry_count -= 1).zero?
|
|
1402
1255
|
self.new_session
|
|
1403
1256
|
raise response.class
|
|
1257
|
+
else
|
|
1258
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1404
1259
|
end
|
|
1405
|
-
|
|
1260
|
+
else
|
|
1261
|
+
raise
|
|
1406
1262
|
end
|
|
1407
|
-
raise
|
|
1408
1263
|
else
|
|
1409
|
-
raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}
|
|
1264
|
+
raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
|
|
1410
1265
|
end
|
|
1411
1266
|
end
|
|
1412
1267
|
|
|
@@ -1414,120 +1269,133 @@ module ZuoraAPI
|
|
|
1414
1269
|
sleep(5)
|
|
1415
1270
|
if (retry_count -= 1) >= 0
|
|
1416
1271
|
retry
|
|
1272
|
+
else
|
|
1273
|
+
Rails.logger.error("File Download Failed")
|
|
1274
|
+
raise
|
|
1417
1275
|
end
|
|
1418
|
-
Rails.logger.error("File Download Failed")
|
|
1419
|
-
raise
|
|
1420
1276
|
end
|
|
1421
1277
|
|
|
1422
1278
|
def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
xml['SOAP-ENV'].
|
|
1427
|
-
xml['
|
|
1428
|
-
xml['ns1'].
|
|
1279
|
+
begin
|
|
1280
|
+
tries ||= 3
|
|
1281
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
|
1282
|
+
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
|
|
1283
|
+
xml['SOAP-ENV'].Header do
|
|
1284
|
+
xml['ns1'].SessionHeader do
|
|
1285
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1286
|
+
end
|
|
1429
1287
|
end
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1288
|
+
xml['SOAP-ENV'].Body do
|
|
1289
|
+
xml['ns1'].create do
|
|
1290
|
+
xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
|
|
1291
|
+
xml['ns2'].Format 'csv'
|
|
1292
|
+
xml['ns2'].Zip zip
|
|
1293
|
+
xml['ns2'].Name 'googman'
|
|
1294
|
+
xml['ns2'].Query query
|
|
1295
|
+
xml['ns2'].Encrypted encrypted
|
|
1296
|
+
end
|
|
1439
1297
|
end
|
|
1440
1298
|
end
|
|
1441
1299
|
end
|
|
1442
1300
|
end
|
|
1443
|
-
end
|
|
1444
1301
|
|
|
1445
|
-
|
|
1302
|
+
response_query = HTTParty.post(self.url, body: request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8", "Z-Track-Id" => z_track_id}, :timeout => 120)
|
|
1446
1303
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1304
|
+
output_xml = Nokogiri::XML(response_query.body)
|
|
1305
|
+
raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
|
1449
1306
|
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1307
|
+
# raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
|
1308
|
+
|
|
1309
|
+
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
|
1453
1310
|
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1311
|
+
confirmRequest = Nokogiri::XML::Builder.new do |xml|
|
|
1312
|
+
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
|
|
1313
|
+
xml['SOAP-ENV'].Header do
|
|
1314
|
+
xml['ns1'].SessionHeader do
|
|
1315
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1316
|
+
end
|
|
1459
1317
|
end
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1318
|
+
xml['SOAP-ENV'].Body do
|
|
1319
|
+
xml['ns1'].query do
|
|
1320
|
+
xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
|
|
1321
|
+
end
|
|
1464
1322
|
end
|
|
1465
1323
|
end
|
|
1466
1324
|
end
|
|
1467
|
-
|
|
1468
|
-
result = 'Waiting'
|
|
1325
|
+
result = 'Waiting'
|
|
1469
1326
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1327
|
+
while result != "Completed"
|
|
1328
|
+
sleep 3
|
|
1329
|
+
response_query = HTTParty.post(self.url, body: confirmRequest.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8", "Z-Track-Id" => z_track_id}, :timeout => 120)
|
|
1473
1330
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1331
|
+
output_xml = Nokogiri::XML(response_query.body)
|
|
1332
|
+
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1333
|
+
status_code = response_query.code if response_query
|
|
1477
1334
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1335
|
+
raise_errors(type: :SOAP, body: output_xml, response: response_query) if result.blank? || result == "Failed"
|
|
1336
|
+
# raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if result.blank? || result == "Failed"
|
|
1337
|
+
end
|
|
1481
1338
|
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1339
|
+
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1340
|
+
export_file = get_file(:url => self.fileURL(file_id))
|
|
1341
|
+
export_file_path = export_file.path
|
|
1342
|
+
Rails.logger.debug("=====> Export path #{export_file.path}")
|
|
1343
|
+
|
|
1344
|
+
if extract && zip
|
|
1345
|
+
require "zip"
|
|
1346
|
+
new_path = export_file_path.partition('.zip').first
|
|
1347
|
+
zipped = Zip::File.open(export_file_path)
|
|
1348
|
+
file_handle = zipped.entries.first
|
|
1349
|
+
file_handle.extract(new_path)
|
|
1350
|
+
File.delete(export_file_path)
|
|
1351
|
+
return new_path
|
|
1352
|
+
else
|
|
1353
|
+
return export_file_path
|
|
1354
|
+
end
|
|
1355
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1356
|
+
if !(tries -= 1).zero?
|
|
1357
|
+
Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
|
|
1358
|
+
self.new_session
|
|
1359
|
+
retry
|
|
1360
|
+
else
|
|
1361
|
+
raise ex
|
|
1362
|
+
end
|
|
1505
1363
|
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1364
|
+
rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
|
|
1365
|
+
if !(tries -= 1).zero?
|
|
1366
|
+
Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
|
|
1367
|
+
sleep 10
|
|
1368
|
+
retry
|
|
1369
|
+
else
|
|
1370
|
+
raise ex
|
|
1371
|
+
end
|
|
1513
1372
|
|
|
1514
|
-
|
|
1515
|
-
|
|
1373
|
+
rescue *ZUORA_API_ERRORS => ex
|
|
1374
|
+
raise ex
|
|
1516
1375
|
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1376
|
+
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
1377
|
+
if !(tries -= 1).zero?
|
|
1378
|
+
Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
|
|
1379
|
+
sleep 5
|
|
1380
|
+
retry
|
|
1381
|
+
else
|
|
1382
|
+
raise ex
|
|
1383
|
+
end
|
|
1524
1384
|
|
|
1525
|
-
|
|
1526
|
-
|
|
1385
|
+
rescue Errno::ECONNRESET => ex
|
|
1386
|
+
if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
|
|
1387
|
+
retry
|
|
1388
|
+
else
|
|
1389
|
+
raise ex
|
|
1390
|
+
end
|
|
1391
|
+
|
|
1392
|
+
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1393
|
+
raise ex
|
|
1394
|
+
end
|
|
1527
1395
|
end
|
|
1528
1396
|
|
|
1529
1397
|
def query(query, parse = false)
|
|
1530
|
-
output_xml, input_xml = self.soap_call(debug
|
|
1398
|
+
output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
|
|
1531
1399
|
xml['ns1'].query do
|
|
1532
1400
|
xml['ns1'].queryString query
|
|
1533
1401
|
end
|