zuora_api 1.7.7 → 1.7.08
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/.gitignore +0 -1
- data/.gitlab-ci.yml +2 -2
- data/Gemfile.lock +29 -29
- data/README.md +1 -1
- data/lib/insights_api/login.rb +6 -5
- data/lib/zuora_api/exceptions.rb +28 -103
- data/lib/zuora_api/login.rb +325 -595
- data/lib/zuora_api/logins/basic.rb +5 -14
- data/lib/zuora_api/logins/oauth.rb +32 -54
- data/lib/zuora_api/version.rb +1 -1
- metadata +2 -2
data/lib/zuora_api/login.rb
CHANGED
@@ -5,7 +5,7 @@ require 'zuora_api/exceptions'
|
|
5
5
|
|
6
6
|
module ZuoraAPI
|
7
7
|
class Login
|
8
|
-
ENVIRONMENTS = [
|
8
|
+
ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown', STAGING = 'Staging' ]
|
9
9
|
REGIONS = [EU = 'EU', US = 'US', NA = 'NA' ]
|
10
10
|
MIN_Endpoint = '96.0'
|
11
11
|
XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
@@ -16,8 +16,7 @@ module ZuoraAPI
|
|
16
16
|
Errno::ECONNREFUSED,
|
17
17
|
SocketError,
|
18
18
|
Errno::EHOSTUNREACH,
|
19
|
-
Errno::EADDRNOTAVAIL
|
20
|
-
Errno::ETIMEDOUT,
|
19
|
+
Errno::EADDRNOTAVAIL
|
21
20
|
].freeze
|
22
21
|
|
23
22
|
CONNECTION_READ_EXCEPTIONS = [
|
@@ -31,17 +30,7 @@ module ZuoraAPI
|
|
31
30
|
ZuoraAPI::Exceptions::ZuoraAPIRequestLimit,
|
32
31
|
ZuoraAPI::Exceptions::ZuoraAPILockCompetition,
|
33
32
|
ZuoraAPI::Exceptions::ZuoraAPITemporaryError,
|
34
|
-
ZuoraAPI::Exceptions::ZuoraDataIntegrity
|
35
|
-
ZuoraAPI::Exceptions::ZuoraAPIInternalServerError,
|
36
|
-
ZuoraAPI::Exceptions::ZuoraUnexpectedError,
|
37
|
-
ZuoraAPI::Exceptions::ZuoraAPIUnkownError
|
38
|
-
].freeze
|
39
|
-
|
40
|
-
ZUORA_SERVER_ERRORS = [
|
41
|
-
ZuoraAPI::Exceptions::ZuoraAPIInternalServerError,
|
42
|
-
ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout,
|
43
|
-
ZuoraAPI::Exceptions::ZuoraAPIReadTimeout,
|
44
|
-
ZuoraAPI::Exceptions::ZuoraUnexpectedError
|
33
|
+
ZuoraAPI::Exceptions::ZuoraDataIntegrity
|
45
34
|
].freeze
|
46
35
|
|
47
36
|
attr_accessor :region, :url, :wsdl_number, :current_session, :bearer_token, :oauth_session_expires_at, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep, :hostname, :zconnect_provider
|
@@ -72,12 +61,27 @@ module ZuoraAPI
|
|
72
61
|
|
73
62
|
def get_identity(cookies)
|
74
63
|
zsession = cookies["ZSession"]
|
64
|
+
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
75
65
|
begin
|
76
66
|
if !zsession.blank?
|
77
67
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
78
68
|
output_json = JSON.parse(response.body)
|
69
|
+
elsif zconnect_accesstoken.present?
|
70
|
+
begin
|
71
|
+
code = zconnect_accesstoken.split("#!").last
|
72
|
+
encrypted_token, tenant_id = Base64.decode64(code).split(":")
|
73
|
+
body = {'token' => encrypted_token}.to_json
|
74
|
+
rescue => ex
|
75
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie")
|
76
|
+
end
|
77
|
+
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
|
78
|
+
output_json = JSON.parse(response.body)
|
79
79
|
else
|
80
|
-
|
80
|
+
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
81
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
82
|
+
else
|
83
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
84
|
+
end
|
81
85
|
end
|
82
86
|
rescue JSON::ParserError => ex
|
83
87
|
output_json = {}
|
@@ -88,12 +92,20 @@ module ZuoraAPI
|
|
88
92
|
|
89
93
|
def get_full_nav(cookies)
|
90
94
|
zsession = cookies["ZSession"]
|
95
|
+
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
91
96
|
begin
|
92
97
|
if zsession.present?
|
93
98
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
94
99
|
output_json = JSON.parse(response.body)
|
100
|
+
elsif zconnect_accesstoken.present?
|
101
|
+
response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
|
102
|
+
output_json = JSON.parse(response.body)
|
95
103
|
else
|
96
|
-
|
104
|
+
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
105
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
106
|
+
else
|
107
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
108
|
+
end
|
97
109
|
end
|
98
110
|
rescue JSON::ParserError => ex
|
99
111
|
output_json = {}
|
@@ -104,12 +116,20 @@ module ZuoraAPI
|
|
104
116
|
|
105
117
|
def set_nav(state, cookies)
|
106
118
|
zsession = cookies["ZSession"]
|
119
|
+
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
107
120
|
begin
|
108
121
|
if !zsession.blank?
|
109
122
|
response = HTTParty.put("https://#{self.hostname}/apps/v1/preference/navigation", :body => state.to_json, :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
110
123
|
output_json = JSON.parse(response.body)
|
124
|
+
elsif !zconnect_accesstoken.blank?
|
125
|
+
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/navigationstate", :body => state.to_json, :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
126
|
+
output_json = JSON.parse(response.body)
|
111
127
|
else
|
112
|
-
|
128
|
+
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
129
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
130
|
+
else
|
131
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
132
|
+
end
|
113
133
|
end
|
114
134
|
rescue JSON::ParserError => ex
|
115
135
|
output_json = {}
|
@@ -120,12 +140,20 @@ module ZuoraAPI
|
|
120
140
|
|
121
141
|
def refresh_nav(cookies)
|
122
142
|
zsession = cookies["ZSession"]
|
143
|
+
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
123
144
|
begin
|
124
145
|
if !zsession.blank?
|
125
146
|
response = HTTParty.post("https://#{self.hostname}/apps/v1/navigation/fetch", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
126
147
|
output_json = JSON.parse(response.body)
|
148
|
+
elsif !zconnect_accesstoken.blank?
|
149
|
+
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/refresh-navbarcache", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
150
|
+
output_json = JSON.parse(response.body)
|
127
151
|
else
|
128
|
-
|
152
|
+
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
153
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
154
|
+
else
|
155
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
156
|
+
end
|
129
157
|
end
|
130
158
|
rescue JSON::ParserError => ex
|
131
159
|
output_json = {}
|
@@ -134,21 +162,27 @@ module ZuoraAPI
|
|
134
162
|
return output_json
|
135
163
|
end
|
136
164
|
|
165
|
+
def get_zconnect_accesstoken(cookies)
|
166
|
+
accesstoken = nil
|
167
|
+
self.update_zconnect_provider
|
168
|
+
if !cookies[self.zconnect_provider].nil? && !cookies[self.zconnect_provider].empty?
|
169
|
+
accesstoken = cookies[self.zconnect_provider]
|
170
|
+
end
|
171
|
+
return accesstoken
|
172
|
+
end
|
173
|
+
|
137
174
|
def reporting_url(path)
|
138
175
|
map = {"US" => {"Sandbox" => "https://zconnectsandbox.zuora.com/api/rest/v1/",
|
139
176
|
"Production" => "https://zconnect.zuora.com/api/rest/v1/",
|
140
|
-
"
|
141
|
-
"Staging" => "https://reporting-stg11.zan.svc.auw2.zuora.com/api/rest/v1/",
|
142
|
-
"Performance" => "https://zconnectpt1.zuora.com/api/rest/v1/",
|
143
|
-
"Services" => "https://reporting-svc08.svc.auw2.zuora.com/api/rest/v1/"},
|
177
|
+
"Services"=> ""},
|
144
178
|
"EU" => {"Sandbox" => "https://zconnect.sandbox.eu.zuora.com/api/rest/v1/",
|
145
179
|
"Production" => "https://zconnect.eu.zuora.com/api/rest/v1/",
|
146
|
-
"Services"=> "
|
180
|
+
"Services"=> ""},
|
147
181
|
"NA" => {"Sandbox" => "https://zconnect.sandbox.na.zuora.com/api/rest/v1/",
|
148
182
|
"Production" => "https://zconnect.na.zuora.com/api/rest/v1/",
|
149
183
|
"Services"=> ""}
|
150
184
|
}
|
151
|
-
return map[
|
185
|
+
return map[zuora_client.region][zuora_client.environment].insert(-1, path)
|
152
186
|
end
|
153
187
|
|
154
188
|
# There are two ways to call this method. The first way is best.
|
@@ -198,7 +232,7 @@ module ZuoraAPI
|
|
198
232
|
end
|
199
233
|
|
200
234
|
def self.environments
|
201
|
-
%w(Sandbox Production Services Performance Staging
|
235
|
+
%w(Sandbox Production Services Performance Staging)
|
202
236
|
end
|
203
237
|
|
204
238
|
def self.regions
|
@@ -210,13 +244,11 @@ module ZuoraAPI
|
|
210
244
|
"Production" => "https://www.zuora.com/apps/services/a/",
|
211
245
|
"Performance" => "https://pt1.zuora.com/apps/services/a/",
|
212
246
|
"Services" => "https://services347.zuora.com/apps/services/a/",
|
213
|
-
"Staging" => "https://staging2.zuora.com/apps/services/a/",
|
214
|
-
"Test" => "https://test.zuora.com/apps/services/a/"},
|
247
|
+
"Staging" => "https://staging2.zuora.com/apps/services/a/"},
|
215
248
|
"EU" => {"Sandbox" => "https://sandbox.eu.zuora.com/apps/services/a/",
|
216
249
|
"Production" => "https://eu.zuora.com/apps/services/a/",
|
217
250
|
"Performance" => "https://pt1.eu.zuora.com/apps/services/a/",
|
218
|
-
"Services" => "https://services347.eu.zuora.com/apps/services/a/",
|
219
|
-
"Test" => "https://test.eu.zuora.com/apps/services/a/"},
|
251
|
+
"Services" => "https://services347.eu.zuora.com/apps/services/a/"},
|
220
252
|
"NA" => {"Sandbox" => "https://sandbox.na.zuora.com/apps/services/a/",
|
221
253
|
"Production" => "https://na.zuora.com/apps/services/a/",
|
222
254
|
"Performance" => "https://pt1.na.zuora.com/apps/services/a/",
|
@@ -253,18 +285,15 @@ module ZuoraAPI
|
|
253
285
|
|
254
286
|
def update_environment
|
255
287
|
if !self.url.blank?
|
256
|
-
|
257
|
-
when /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/
|
288
|
+
if /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/ === self.hostname
|
258
289
|
self.environment = 'Sandbox'
|
259
|
-
|
290
|
+
elsif /(?<=\.|\/|^)(service[\d]*|services[\d]*|ep-edge)(?=\.|\/|$)/ === self.hostname
|
260
291
|
self.environment = 'Services'
|
261
|
-
|
292
|
+
elsif /(?<=\.|\/|-|^)(pt[\d]*)(?=\.|\/|-|$)/ === self.hostname
|
262
293
|
self.environment = 'Performance'
|
263
|
-
|
294
|
+
elsif /(?<=\.|\/|^)(staging1|staging2|stg)(?=\.|\/|$)/ === self.hostname
|
264
295
|
self.environment = 'Staging'
|
265
|
-
|
266
|
-
self.environment = 'Test'
|
267
|
-
when /(?<=\.|\/|^)(www|api)(?=\.|\/|$)/, /(^|tls10\.|origin-www\.|zforsf\.|eu\.|na\.)(zuora\.com)/
|
296
|
+
elsif is_prod_env
|
268
297
|
self.environment = 'Production'
|
269
298
|
else
|
270
299
|
self.environment = 'Unknown'
|
@@ -274,14 +303,25 @@ module ZuoraAPI
|
|
274
303
|
end
|
275
304
|
end
|
276
305
|
|
306
|
+
def is_prod_env
|
307
|
+
is_prod = false
|
308
|
+
www_or_api = /(?<=\.|\/|^)(www|api)(?=\.|\/|$)/ === self.hostname
|
309
|
+
host_prefix_match = /(^|tls10\.|origin-www\.|zforsf\.|eu\.|na\.)(zuora\.com)/ === self.hostname
|
310
|
+
if www_or_api || host_prefix_match
|
311
|
+
is_prod = true
|
312
|
+
end
|
313
|
+
return is_prod
|
314
|
+
end
|
315
|
+
|
277
316
|
def update_zconnect_provider
|
278
317
|
region = update_region
|
279
318
|
environment = update_environment
|
280
|
-
mappings = {"US" => {"Sandbox" => "ZConnectSbx",
|
281
|
-
"NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "
|
282
|
-
"EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "
|
319
|
+
mappings = {"US" => {"Sandbox" => "ZConnectSbx", "KubeSTG" => "ZConnectDev", "KubeDEV" => "ZConnectDev", "KubePROD" => "ZConnectDev", "Services" => "ZConnectQA", "Production" => "ZConnectProd", "Performance" => "ZConnectPT1", "Staging" => "ZConnectQA"},
|
320
|
+
"NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "ZConnectQANA", "Production" => "ZConnectProdNA", "Performance" => "ZConnectPT1NA"},
|
321
|
+
"EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "ZConnectQAEU", "Production" => "ZConnectProdEU", "Performance" => "ZConnectPT1EU"},
|
283
322
|
"Unknown" => {"Unknown" => "Unknown"}}
|
284
323
|
self.zconnect_provider = mappings[region][environment]
|
324
|
+
# raise "Can't find ZConnect Provider for #{region} region and #{environment} environment" if self.zconnect_provider.nil?
|
285
325
|
end
|
286
326
|
|
287
327
|
def aqua_endpoint(url="")
|
@@ -294,35 +334,45 @@ module ZuoraAPI
|
|
294
334
|
return "#{url_slash_apps_slash}api/#{url}"
|
295
335
|
end
|
296
336
|
|
297
|
-
def rest_endpoint(url=""
|
337
|
+
def rest_endpoint(url="")
|
298
338
|
update_environment
|
299
339
|
endpoint = url
|
300
|
-
|
301
|
-
|
340
|
+
|
302
341
|
case self.environment
|
303
|
-
when 'Test'
|
304
|
-
endpoint = "https://rest.test#{url_postfix}zuora.com"
|
305
342
|
when 'Sandbox'
|
306
|
-
|
307
|
-
|
343
|
+
case self.region
|
344
|
+
when 'US'
|
345
|
+
endpoint = "https://rest.apisandbox.zuora.com/v1/".concat(url)
|
346
|
+
when 'EU'
|
347
|
+
endpoint = "https://rest.sandbox.eu.zuora.com/v1/".concat(url)
|
348
|
+
when 'NA'
|
349
|
+
endpoint = "https://rest.sandbox.na.zuora.com/v1/".concat(url)
|
350
|
+
end
|
308
351
|
when 'Production'
|
309
|
-
|
352
|
+
case self.region
|
353
|
+
when 'US'
|
354
|
+
endpoint = "https://rest.zuora.com/v1/".concat(url)
|
355
|
+
when 'EU'
|
356
|
+
endpoint = "https://rest.eu.zuora.com/v1/".concat(url)
|
357
|
+
when 'NA'
|
358
|
+
endpoint = "https://rest.na.zuora.com/v1/".concat(url)
|
359
|
+
end
|
310
360
|
when 'Performance'
|
311
|
-
endpoint = "https://rest.pt1.zuora.com"
|
361
|
+
endpoint = "https://rest.pt1.zuora.com/v1/".concat(url)
|
312
362
|
when 'Services'
|
313
363
|
https = /https:\/\/|http:\/\//.match(self.url)[0]
|
314
364
|
host = self.hostname
|
315
|
-
endpoint = "#{https}rest#{host}"
|
365
|
+
endpoint = "#{https}rest#{host}/v1/#{url}"
|
316
366
|
when 'Staging'
|
317
|
-
endpoint = "https://rest-staging2.zuora.com"
|
367
|
+
endpoint = "https://rest-staging2.zuora.com/v1/".concat(url)
|
318
368
|
when 'Unknown'
|
319
369
|
raise "Environment unknown, returning passed in parameter unaltered"
|
320
370
|
end
|
321
|
-
return
|
371
|
+
return endpoint
|
322
372
|
end
|
323
373
|
|
324
374
|
def rest_domain
|
325
|
-
return URI(self.rest_endpoint).host
|
375
|
+
return URI(self.rest_endpoint).host
|
326
376
|
end
|
327
377
|
|
328
378
|
def fileURL(url="")
|
@@ -333,10 +383,10 @@ module ZuoraAPI
|
|
333
383
|
return self.wsdl_number > 68 ? '%Y-%m-%d' : '%Y-%m-%dT%H:%M:%S'
|
334
384
|
end
|
335
385
|
|
336
|
-
def new_session(auth_type: :basic, debug: false
|
386
|
+
def new_session(auth_type: :basic, debug: false)
|
337
387
|
end
|
338
388
|
|
339
|
-
def get_session(prefix: false, auth_type: :basic
|
389
|
+
def get_session(prefix: false, auth_type: :basic)
|
340
390
|
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}") if Rails.env.to_s == 'development'
|
341
391
|
case auth_type
|
342
392
|
when :basic
|
@@ -344,13 +394,13 @@ module ZuoraAPI
|
|
344
394
|
case self.class.to_s
|
345
395
|
when 'ZuoraAPI::Oauth'
|
346
396
|
if self.bearer_token.blank? || self.oauth_expired?
|
347
|
-
self.new_session(auth_type: :bearer
|
397
|
+
self.new_session(auth_type: :bearer)
|
348
398
|
end
|
349
|
-
self.get_z_session
|
399
|
+
self.get_z_session if self.status == 'Active'
|
350
400
|
when 'ZuoraAPI::Basic'
|
351
|
-
self.new_session(auth_type: :basic
|
401
|
+
self.new_session(auth_type: :basic)
|
352
402
|
else
|
353
|
-
|
403
|
+
raise "No Zuora Login Specified"
|
354
404
|
end
|
355
405
|
end
|
356
406
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
@@ -359,33 +409,17 @@ module ZuoraAPI
|
|
359
409
|
case self.class.to_s
|
360
410
|
when 'ZuoraAPI::Oauth'
|
361
411
|
if self.bearer_token.blank? || self.oauth_expired?
|
362
|
-
self.new_session(auth_type: :bearer
|
412
|
+
self.new_session(auth_type: :bearer)
|
363
413
|
end
|
364
414
|
when 'ZuoraAPI::Basic'
|
365
415
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}")
|
366
|
-
else
|
367
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Unknown Login, does not support Authentication of Type: #{auth_type}")
|
368
416
|
end
|
369
|
-
|
370
417
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
371
418
|
return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
|
372
419
|
end
|
373
420
|
end
|
374
421
|
|
375
|
-
def soap_call(
|
376
|
-
ns1: 'ns1',
|
377
|
-
ns2: 'ns2',
|
378
|
-
batch_size: nil,
|
379
|
-
single_transaction: false,
|
380
|
-
debug: false,
|
381
|
-
zuora_track_id: nil,
|
382
|
-
errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
|
383
|
-
z_session: true,
|
384
|
-
timeout_retry: false,
|
385
|
-
timeout: 120,
|
386
|
-
timeout_sleep_interval: self.timeout_sleep,
|
387
|
-
output_exception_messages: true,
|
388
|
-
**keyword_args)
|
422
|
+
def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS), z_session: true, timeout_retry: false, timeout: 120,**keyword_args)
|
389
423
|
tries ||= 2
|
390
424
|
xml = Nokogiri::XML::Builder.new do |xml|
|
391
425
|
xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/",
|
@@ -395,7 +429,7 @@ module ZuoraAPI
|
|
395
429
|
"xmlns:#{ns1}" => "http://api.zuora.com/") do
|
396
430
|
xml['SOAP-ENV'].Header do
|
397
431
|
xml["#{ns1}"].SessionHeader do
|
398
|
-
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic
|
432
|
+
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic)
|
399
433
|
end
|
400
434
|
if single_transaction
|
401
435
|
xml["#{ns1}"].CallOptions do
|
@@ -418,34 +452,15 @@ module ZuoraAPI
|
|
418
452
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
419
453
|
Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
420
454
|
|
421
|
-
|
422
|
-
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
423
|
-
|
424
|
-
request = HTTParty::Request.new(
|
425
|
-
Net::HTTP::Post,
|
426
|
-
self.url,
|
427
|
-
body: xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip,
|
428
|
-
headers: headers,
|
429
|
-
timeout: timeout,
|
430
|
-
)
|
431
|
-
|
432
|
-
response = request.perform
|
433
|
-
|
455
|
+
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)
|
434
456
|
output_xml = Nokogiri::XML(response.body)
|
435
457
|
Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
436
458
|
|
437
459
|
raise_errors(type: :SOAP, body: output_xml, response: response)
|
438
460
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
439
|
-
if !tries.zero? && z_session
|
440
|
-
tries -= 1
|
461
|
+
if !(tries -= 1).zero? && z_session
|
441
462
|
Rails.logger.debug("SOAP Call - Session Invalid")
|
442
|
-
|
443
|
-
begin
|
444
|
-
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
445
|
-
rescue *ZUORA_API_ERRORS => ex
|
446
|
-
return output_xml, input_xml, ex.response
|
447
|
-
end
|
448
|
-
|
463
|
+
self.new_session(auth_type: :basic)
|
449
464
|
retry
|
450
465
|
else
|
451
466
|
if errors.include?(ex.class)
|
@@ -458,45 +473,30 @@ module ZuoraAPI
|
|
458
473
|
if errors.include?(ex.class)
|
459
474
|
raise ex
|
460
475
|
else
|
461
|
-
response = ex.response unless response
|
462
476
|
return output_xml, input_xml, response
|
463
477
|
end
|
464
478
|
rescue *CONNECTION_EXCEPTIONS => ex
|
465
|
-
if tries.zero?
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
end
|
472
|
-
end
|
473
|
-
raise ex
|
479
|
+
if !(tries -= 1).zero?
|
480
|
+
Rails.logger.info("SOAP Call - #{ex.class} Timed out will retry after 5 seconds")
|
481
|
+
sleep(self.timeout_sleep)
|
482
|
+
retry
|
483
|
+
else
|
484
|
+
raise ex
|
474
485
|
end
|
475
|
-
|
476
|
-
tries -= 1
|
477
|
-
sleep(timeout_sleep_interval)
|
478
|
-
retry
|
479
486
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
480
|
-
if !tries.zero?
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
sleep(timeout_sleep_interval)
|
487
|
-
retry
|
488
|
-
end
|
487
|
+
if !(tries -= 1).zero? && timeout_retry
|
488
|
+
Rails.logger.info("SOAP Call - #{ex.class} Timed out will retry after 5 seconds")
|
489
|
+
sleep(self.timeout_sleep)
|
490
|
+
retry
|
491
|
+
else
|
492
|
+
raise ex
|
489
493
|
end
|
490
|
-
|
491
|
-
if
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
496
|
-
end
|
494
|
+
rescue Errno::ECONNRESET => ex
|
495
|
+
if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
|
496
|
+
retry
|
497
|
+
else
|
498
|
+
raise ex
|
497
499
|
end
|
498
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
499
|
-
raise ex
|
500
500
|
rescue => ex
|
501
501
|
raise ex
|
502
502
|
else
|
@@ -504,60 +504,39 @@ module ZuoraAPI
|
|
504
504
|
end
|
505
505
|
|
506
506
|
def raise_errors(type: :SOAP, body: nil, response: nil)
|
507
|
-
request_uri, request_path, match_string = "", "", ""
|
508
|
-
if response.class.to_s == "HTTP::Message"
|
509
|
-
request_uri = response.http_header.request_uri.to_s
|
510
|
-
request_path = response.http_header.request_uri.path
|
511
|
-
match_string = "#{response.http_header.request_method}::#{response.code}::#{request_uri}"
|
512
|
-
else
|
513
|
-
request = response.request
|
514
|
-
request_uri = response.request.uri
|
515
|
-
request_path = request.path.path
|
516
|
-
match_string = "#{request.http_method.to_s.split("Net::HTTP::").last.upcase}::#{response.code}::#{request_path}"
|
517
|
-
end
|
518
|
-
|
519
507
|
if [502,503].include?(response.code)
|
520
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from
|
508
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from downstream host", response)
|
521
509
|
end
|
522
510
|
|
523
|
-
|
524
|
-
|
525
|
-
when 504
|
526
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{request_uri}", response)
|
527
|
-
when 429
|
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)
|
529
|
-
when 401
|
530
|
-
|
531
|
-
else
|
532
|
-
if body.class == Hash
|
533
|
-
case request_path
|
534
|
-
when /^\/v1\/connections$/
|
535
|
-
response_headers = response.headers.to_h
|
536
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing cookies for authentication call", response) if response_headers['set-cookie'].blank?
|
537
|
-
z_session_cookie = response_headers.fetch('set-cookie', []).select{|x| x.match(/^ZSession=.*/) }.first
|
538
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing ZSession cookie for authentication call", response) if z_session_cookie.blank?
|
539
|
-
end
|
540
|
-
end
|
511
|
+
if response.code == 504
|
512
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from downstream host", response)
|
541
513
|
end
|
542
514
|
|
543
515
|
case type
|
544
516
|
when :SOAP
|
545
|
-
error
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
517
|
+
error = body.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text
|
518
|
+
message = body.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
519
|
+
|
520
|
+
if error.blank? || message.blank?
|
521
|
+
error = body.xpath('//faultcode').text
|
522
|
+
message = body.xpath('//faultstring').text
|
523
|
+
end
|
524
|
+
|
525
|
+
if error.blank? || message.blank?
|
526
|
+
error = body.xpath('//ns1:Code', 'ns1' =>'http://api.zuora.com/').text
|
527
|
+
message = body.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text
|
528
|
+
end
|
529
|
+
|
530
|
+
#Update/Create/Delete Calls with multiple requests and responses
|
531
|
+
if body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').size > 0 && body.xpath('//ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
|
532
|
+
error = []
|
533
|
+
success = []
|
534
|
+
body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').each_with_index do |call, object_index|
|
535
|
+
if call.xpath('./ns1:Success', 'ns1' =>'http://api.zuora.com/').text == 'false' && call.xpath('./ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
|
536
|
+
message = "#{call.xpath('./*/ns1:Code', 'ns1' =>'http://api.zuora.com/').text}::#{call.xpath('./*/ns1:Message', 'ns1' =>'http://api.zuora.com/').text}"
|
537
|
+
error.push(message)
|
558
538
|
else
|
559
|
-
|
560
|
-
message = 'Export failed due to unknown reason. Consult api logs.'
|
539
|
+
success.push(call.xpath('./ns1:Id', 'ns1' =>'http://api.zuora.com/').text)
|
561
540
|
end
|
562
541
|
end
|
563
542
|
end
|
@@ -565,48 +544,44 @@ module ZuoraAPI
|
|
565
544
|
#By default response if not passed in for SOAP as all SOAP is 200
|
566
545
|
if error.present?
|
567
546
|
if error.class == String
|
568
|
-
|
547
|
+
case error
|
548
|
+
when "INVALID_SESSION"
|
549
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{error}::#{message}", response)
|
550
|
+
when "REQUEST_EXCEEDED_LIMIT"
|
551
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{error}::#{message}", response)
|
552
|
+
when "LOCK_COMPETITION"
|
553
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
|
554
|
+
when "BATCH_FAIL_ERROR"
|
555
|
+
if message.include?("optimistic locking failed")
|
556
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
|
557
|
+
else
|
558
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
|
559
|
+
end
|
560
|
+
when "TEMPORARY_ERROR"
|
561
|
+
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{error}::#{message}", response)
|
562
|
+
when "INVALID_VALUE"
|
563
|
+
if message.include?("data integrity violation")
|
564
|
+
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
|
565
|
+
else
|
566
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
|
567
|
+
end
|
568
|
+
else
|
569
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response) if error.present?
|
570
|
+
end
|
569
571
|
elsif error.class == Array
|
570
|
-
if error.
|
571
|
-
|
572
|
-
raise_errors_helper(error: err, message: msg, response: response, errors: error, success: success)
|
572
|
+
if error[0].include?("LOCK_COMPETITION") && error.count == 1
|
573
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), response)
|
573
574
|
else
|
574
575
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), response, error, success)
|
575
576
|
end
|
576
577
|
end
|
577
578
|
end
|
578
|
-
|
579
|
-
self.errors_via_content_type(response: response, type: :xml)
|
580
579
|
|
581
|
-
|
582
|
-
|
583
|
-
when /^\/query\/jobs.*/ #DataQuery Paths
|
584
|
-
return if body.class != Hash
|
585
|
-
case match_string
|
586
|
-
when /^GET::200::\/query\/jobs\/([a-zA-Z0-9\-_]+)$/ #Get DQ job, Capture of the id is present if needed in future error responses.
|
587
|
-
if body.dig('data', "errorCode") == "LINK_10000005"
|
588
|
-
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body.dig('data', "errorMessage"), response)
|
589
|
-
elsif (body.dig('data', "errorMessage").present? || body.dig('data', "queryStatus") == "failed")
|
590
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('data', "errorMessage"), response)
|
591
|
-
end
|
592
|
-
when /^GET::404::\/query\/jobs\/([a-zA-Z0-9\-_]+)$/ #Get DQ job not found, capture of the id is present if needed in future error responses.
|
593
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('message'), response) if body.dig('message').present?
|
594
|
-
when /^POST::400::\/query\/jobs$/ #Create DQ job
|
595
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('message'), response) if body.dig('message').present?
|
596
|
-
end
|
597
|
-
when /^\/api\/rest\/v1\/reports.*/ #Reporting Paths
|
598
|
-
reporting_message = response.parsed_response.dig("ZanResponse", "response", "message") || body.dig("message")
|
599
|
-
if reporting_message&.include?("com.zuora.rest.RestUsageException: The user does not have permissions for this API.")
|
600
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response)
|
601
|
-
elsif reporting_message&.include?("500 Internal Server Error")
|
602
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Internal Server Error. The Reporting API is down. Contact Support.", response)
|
603
|
-
end
|
604
|
-
case match_string
|
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.
|
606
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
|
607
|
-
end
|
580
|
+
if response.code == 429
|
581
|
+
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)
|
608
582
|
end
|
609
583
|
|
584
|
+
when :JSON
|
610
585
|
body = body.dig("results").present? ? body["results"] : body if body.class == Hash
|
611
586
|
if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
|
612
587
|
messages_array = body.fetch("reasons", []).map {|error| error['message']}.compact
|
@@ -614,14 +589,6 @@ module ZuoraAPI
|
|
614
589
|
codes_array = body.fetch("reasons", []).map {|error| error['code']}.compact
|
615
590
|
codes_array = codes_array.push(body.dig("error", 'code')).compact if body.dig('error').class == Hash
|
616
591
|
|
617
|
-
if body['message'] == 'request exceeded limit'
|
618
|
-
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)
|
619
|
-
end
|
620
|
-
|
621
|
-
if (body.dig('message') || '').downcase.include?('unexpected error') && response.code != 500
|
622
|
-
raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(body['message'], response)
|
623
|
-
end
|
624
|
-
|
625
592
|
if body['message'] == "No bearer token" && response.code == 400
|
626
593
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Authentication type is not supported by this Login", response)
|
627
594
|
end
|
@@ -635,12 +602,8 @@ module ZuoraAPI
|
|
635
602
|
end
|
636
603
|
|
637
604
|
#Oauth Tokens - User deactivated
|
638
|
-
if body['
|
639
|
-
|
640
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Forbidden", response)
|
641
|
-
elsif body['status'] == 400 && response.code == 400 && body['message'].include?("Invalid client id")
|
642
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Invalid Oauth Client Id", response)
|
643
|
-
end
|
605
|
+
if body['reason'] == 'Forbidden' && body['status'] == 403 && response.code == 403
|
606
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Forbidden", response)
|
644
607
|
end
|
645
608
|
|
646
609
|
if body['error'] == 'Unauthorized' && body['status'] == 401
|
@@ -648,12 +611,7 @@ module ZuoraAPI
|
|
648
611
|
end
|
649
612
|
#Authentication failed
|
650
613
|
if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
|
651
|
-
|
652
|
-
if new_message.present?
|
653
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(new_message, response)
|
654
|
-
else
|
655
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(body['message'], response)
|
656
|
-
end
|
614
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
|
657
615
|
end
|
658
616
|
|
659
617
|
#Zuora REST Create Amendment error #Authentication failed
|
@@ -661,30 +619,16 @@ module ZuoraAPI
|
|
661
619
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body['faultstring']}", response)
|
662
620
|
end
|
663
621
|
|
664
|
-
#Locking contention
|
665
|
-
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
|
666
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
|
667
|
-
end
|
668
|
-
#Internal Server Error
|
669
|
-
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(60)
|
670
|
-
if messages_array.uniq.size == 1
|
671
|
-
if messages_array.first.match(/^Transaction declined.*|^There is an invoice pending tax.*|^The Zuora GetTax call to Avalara.*|^The tax calculation call to Zuora Connect returned the following error: Status Code: 4.*/)
|
672
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(messages_array.first, response)
|
673
|
-
end
|
674
|
-
end
|
675
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("#{messages_array.join(', ')}", response)
|
676
|
-
end
|
677
|
-
|
678
|
-
#Retryiable Service Error
|
679
|
-
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(61)
|
680
|
-
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{messages_array.join(', ')}", response)
|
681
|
-
end
|
682
|
-
|
683
622
|
#Request exceeded limit
|
684
623
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70)
|
685
624
|
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", response)
|
686
625
|
end
|
687
626
|
|
627
|
+
#Locking contention
|
628
|
+
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
|
629
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
|
630
|
+
end
|
631
|
+
|
688
632
|
#All Errors catch
|
689
633
|
if codes_array.size > 0
|
690
634
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages_array.join(', ')}", response)
|
@@ -692,20 +636,26 @@ module ZuoraAPI
|
|
692
636
|
|
693
637
|
#Zuora REST Query Errors
|
694
638
|
if body["faultcode"].present?
|
695
|
-
|
639
|
+
case body["faultcode"]
|
640
|
+
when "fns:MALFORMED_QUERY"
|
641
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
642
|
+
when "fns:REQUEST_EXCEEDED_LIMIT"
|
643
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
644
|
+
when "fns:LOCK_COMPETITION"
|
645
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
646
|
+
when "INVALID_SESSION"
|
647
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
648
|
+
else
|
649
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
650
|
+
end
|
696
651
|
end
|
697
652
|
|
698
653
|
if body["Errors"].present? || body["errors"].present?
|
699
|
-
|
700
|
-
body
|
701
|
-
body
|
702
|
-
|
703
|
-
|
704
|
-
if codes.size == 1
|
705
|
-
raise_errors_helper(error: codes.first, message: messages.first, response: response, errors: messages)
|
706
|
-
else
|
707
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages.join(", ")}", response, messages)
|
708
|
-
end
|
654
|
+
errors = []
|
655
|
+
(body["Errors"] || []).select { |obj| errors.push(obj["Message"]) }.compact
|
656
|
+
(body["errors"] || []).select { |obj| errors.push(obj["Message"]) }.compact
|
657
|
+
if errors.size > 0
|
658
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{errors.join(", ")}", response, errors)
|
709
659
|
end
|
710
660
|
end
|
711
661
|
end
|
@@ -723,7 +673,7 @@ module ZuoraAPI
|
|
723
673
|
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", response)
|
724
674
|
elsif error_messages.first.include?("data integrity violation")
|
725
675
|
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
|
726
|
-
end
|
676
|
+
end
|
727
677
|
end
|
728
678
|
end
|
729
679
|
|
@@ -732,128 +682,15 @@ module ZuoraAPI
|
|
732
682
|
end
|
733
683
|
end
|
734
684
|
|
735
|
-
if body.class == Hash && body['message'].present?
|
736
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(body['message'], response) if response.code == 500
|
737
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['message'], response) if ![200,201].include?(response.code)
|
738
|
-
end
|
739
|
-
|
740
|
-
self.errors_via_content_type(response: response, type: :json)
|
741
|
-
|
742
685
|
#All other errors
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
def errors_via_content_type(response: nil, type: :xml)
|
748
|
-
response_content_types = response.headers.transform_keys(&:downcase).fetch('content-type', []).first || ""
|
749
|
-
|
750
|
-
if response_content_types.include?('application/json') && type != :json
|
751
|
-
output_json = JSON.parse(response.body)
|
752
|
-
self.raise_errors(type: :JSON, body: output_json, response: response)
|
753
|
-
|
754
|
-
elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml')) and type != :xml
|
755
|
-
output_xml = Nokogiri::XML(response.body)
|
756
|
-
self.raise_errors(type: :SOAP, body: output_xml, response: response)
|
757
|
-
|
758
|
-
elsif response_content_types.include?('text/html')
|
759
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Akamai Error", response) if response.headers.fetch('server', '') == 'AkamaiGHost'
|
760
|
-
|
761
|
-
parse_body = Nokogiri::HTML(response.body)
|
762
|
-
error_title = parse_body.xpath('//h2').text
|
763
|
-
error_title = parse_body.xpath('//h1').text if error_title.blank?
|
764
|
-
error_message = parse_body.xpath('//p').text
|
765
|
-
|
766
|
-
error_message = error_title if error_message.blank?
|
767
|
-
|
768
|
-
if error_title.present?
|
769
|
-
case error_title
|
770
|
-
when /Service Unavailable/
|
771
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
|
772
|
-
when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
|
773
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
774
|
-
else
|
775
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
776
|
-
end
|
777
|
-
end
|
778
|
-
|
779
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Http response body is missing", response) if response.body.blank?
|
780
|
-
end
|
781
|
-
|
782
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(response.body, response) if response.code == 500
|
783
|
-
end
|
784
|
-
|
785
|
-
|
786
|
-
def get_soap_error_and_message(body)
|
787
|
-
error = body.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text
|
788
|
-
message = body.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
789
|
-
|
790
|
-
if error.blank? || message.blank?
|
791
|
-
error = body.xpath('//faultcode').text
|
792
|
-
message = body.xpath('//faultstring').text
|
793
|
-
end
|
794
|
-
|
795
|
-
if error.blank? || message.blank?
|
796
|
-
error = body.xpath('//ns1:Code', 'ns1' =>'http://api.zuora.com/').text
|
797
|
-
message = body.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text
|
798
|
-
end
|
799
|
-
|
800
|
-
#Update/Create/Delete Calls with multiple requests and responses
|
801
|
-
if body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').size > 0 && body.xpath('//ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
|
802
|
-
error = []
|
803
|
-
success = []
|
804
|
-
body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').each_with_index do |call, object_index|
|
805
|
-
if call.xpath('./ns1:Success', 'ns1' =>'http://api.zuora.com/').text == 'false' && call.xpath('./ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
|
806
|
-
message = "#{call.xpath('./*/ns1:Code', 'ns1' =>'http://api.zuora.com/').text}::#{call.xpath('./*/ns1:Message', 'ns1' =>'http://api.zuora.com/').text}"
|
807
|
-
error.push(message)
|
686
|
+
if ![200,201].include?(response.code)
|
687
|
+
if response.code == 429
|
688
|
+
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)
|
808
689
|
else
|
809
|
-
|
690
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{response.message}", response)
|
810
691
|
end
|
811
692
|
end
|
812
693
|
end
|
813
|
-
return error, success, message
|
814
|
-
end
|
815
|
-
|
816
|
-
def raise_errors_helper(error: nil, message: nil, response: nil, errors: [], success: [])
|
817
|
-
case error
|
818
|
-
when /.*INVALID_SESSION/
|
819
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response, errors, success)
|
820
|
-
when /.*REQUEST_EXCEEDED_LIMIT/
|
821
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new(message, response, errors, success)
|
822
|
-
when /.*LOCK_COMPETITION/
|
823
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(message, response, errors, success)
|
824
|
-
when /.*BATCH_FAIL_ERROR/
|
825
|
-
if message.include?("optimistic locking failed") || message.include?("Operation failed due to a lock competition, please retry later.")
|
826
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(message, response, errors, success)
|
827
|
-
elsif message.include?("org.hibernate.exception.ConstraintViolationException")
|
828
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
|
829
|
-
end
|
830
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
831
|
-
when /.*TEMPORARY_ERROR/, /.*TRANSACTION_TIMEOUT/
|
832
|
-
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(message, response, errors, success)
|
833
|
-
when /.*INVALID_VALUE/
|
834
|
-
if message.include?("data integrity violation")
|
835
|
-
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response, errors), success
|
836
|
-
end
|
837
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
838
|
-
when /.*UNKNOWN_ERROR/
|
839
|
-
if /payment\/refund|Credit Balance Adjustment|Payment Gateway|ARSettlement permission/.match(message).nil?
|
840
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
|
841
|
-
end
|
842
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
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/
|
844
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
845
|
-
when /.*UNEXPECTED_ERROR/
|
846
|
-
raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
|
847
|
-
when /.*soapenv:Server.*/
|
848
|
-
if /^Invalid value.*for type.*|^Id is invalid|^date string can not be less than 19 charactors$/.match(message).present?
|
849
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
850
|
-
elsif /^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
|
851
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
|
852
|
-
end
|
853
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
|
854
|
-
else
|
855
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Z:#{error}::#{message}", response, errors, success)
|
856
|
-
end
|
857
694
|
end
|
858
695
|
|
859
696
|
def aqua_query(queryName: '', query: '', version: '1.2', jobName: 'Aqua',partner: '', project: '')
|
@@ -934,23 +771,15 @@ module ZuoraAPI
|
|
934
771
|
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
|
935
772
|
end
|
936
773
|
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
937
|
-
if tries.zero?
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
end
|
944
|
-
end
|
945
|
-
raise ex
|
774
|
+
if !(tries -= 1).zero?
|
775
|
+
Rails.logger.info("Describe - #{ex.class} Timed out will retry after 5 seconds")
|
776
|
+
sleep(self.timeout_sleep)
|
777
|
+
retry
|
778
|
+
else
|
779
|
+
raise ex
|
946
780
|
end
|
947
|
-
|
948
|
-
tries -= 1
|
949
|
-
sleep(self.timeout_sleep)
|
950
|
-
retry
|
951
781
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
952
|
-
if !tries.zero? && self.status == 'Active'
|
953
|
-
tries -= 1
|
782
|
+
if !(tries -= 1).zero? && self.status == 'Active'
|
954
783
|
Rails.logger.debug("Describe session expired. Starting new session.")
|
955
784
|
self.new_session
|
956
785
|
retry
|
@@ -975,73 +804,50 @@ module ZuoraAPI
|
|
975
804
|
session_type: :basic,
|
976
805
|
timeout_retry: false,
|
977
806
|
timeout: 120,
|
978
|
-
timeout_sleep_interval: self.timeout_sleep,
|
979
807
|
multipart: false,
|
980
|
-
|
981
|
-
output_exception_messages: true,
|
982
|
-
**keyword_args,
|
983
|
-
&block
|
808
|
+
**keyword_args
|
984
809
|
)
|
985
810
|
tries ||= 2
|
986
811
|
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
if z_session
|
991
|
-
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type) }
|
992
|
-
if self.entity_id.present?
|
993
|
-
authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
994
|
-
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
995
|
-
end
|
812
|
+
if self.entity_id.present?
|
813
|
+
headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
814
|
+
headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
996
815
|
end
|
997
816
|
|
817
|
+
raise "Method not supported, supported methods include: :get, :post, :put, :delete, :patch, :head, :options" if ![:get, :post, :put, :delete, :patch, :head, :options].include?(method)
|
818
|
+
|
819
|
+
authentication_headers = z_session ? {"Authorization" => self.get_session(prefix: true, auth_type: session_type) } : {}
|
998
820
|
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
999
821
|
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
stream_body: stream_body
|
1009
|
-
)
|
1010
|
-
|
1011
|
-
response = request.perform(&block)
|
1012
|
-
|
1013
|
-
Rails.logger.debug("Response Code: #{response.code}") if debug
|
1014
|
-
begin
|
1015
|
-
output_json = JSON.parse(response.body)
|
1016
|
-
rescue JSON::ParserError => ex
|
1017
|
-
output_json = {}
|
1018
|
-
end
|
1019
|
-
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
822
|
+
response = HTTParty::Request.new(
|
823
|
+
"Net::HTTP::#{method.to_s.capitalize}".constantize,
|
824
|
+
url,
|
825
|
+
body: body,
|
826
|
+
headers: modified_headers,
|
827
|
+
timeout: timeout,
|
828
|
+
multipart: multipart,
|
829
|
+
).perform
|
1020
830
|
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
831
|
+
Rails.logger.debug("Response Code: #{response.code}") if debug
|
832
|
+
begin
|
833
|
+
output_json = JSON.parse(response.body)
|
834
|
+
rescue JSON::ParserError => ex
|
835
|
+
output_json = {}
|
1025
836
|
end
|
837
|
+
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
838
|
+
|
839
|
+
raise_errors(type: :JSON, body: output_json, response: response)
|
1026
840
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
1027
841
|
if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
|
1028
|
-
session_type
|
1029
|
-
retry
|
842
|
+
self.rest_call(method: method.to_sym, url: url, body: body, debug: debug, errors: errors, z_session: z_session, session_type: :bearer, timeout_retry: timeout_retry, timeout: timeout)
|
1030
843
|
else
|
1031
844
|
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
1032
845
|
raise ex
|
1033
846
|
end
|
1034
847
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
1035
|
-
if !tries.zero? && z_session
|
1036
|
-
tries -= 1
|
848
|
+
if !(tries -= 1).zero? && z_session
|
1037
849
|
Rails.logger.debug("Rest Call - Session Invalid #{session_type}")
|
1038
|
-
|
1039
|
-
begin
|
1040
|
-
self.new_session(auth_type: session_type)
|
1041
|
-
rescue *ZUORA_API_ERRORS => ex
|
1042
|
-
return [output_json, ex.response]
|
1043
|
-
end
|
1044
|
-
|
850
|
+
self.new_session(auth_type: session_type)
|
1045
851
|
retry
|
1046
852
|
else
|
1047
853
|
if errors.include?(ex.class)
|
@@ -1054,46 +860,32 @@ module ZuoraAPI
|
|
1054
860
|
if errors.include?(ex.class)
|
1055
861
|
raise ex
|
1056
862
|
else
|
1057
|
-
response = ex.response unless response
|
1058
863
|
return [output_json, response]
|
1059
864
|
end
|
1060
865
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
1061
866
|
raise ex
|
1062
867
|
rescue *CONNECTION_EXCEPTIONS => ex
|
1063
|
-
if tries.zero?
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
end
|
1070
|
-
end
|
1071
|
-
raise ex
|
868
|
+
if !(tries -= 1).zero?
|
869
|
+
Rails.logger.info("Rest Call - #{ex.class} Timed out will retry after 5 seconds")
|
870
|
+
sleep(self.timeout_sleep)
|
871
|
+
retry
|
872
|
+
else
|
873
|
+
raise ex
|
1072
874
|
end
|
1073
|
-
|
1074
|
-
tries -= 1
|
1075
|
-
sleep(timeout_sleep_interval)
|
1076
|
-
retry
|
1077
875
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
1078
|
-
if !tries.zero?
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
retry
|
1085
|
-
end
|
876
|
+
if !(tries -= 1).zero? && timeout_retry
|
877
|
+
Rails.logger.info("Rest Call - #{ex.class} Timed out will retry after 5 seconds")
|
878
|
+
sleep(self.timeout_sleep)
|
879
|
+
retry
|
880
|
+
else
|
881
|
+
raise ex
|
1086
882
|
end
|
1087
|
-
|
1088
|
-
if
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
1093
|
-
end
|
883
|
+
rescue Errno::ECONNRESET => ex
|
884
|
+
if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
|
885
|
+
retry
|
886
|
+
else
|
887
|
+
raise ex
|
1094
888
|
end
|
1095
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
1096
|
-
raise ex
|
1097
889
|
rescue => ex
|
1098
890
|
raise ex
|
1099
891
|
else
|
@@ -1146,11 +938,9 @@ module ZuoraAPI
|
|
1146
938
|
return products, catalog_map
|
1147
939
|
end
|
1148
940
|
|
1149
|
-
def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil,
|
941
|
+
def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: 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)
|
1150
942
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
1151
943
|
|
1152
|
-
retry_count ||= timeout_retries
|
1153
|
-
|
1154
944
|
#Make sure directory exists
|
1155
945
|
require 'fileutils'
|
1156
946
|
FileUtils.mkdir_p(file_path) unless File.exists?(file_path)
|
@@ -1165,9 +955,8 @@ module ZuoraAPI
|
|
1165
955
|
headers = headers.merge({"Zuora-Entity-Ids" => self.entity_id}) if !self.entity_id.blank?
|
1166
956
|
end
|
1167
957
|
|
1168
|
-
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
1169
|
-
|
1170
958
|
response_save = nil
|
959
|
+
retry_count ||= timeout_retries
|
1171
960
|
http.request_get(uri.request_uri, headers) do |response|
|
1172
961
|
response_save = response
|
1173
962
|
status_code = response.code if response
|
@@ -1261,11 +1050,11 @@ module ZuoraAPI
|
|
1261
1050
|
raise
|
1262
1051
|
end
|
1263
1052
|
else
|
1264
|
-
raise
|
1053
|
+
raise StandardError.new("File Download Failed #{response.class}")
|
1265
1054
|
end
|
1266
1055
|
end
|
1267
|
-
|
1268
|
-
rescue => ex
|
1056
|
+
|
1057
|
+
rescue => ex
|
1269
1058
|
sleep(5)
|
1270
1059
|
if (retry_count -= 1) >= 0
|
1271
1060
|
retry
|
@@ -1275,122 +1064,75 @@ module ZuoraAPI
|
|
1275
1064
|
end
|
1276
1065
|
end
|
1277
1066
|
|
1278
|
-
def getDataSourceExport(query, extract: true, encrypted: false, zip: true
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
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
|
1067
|
+
def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
|
1068
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
1069
|
+
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
|
1070
|
+
xml['SOAP-ENV'].Header do
|
1071
|
+
xml['ns1'].SessionHeader do
|
1072
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
|
1287
1073
|
end
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1074
|
+
end
|
1075
|
+
xml['SOAP-ENV'].Body do
|
1076
|
+
xml['ns1'].create do
|
1077
|
+
xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
|
1078
|
+
xml['ns2'].Format 'csv'
|
1079
|
+
xml['ns2'].Zip zip
|
1080
|
+
xml['ns2'].Name 'googman'
|
1081
|
+
xml['ns2'].Query query
|
1082
|
+
xml['ns2'].Encrypted encrypted
|
1297
1083
|
end
|
1298
1084
|
end
|
1299
1085
|
end
|
1300
1086
|
end
|
1087
|
+
end
|
1301
1088
|
|
1302
|
-
|
1089
|
+
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)
|
1303
1090
|
|
1304
|
-
|
1305
|
-
|
1091
|
+
output_xml = Nokogiri::XML(response_query.body)
|
1092
|
+
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"
|
1093
|
+
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
1306
1094
|
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
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
|
1095
|
+
confirmRequest = Nokogiri::XML::Builder.new do |xml|
|
1096
|
+
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
|
1097
|
+
xml['SOAP-ENV'].Header do
|
1098
|
+
xml['ns1'].SessionHeader do
|
1099
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
|
1317
1100
|
end
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1101
|
+
end
|
1102
|
+
xml['SOAP-ENV'].Body do
|
1103
|
+
xml['ns1'].query do
|
1104
|
+
xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
|
1322
1105
|
end
|
1323
1106
|
end
|
1324
1107
|
end
|
1325
|
-
|
1326
|
-
|
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)
|
1330
|
-
|
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
|
1334
|
-
|
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
|
1338
|
-
|
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
|
1363
|
-
|
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
|
1108
|
+
end
|
1109
|
+
result = 'Waiting'
|
1372
1110
|
|
1373
|
-
|
1374
|
-
|
1111
|
+
while result != "Completed"
|
1112
|
+
sleep 3
|
1113
|
+
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)
|
1375
1114
|
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
else
|
1382
|
-
raise ex
|
1383
|
-
end
|
1384
|
-
|
1385
|
-
rescue Errno::ECONNRESET => ex
|
1386
|
-
if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
|
1387
|
-
retry
|
1388
|
-
else
|
1389
|
-
raise ex
|
1390
|
-
end
|
1115
|
+
output_xml = Nokogiri::XML(response_query.body)
|
1116
|
+
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
1117
|
+
status_code = response_query.code if response_query
|
1118
|
+
raise "Export Creation Unsuccessful : #{output_xml.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text}" if result.blank? || result == "Failed"
|
1119
|
+
end
|
1391
1120
|
|
1392
|
-
|
1393
|
-
|
1121
|
+
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
1122
|
+
export_file = get_file(:url => self.fileURL(file_id))
|
1123
|
+
export_file_path = export_file.path
|
1124
|
+
Rails.logger.debug("=====> Export path #{export_file.path}")
|
1125
|
+
|
1126
|
+
if extract && zip
|
1127
|
+
require "zip"
|
1128
|
+
new_path = export_file_path.partition('.zip').first
|
1129
|
+
zipped = Zip::File.open(export_file_path)
|
1130
|
+
file_handle = zipped.entries.first
|
1131
|
+
file_handle.extract(new_path)
|
1132
|
+
File.delete(export_file_path)
|
1133
|
+
return new_path
|
1134
|
+
else
|
1135
|
+
return export_file_path
|
1394
1136
|
end
|
1395
1137
|
end
|
1396
1138
|
|
@@ -1457,17 +1199,5 @@ module ZuoraAPI
|
|
1457
1199
|
end
|
1458
1200
|
return "failure"
|
1459
1201
|
end
|
1460
|
-
|
1461
|
-
def reset_files(body)
|
1462
|
-
return unless body.is_a? Hash
|
1463
|
-
|
1464
|
-
body.transform_values! do |v|
|
1465
|
-
if v.is_a?(File)
|
1466
|
-
v.reopen(v.path)
|
1467
|
-
else
|
1468
|
-
v
|
1469
|
-
end
|
1470
|
-
end
|
1471
|
-
end
|
1472
1202
|
end
|
1473
1203
|
end
|