zuora_api 1.7.65 → 1.7.66g
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 +2 -1
- data/Gemfile +1 -1
- data/lib/zuora_api/exceptions.rb +19 -4
- data/lib/zuora_api/login.rb +350 -206
- data/lib/zuora_api/logins/basic.rb +10 -101
- data/lib/zuora_api/logins/oauth.rb +24 -90
- data/lib/zuora_api/version.rb +1 -1
- data/zuora_api.gemspec +3 -2
- metadata +24 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dd393a41c8c3cf0854d5ac12b6ad87c2b2563f9347b0f4124e1ad3fbfb477df9
|
|
4
|
+
data.tar.gz: 6638cdbc20f485a18a94f9808f72e263605ec28d937a86950774d43638ad9334
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 05b50f2f78772ca52b9649131c1ff43d8b1909cb6fc5dc4074be9699ff9baa42c9d49131e4c5120b826e048e4a72ee65d056431f9efabc8071717e8183ff1d0a
|
|
7
|
+
data.tar.gz: dc4f45572be1b44ad33d7941a271368436bc034e894d7d483a6f590bea6eec128d5c50146f1101a2ceadd57c41be8322fe60aac6c099f7fc7fd3b5a4dc2d3253
|
data/.gitlab-ci.yml
CHANGED
data/Gemfile
CHANGED
data/lib/zuora_api/exceptions.rb
CHANGED
|
@@ -40,6 +40,19 @@ 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
|
|
43
56
|
end
|
|
44
57
|
|
|
45
58
|
class BadEntityError < Error
|
|
@@ -177,14 +190,15 @@ module ZuoraAPI
|
|
|
177
190
|
end
|
|
178
191
|
|
|
179
192
|
class ZuoraAPITemporaryError < Error
|
|
180
|
-
attr_reader :code, :response
|
|
193
|
+
attr_reader :code, :response, :errors
|
|
181
194
|
attr_writer :default_message
|
|
182
195
|
|
|
183
|
-
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
196
|
+
def initialize(message = nil, response = nil, errors = [], successes = [], *args)
|
|
184
197
|
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
185
198
|
@message = parse_message(message)
|
|
186
199
|
@response = response
|
|
187
200
|
@default_message = "There is a temporary error with zuora system."
|
|
201
|
+
@errors = errors
|
|
188
202
|
end
|
|
189
203
|
|
|
190
204
|
def to_s
|
|
@@ -225,13 +239,14 @@ module ZuoraAPI
|
|
|
225
239
|
end
|
|
226
240
|
|
|
227
241
|
class ZuoraAPIReadTimeout < Net::ReadTimeout
|
|
228
|
-
attr_reader :code, :response
|
|
242
|
+
attr_reader :code, :response, :request
|
|
229
243
|
attr_writer :default_message
|
|
230
244
|
|
|
231
|
-
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
245
|
+
def initialize(message = nil, response = nil, request = nil, errors = [], successes = [], *args)
|
|
232
246
|
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
233
247
|
@message = message
|
|
234
248
|
@response = response
|
|
249
|
+
@request = request
|
|
235
250
|
@default_message = "Authentication type is not supported by this Login"
|
|
236
251
|
end
|
|
237
252
|
|
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
|
|
|
@@ -374,8 +374,8 @@ module ZuoraAPI
|
|
|
374
374
|
return domain ? endpoint.concat(prefix).concat(url) : prefix.concat(url)
|
|
375
375
|
end
|
|
376
376
|
|
|
377
|
-
def rest_domain
|
|
378
|
-
return URI(
|
|
377
|
+
def rest_domain(endpoint: self.rest_endpoint)
|
|
378
|
+
return URI(endpoint).host
|
|
379
379
|
end
|
|
380
380
|
|
|
381
381
|
def fileURL(url="")
|
|
@@ -387,10 +387,41 @@ module ZuoraAPI
|
|
|
387
387
|
end
|
|
388
388
|
|
|
389
389
|
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
|
+
|
|
390
422
|
end
|
|
391
423
|
|
|
392
424
|
def get_session(prefix: false, auth_type: :basic, zuora_track_id: nil)
|
|
393
|
-
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}") if Rails.env.to_s == 'development'
|
|
394
425
|
case auth_type
|
|
395
426
|
when :basic
|
|
396
427
|
if self.current_session.blank?
|
|
@@ -399,14 +430,13 @@ module ZuoraAPI
|
|
|
399
430
|
if self.bearer_token.blank? || self.oauth_expired?
|
|
400
431
|
self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id)
|
|
401
432
|
end
|
|
402
|
-
self.get_z_session(zuora_track_id: zuora_track_id)
|
|
433
|
+
self.get_z_session(zuora_track_id: zuora_track_id)
|
|
403
434
|
when 'ZuoraAPI::Basic'
|
|
404
435
|
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
405
436
|
else
|
|
406
437
|
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
407
438
|
end
|
|
408
439
|
end
|
|
409
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
|
410
440
|
return prefix ? "ZSession #{self.current_session}" : self.current_session.to_s
|
|
411
441
|
when :bearer
|
|
412
442
|
case self.class.to_s
|
|
@@ -419,8 +449,6 @@ module ZuoraAPI
|
|
|
419
449
|
else
|
|
420
450
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Unknown Login, does not support Authentication of Type: #{auth_type}")
|
|
421
451
|
end
|
|
422
|
-
|
|
423
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
|
424
452
|
return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
|
|
425
453
|
end
|
|
426
454
|
end
|
|
@@ -428,16 +456,18 @@ module ZuoraAPI
|
|
|
428
456
|
def soap_call(
|
|
429
457
|
ns1: 'ns1',
|
|
430
458
|
ns2: 'ns2',
|
|
431
|
-
batch_size: nil,
|
|
459
|
+
batch_size: nil,
|
|
460
|
+
headers: {},
|
|
432
461
|
single_transaction: false,
|
|
433
462
|
debug: false,
|
|
434
463
|
zuora_track_id: nil,
|
|
435
464
|
errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
|
|
436
465
|
z_session: true,
|
|
437
466
|
timeout_retry: false,
|
|
438
|
-
timeout:
|
|
467
|
+
timeout: 130,
|
|
439
468
|
timeout_sleep_interval: self.timeout_sleep,
|
|
440
469
|
output_exception_messages: true,
|
|
470
|
+
skip_session: false,
|
|
441
471
|
**keyword_args)
|
|
442
472
|
tries ||= 2
|
|
443
473
|
xml = Nokogiri::XML::Builder.new do |xml|
|
|
@@ -447,8 +477,10 @@ module ZuoraAPI
|
|
|
447
477
|
'xmlns:api' => "http://api.zuora.com/",
|
|
448
478
|
"xmlns:#{ns1}" => "http://api.zuora.com/") do
|
|
449
479
|
xml['SOAP-ENV'].Header do
|
|
450
|
-
|
|
451
|
-
xml["#{ns1}"].
|
|
480
|
+
if !skip_session
|
|
481
|
+
xml["#{ns1}"].SessionHeader do
|
|
482
|
+
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
483
|
+
end
|
|
452
484
|
end
|
|
453
485
|
if single_transaction
|
|
454
486
|
xml["#{ns1}"].CallOptions do
|
|
@@ -466,25 +498,32 @@ module ZuoraAPI
|
|
|
466
498
|
end
|
|
467
499
|
end
|
|
468
500
|
end
|
|
469
|
-
|
|
470
501
|
input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
|
471
502
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
|
472
503
|
Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
473
504
|
|
|
474
|
-
headers
|
|
505
|
+
headers.merge!({ 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'})
|
|
475
506
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
476
507
|
|
|
477
|
-
|
|
508
|
+
request = HTTParty::Request.new(
|
|
509
|
+
Net::HTTP::Post,
|
|
478
510
|
self.url,
|
|
479
|
-
:
|
|
480
|
-
:
|
|
481
|
-
:
|
|
511
|
+
body: xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip,
|
|
512
|
+
headers: headers,
|
|
513
|
+
timeout: timeout,
|
|
482
514
|
)
|
|
515
|
+
|
|
516
|
+
response = request.perform
|
|
517
|
+
|
|
483
518
|
output_xml = Nokogiri::XML(response.body)
|
|
484
519
|
Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
485
520
|
|
|
486
521
|
raise_errors(type: :SOAP, body: output_xml, response: response)
|
|
522
|
+
|
|
523
|
+
return output_xml, input_xml, response
|
|
524
|
+
|
|
487
525
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
526
|
+
raise if skip_session
|
|
488
527
|
if !tries.zero? && z_session
|
|
489
528
|
tries -= 1
|
|
490
529
|
Rails.logger.debug("SOAP Call - Session Invalid")
|
|
@@ -496,89 +535,144 @@ module ZuoraAPI
|
|
|
496
535
|
end
|
|
497
536
|
|
|
498
537
|
retry
|
|
499
|
-
else
|
|
500
|
-
if errors.include?(ex.class)
|
|
501
|
-
raise ex
|
|
502
|
-
else
|
|
503
|
-
return output_xml, input_xml, response
|
|
504
|
-
end
|
|
505
538
|
end
|
|
539
|
+
|
|
540
|
+
raise ex if errors.include?(ex.class)
|
|
541
|
+
|
|
542
|
+
return output_xml, input_xml, response
|
|
543
|
+
|
|
506
544
|
rescue *ZUORA_API_ERRORS => ex
|
|
507
|
-
if errors.include?(ex.class)
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
end
|
|
545
|
+
raise ex if errors.include?(ex.class)
|
|
546
|
+
|
|
547
|
+
response = ex.response unless response
|
|
548
|
+
return output_xml, input_xml, response
|
|
549
|
+
|
|
513
550
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
514
|
-
if tries.zero?
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
520
|
-
end
|
|
521
|
-
end
|
|
522
|
-
raise ex
|
|
551
|
+
if !tries.zero?
|
|
552
|
+
tries -= 1
|
|
553
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
554
|
+
sleep(timeout_sleep_interval)
|
|
555
|
+
retry
|
|
523
556
|
end
|
|
524
557
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
558
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
559
|
+
raise ex
|
|
560
|
+
|
|
528
561
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
529
|
-
if tries.zero?
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
562
|
+
if !tries.zero?
|
|
563
|
+
tries -= 1
|
|
564
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
565
|
+
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
566
|
+
retry
|
|
567
|
+
elsif timeout_retry
|
|
568
|
+
sleep(timeout_sleep_interval)
|
|
569
|
+
retry
|
|
536
570
|
end
|
|
537
|
-
raise ex
|
|
538
571
|
end
|
|
539
572
|
|
|
540
|
-
|
|
573
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
574
|
+
ex = ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
575
|
+
raise ex
|
|
541
576
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
577
|
+
rescue => ex
|
|
578
|
+
raise ex
|
|
579
|
+
ensure
|
|
580
|
+
self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
|
|
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)
|
|
547
601
|
else
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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, k.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, k.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?
|
|
556
641
|
end
|
|
557
642
|
rescue => ex
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
return
|
|
643
|
+
Rails.logger.error("Failed to create exception arguments", ex, args)
|
|
644
|
+
ensure
|
|
645
|
+
return args
|
|
561
646
|
end
|
|
562
647
|
|
|
563
648
|
def raise_errors(type: :SOAP, body: nil, response: nil)
|
|
564
|
-
|
|
565
|
-
|
|
649
|
+
request_uri, request_path, match_string = "", "", ""
|
|
650
|
+
if response.class.to_s == "HTTP::Message"
|
|
651
|
+
request_uri = response.http_header.request_uri.to_s
|
|
652
|
+
request_path = response.http_header.request_uri.path
|
|
653
|
+
match_string = "#{response.http_header.request_method}::#{response.code}::#{request_uri}"
|
|
654
|
+
else
|
|
655
|
+
request = response.request
|
|
656
|
+
request_uri = response.request.uri
|
|
657
|
+
request_path = request.path.path
|
|
658
|
+
match_string = "#{request.http_method.to_s.split("Net::HTTP::").last.upcase}::#{response.code}::#{request_path}"
|
|
659
|
+
end
|
|
566
660
|
|
|
567
661
|
if [502,503].include?(response.code)
|
|
568
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from
|
|
662
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from 'https://#{rest_domain(endpoint: request_uri)}'", response)
|
|
569
663
|
end
|
|
570
664
|
|
|
571
665
|
# Check failure response code
|
|
572
666
|
case response.code
|
|
573
667
|
when 504
|
|
574
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from
|
|
668
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response)
|
|
575
669
|
when 429
|
|
576
670
|
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)
|
|
577
671
|
when 401
|
|
578
672
|
|
|
579
673
|
else
|
|
580
674
|
if body.class == Hash
|
|
581
|
-
case
|
|
675
|
+
case request_path
|
|
582
676
|
when /^\/v1\/connections$/
|
|
583
677
|
response_headers = response.headers.to_h
|
|
584
678
|
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing cookies for authentication call", response) if response_headers['set-cookie'].blank?
|
|
@@ -592,6 +686,10 @@ module ZuoraAPI
|
|
|
592
686
|
when :SOAP
|
|
593
687
|
error, success, message = get_soap_error_and_message(body)
|
|
594
688
|
|
|
689
|
+
if body.xpath('//fns:LoginFault', 'fns' =>'http://fault.api.zuora.com/').present?
|
|
690
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response)
|
|
691
|
+
end
|
|
692
|
+
|
|
595
693
|
if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
|
|
596
694
|
body.xpath(
|
|
597
695
|
'//ns1:records[@xsi:type="ns2:Export"]',
|
|
@@ -602,7 +700,7 @@ module ZuoraAPI
|
|
|
602
700
|
reason = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
|
|
603
701
|
if reason.present?
|
|
604
702
|
message = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
|
|
605
|
-
error = message.match(/^[\w\d]{16}\: (Unexpected error.|No HTTP Response)/).present? ? 'UNEXPECTED_ERROR' : 'FATAL_ERROR'
|
|
703
|
+
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'
|
|
606
704
|
else
|
|
607
705
|
error = 'FATAL_ERROR'
|
|
608
706
|
message = 'Export failed due to unknown reason. Consult api logs.'
|
|
@@ -624,23 +722,10 @@ module ZuoraAPI
|
|
|
624
722
|
end
|
|
625
723
|
end
|
|
626
724
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
elsif response.code == 500
|
|
630
|
-
if response.headers.fetch('content-type', []).include?('application/json')
|
|
631
|
-
begin
|
|
632
|
-
output_json = JSON.parse(response.body)
|
|
633
|
-
self.raise_errors(type: :JSON, body: output_json, response: response)
|
|
634
|
-
rescue JSON::ParserError => ex
|
|
635
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(response.body, response)
|
|
636
|
-
end
|
|
637
|
-
else
|
|
638
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(response.body, response)
|
|
639
|
-
end
|
|
640
|
-
end
|
|
641
|
-
|
|
725
|
+
self.errors_via_content_type(response: response, type: :xml)
|
|
726
|
+
|
|
642
727
|
when :JSON
|
|
643
|
-
case
|
|
728
|
+
case request_path
|
|
644
729
|
when /^\/query\/jobs.*/ #DataQuery Paths
|
|
645
730
|
return if body.class != Hash
|
|
646
731
|
case match_string
|
|
@@ -660,12 +745,16 @@ module ZuoraAPI
|
|
|
660
745
|
if reporting_message&.include?("com.zuora.rest.RestUsageException: The user does not have permissions for this API.")
|
|
661
746
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response)
|
|
662
747
|
elsif reporting_message&.include?("500 Internal Server Error")
|
|
663
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Internal Server Error. The Reporting API is down. Contact Support.")
|
|
748
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Internal Server Error. The Reporting API is down. Contact Support.", response)
|
|
664
749
|
end
|
|
665
750
|
case match_string
|
|
666
751
|
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.
|
|
667
752
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
|
|
668
753
|
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
|
|
669
758
|
end
|
|
670
759
|
|
|
671
760
|
body = body.dig("results").present? ? body["results"] : body if body.class == Hash
|
|
@@ -705,7 +794,11 @@ module ZuoraAPI
|
|
|
705
794
|
end
|
|
706
795
|
|
|
707
796
|
if body['error'] == 'Unauthorized' && body['status'] == 401
|
|
708
|
-
|
|
797
|
+
if body['message'].present?
|
|
798
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(body['message'], response)
|
|
799
|
+
else
|
|
800
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
|
|
801
|
+
end
|
|
709
802
|
end
|
|
710
803
|
#Authentication failed
|
|
711
804
|
if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
|
|
@@ -726,7 +819,6 @@ module ZuoraAPI
|
|
|
726
819
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
|
|
727
820
|
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
|
|
728
821
|
end
|
|
729
|
-
|
|
730
822
|
#Internal Server Error
|
|
731
823
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(60)
|
|
732
824
|
if messages_array.uniq.size == 1
|
|
@@ -737,6 +829,11 @@ module ZuoraAPI
|
|
|
737
829
|
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("#{messages_array.join(', ')}", response)
|
|
738
830
|
end
|
|
739
831
|
|
|
832
|
+
#Retryiable Service Error
|
|
833
|
+
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(61)
|
|
834
|
+
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{messages_array.join(', ')}", response)
|
|
835
|
+
end
|
|
836
|
+
|
|
740
837
|
#Request exceeded limit
|
|
741
838
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70)
|
|
742
839
|
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", response)
|
|
@@ -789,26 +886,56 @@ module ZuoraAPI
|
|
|
789
886
|
end
|
|
790
887
|
end
|
|
791
888
|
|
|
889
|
+
if body.class == Hash && body['message'].present?
|
|
890
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(body['message'], response) if response.code == 500
|
|
891
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['message'], response) if ![200,201].include?(response.code)
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
self.errors_via_content_type(response: response, type: :json)
|
|
895
|
+
|
|
792
896
|
#All other errors
|
|
793
|
-
if response.code
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
897
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(response.body, response) if ![200,201].include?(response.code)
|
|
898
|
+
end
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
def errors_via_content_type(response: nil, type: :xml)
|
|
902
|
+
response_content_types = response.headers.transform_keys(&:downcase).fetch('content-type', []).first || ""
|
|
903
|
+
|
|
904
|
+
if response_content_types.include?('application/json') && type != :json
|
|
905
|
+
output_json = JSON.parse(response.body)
|
|
906
|
+
self.raise_errors(type: :JSON, body: output_json, response: response)
|
|
907
|
+
|
|
908
|
+
elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml')) and type != :xml
|
|
909
|
+
output_xml = Nokogiri::XML(response.body)
|
|
910
|
+
self.raise_errors(type: :SOAP, body: output_xml, response: response)
|
|
911
|
+
|
|
912
|
+
elsif response_content_types.include?('text/html')
|
|
913
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Akamai Error", response) if response.headers.fetch('server', '') == 'AkamaiGHost'
|
|
914
|
+
|
|
915
|
+
parse_body = Nokogiri::HTML(response.body)
|
|
916
|
+
error_title = parse_body.xpath('//h2').text
|
|
917
|
+
error_title = parse_body.xpath('//h1').text if error_title.blank?
|
|
918
|
+
error_message = parse_body.xpath('//p').text
|
|
919
|
+
|
|
920
|
+
error_message = error_title if error_message.blank?
|
|
921
|
+
|
|
922
|
+
if error_title.present?
|
|
923
|
+
case error_title
|
|
924
|
+
when /Service Unavailable/
|
|
925
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
|
|
926
|
+
when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
|
|
927
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
928
|
+
else
|
|
929
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
808
930
|
end
|
|
809
931
|
end
|
|
932
|
+
|
|
933
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Http response body is missing", response) if response.body.blank?
|
|
810
934
|
end
|
|
935
|
+
|
|
936
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(response.body, response) if response.code == 500
|
|
811
937
|
end
|
|
938
|
+
|
|
812
939
|
|
|
813
940
|
def get_soap_error_and_message(body)
|
|
814
941
|
error = body.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text
|
|
@@ -872,9 +999,9 @@ module ZuoraAPI
|
|
|
872
999
|
when /.*UNEXPECTED_ERROR/
|
|
873
1000
|
raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
|
|
874
1001
|
when /.*soapenv:Server.*/
|
|
875
|
-
if /^Invalid value.*for type.*|^Id is invalid
|
|
1002
|
+
if /^Invalid value.*for type.*|^Id is invalid|^date string can not be less than 19 charactors$/.match(message).present?
|
|
876
1003
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
877
|
-
elsif /^Invalid white space character \(.*\) in text to output$/.match(message).present?
|
|
1004
|
+
elsif /^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
|
|
878
1005
|
raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
|
|
879
1006
|
end
|
|
880
1007
|
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
|
|
@@ -927,7 +1054,7 @@ module ZuoraAPI
|
|
|
927
1054
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
|
928
1055
|
url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
|
|
929
1056
|
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"}
|
|
930
|
-
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout =>
|
|
1057
|
+
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 130)
|
|
931
1058
|
|
|
932
1059
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
|
|
933
1060
|
|
|
@@ -960,35 +1087,31 @@ module ZuoraAPI
|
|
|
960
1087
|
end
|
|
961
1088
|
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
|
|
962
1089
|
end
|
|
1090
|
+
|
|
1091
|
+
return des_hash
|
|
963
1092
|
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
964
|
-
if tries.zero?
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
Rails.logger.error("Describe - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
|
|
970
|
-
end
|
|
971
|
-
end
|
|
972
|
-
raise ex
|
|
1093
|
+
if !tries.zero?
|
|
1094
|
+
tries -= 1
|
|
1095
|
+
self.log(location: "Describe", exception: ex, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :debug)
|
|
1096
|
+
sleep(self.timeout_sleep)
|
|
1097
|
+
retry
|
|
973
1098
|
end
|
|
974
1099
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1100
|
+
self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors
|
|
1101
|
+
raise ex
|
|
1102
|
+
|
|
978
1103
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
979
1104
|
if !tries.zero? && self.status == 'Active'
|
|
980
1105
|
tries -= 1
|
|
981
1106
|
Rails.logger.debug("Describe session expired. Starting new session.")
|
|
982
1107
|
self.new_session
|
|
983
1108
|
retry
|
|
984
|
-
else
|
|
985
|
-
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
986
|
-
raise ex
|
|
987
1109
|
end
|
|
1110
|
+
|
|
1111
|
+
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1112
|
+
raise ex
|
|
988
1113
|
rescue => ex
|
|
989
1114
|
raise ex
|
|
990
|
-
else
|
|
991
|
-
return des_hash
|
|
992
1115
|
end
|
|
993
1116
|
|
|
994
1117
|
def rest_call(
|
|
@@ -1001,11 +1124,12 @@ module ZuoraAPI
|
|
|
1001
1124
|
z_session: true,
|
|
1002
1125
|
session_type: :basic,
|
|
1003
1126
|
timeout_retry: false,
|
|
1004
|
-
timeout:
|
|
1127
|
+
timeout: 130,
|
|
1005
1128
|
timeout_sleep_interval: self.timeout_sleep,
|
|
1006
1129
|
multipart: false,
|
|
1007
1130
|
stream_body: false,
|
|
1008
1131
|
output_exception_messages: true,
|
|
1132
|
+
zuora_track_id: nil,
|
|
1009
1133
|
**keyword_args,
|
|
1010
1134
|
&block
|
|
1011
1135
|
)
|
|
@@ -1015,17 +1139,18 @@ module ZuoraAPI
|
|
|
1015
1139
|
|
|
1016
1140
|
authentication_headers = {}
|
|
1017
1141
|
if z_session
|
|
1018
|
-
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type) }
|
|
1142
|
+
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type, zuora_track_id: zuora_track_id) }
|
|
1019
1143
|
if self.entity_id.present?
|
|
1020
1144
|
authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
|
1021
1145
|
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
|
1022
1146
|
end
|
|
1023
1147
|
end
|
|
1148
|
+
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
1024
1149
|
|
|
1025
1150
|
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
|
1026
1151
|
|
|
1027
1152
|
begin
|
|
1028
|
-
|
|
1153
|
+
request = HTTParty::Request.new(
|
|
1029
1154
|
"Net::HTTP::#{method.to_s.capitalize}".constantize,
|
|
1030
1155
|
url,
|
|
1031
1156
|
body: body,
|
|
@@ -1033,7 +1158,9 @@ module ZuoraAPI
|
|
|
1033
1158
|
timeout: timeout,
|
|
1034
1159
|
multipart: multipart,
|
|
1035
1160
|
stream_body: stream_body
|
|
1036
|
-
)
|
|
1161
|
+
)
|
|
1162
|
+
|
|
1163
|
+
response = request.perform(&block)
|
|
1037
1164
|
|
|
1038
1165
|
Rails.logger.debug("Response Code: #{response.code}") if debug
|
|
1039
1166
|
begin
|
|
@@ -1044,18 +1171,20 @@ module ZuoraAPI
|
|
|
1044
1171
|
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
|
1045
1172
|
|
|
1046
1173
|
raise_errors(type: :JSON, body: output_json, response: response)
|
|
1047
|
-
rescue
|
|
1174
|
+
rescue => ex
|
|
1048
1175
|
reset_files(body) if multipart
|
|
1049
1176
|
raise
|
|
1050
1177
|
end
|
|
1178
|
+
|
|
1179
|
+
return [output_json, response]
|
|
1051
1180
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
|
1052
1181
|
if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
|
|
1053
1182
|
session_type = :bearer
|
|
1054
1183
|
retry
|
|
1055
|
-
else
|
|
1056
|
-
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
|
1057
|
-
raise ex
|
|
1058
1184
|
end
|
|
1185
|
+
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
|
1186
|
+
raise ex
|
|
1187
|
+
|
|
1059
1188
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1060
1189
|
if !tries.zero? && z_session
|
|
1061
1190
|
tries -= 1
|
|
@@ -1068,70 +1197,51 @@ module ZuoraAPI
|
|
|
1068
1197
|
end
|
|
1069
1198
|
|
|
1070
1199
|
retry
|
|
1071
|
-
else
|
|
1072
|
-
if errors.include?(ex.class)
|
|
1073
|
-
raise ex
|
|
1074
|
-
else
|
|
1075
|
-
return [output_json, response]
|
|
1076
|
-
end
|
|
1077
1200
|
end
|
|
1201
|
+
|
|
1202
|
+
raise ex if errors.include?(ex.class)
|
|
1203
|
+
return [output_json, response]
|
|
1204
|
+
|
|
1078
1205
|
rescue *ZUORA_API_ERRORS => ex
|
|
1079
|
-
if errors.include?(ex.class)
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
end
|
|
1206
|
+
raise ex if errors.include?(ex.class)
|
|
1207
|
+
|
|
1208
|
+
response = ex.response unless response
|
|
1209
|
+
return [output_json, response]
|
|
1210
|
+
|
|
1085
1211
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1086
1212
|
raise ex
|
|
1087
1213
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
1088
|
-
if tries.zero?
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1094
|
-
end
|
|
1095
|
-
end
|
|
1096
|
-
raise ex
|
|
1214
|
+
if !tries.zero?
|
|
1215
|
+
tries -= 1
|
|
1216
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
1217
|
+
sleep(timeout_sleep_interval)
|
|
1218
|
+
retry
|
|
1097
1219
|
end
|
|
1098
1220
|
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1221
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
1222
|
+
raise ex
|
|
1223
|
+
|
|
1102
1224
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
1103
|
-
if tries.zero?
|
|
1104
|
-
if output_exception_messages
|
|
1105
|
-
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
1106
|
-
Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
1107
|
-
else
|
|
1108
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1109
|
-
end
|
|
1110
|
-
end
|
|
1111
|
-
raise ex
|
|
1112
|
-
end
|
|
1113
|
-
|
|
1114
|
-
tries -= 1
|
|
1115
1225
|
|
|
1116
|
-
if
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
1125
|
-
else
|
|
1126
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1127
|
-
end
|
|
1226
|
+
if !tries.zero?
|
|
1227
|
+
tries -= 1
|
|
1228
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
1229
|
+
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
1230
|
+
retry
|
|
1231
|
+
elsif timeout_retry
|
|
1232
|
+
sleep(timeout_sleep_interval)
|
|
1233
|
+
retry
|
|
1128
1234
|
end
|
|
1129
|
-
raise ex
|
|
1130
1235
|
end
|
|
1236
|
+
|
|
1237
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
1238
|
+
ex = ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
1239
|
+
raise ex
|
|
1240
|
+
|
|
1131
1241
|
rescue => ex
|
|
1132
1242
|
raise ex
|
|
1133
|
-
|
|
1134
|
-
|
|
1243
|
+
ensure
|
|
1244
|
+
self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
|
|
1135
1245
|
end
|
|
1136
1246
|
|
|
1137
1247
|
def update_create_tenant
|
|
@@ -1153,8 +1263,9 @@ module ZuoraAPI
|
|
|
1153
1263
|
while !response["nextPage"].blank?
|
|
1154
1264
|
url = self.rest_endpoint(response["nextPage"].split('/v1/').last)
|
|
1155
1265
|
Rails.logger.debug("Fetch Catalog URL #{url}")
|
|
1156
|
-
output_json, response = self.rest_call(:
|
|
1157
|
-
|
|
1266
|
+
output_json, response = self.rest_call(debug: false, url: url, timeout_retry: true)
|
|
1267
|
+
|
|
1268
|
+
if !/(true|t|yes|y|1)$/.match(output_json['success'].to_s) || output_json['success'].class != TrueClass
|
|
1158
1269
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
|
|
1159
1270
|
end
|
|
1160
1271
|
output_json["products"].each do |product|
|
|
@@ -1180,9 +1291,11 @@ module ZuoraAPI
|
|
|
1180
1291
|
return products, catalog_map
|
|
1181
1292
|
end
|
|
1182
1293
|
|
|
1183
|
-
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:
|
|
1294
|
+
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: 130, session_type: :basic, **execute_params)
|
|
1184
1295
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
|
1185
1296
|
|
|
1297
|
+
retry_count ||= timeout_retries
|
|
1298
|
+
|
|
1186
1299
|
#Make sure directory exists
|
|
1187
1300
|
require 'fileutils'
|
|
1188
1301
|
FileUtils.mkdir_p(file_path) unless File.exists?(file_path)
|
|
@@ -1200,7 +1313,6 @@ module ZuoraAPI
|
|
|
1200
1313
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
1201
1314
|
|
|
1202
1315
|
response_save = nil
|
|
1203
|
-
retry_count ||= timeout_retries
|
|
1204
1316
|
http.request_get(uri.request_uri, headers) do |response|
|
|
1205
1317
|
response_save = response
|
|
1206
1318
|
status_code = response.code if response
|
|
@@ -1287,12 +1399,10 @@ module ZuoraAPI
|
|
|
1287
1399
|
if !(retry_count -= 1).zero?
|
|
1288
1400
|
self.new_session
|
|
1289
1401
|
raise response.class
|
|
1290
|
-
else
|
|
1291
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1292
1402
|
end
|
|
1293
|
-
|
|
1294
|
-
raise
|
|
1403
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1295
1404
|
end
|
|
1405
|
+
raise
|
|
1296
1406
|
else
|
|
1297
1407
|
raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
|
|
1298
1408
|
end
|
|
@@ -1302,18 +1412,18 @@ module ZuoraAPI
|
|
|
1302
1412
|
sleep(5)
|
|
1303
1413
|
if (retry_count -= 1) >= 0
|
|
1304
1414
|
retry
|
|
1305
|
-
else
|
|
1306
|
-
Rails.logger.error("File Download Failed")
|
|
1307
|
-
raise
|
|
1308
1415
|
end
|
|
1416
|
+
Rails.logger.error("File Download Failed")
|
|
1417
|
+
raise
|
|
1309
1418
|
end
|
|
1310
1419
|
|
|
1311
|
-
def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
|
|
1420
|
+
def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
|
|
1421
|
+
tries ||= 3
|
|
1312
1422
|
request = Nokogiri::XML::Builder.new do |xml|
|
|
1313
1423
|
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
|
|
1314
1424
|
xml['SOAP-ENV'].Header do
|
|
1315
1425
|
xml['ns1'].SessionHeader do
|
|
1316
|
-
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
|
|
1426
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1317
1427
|
end
|
|
1318
1428
|
end
|
|
1319
1429
|
xml['SOAP-ENV'].Body do
|
|
@@ -1330,17 +1440,20 @@ module ZuoraAPI
|
|
|
1330
1440
|
end
|
|
1331
1441
|
end
|
|
1332
1442
|
|
|
1333
|
-
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 =>
|
|
1443
|
+
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 => 130)
|
|
1334
1444
|
|
|
1335
1445
|
output_xml = Nokogiri::XML(response_query.body)
|
|
1336
|
-
|
|
1446
|
+
raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
|
1447
|
+
|
|
1448
|
+
# raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
|
1449
|
+
|
|
1337
1450
|
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
|
1338
1451
|
|
|
1339
1452
|
confirmRequest = Nokogiri::XML::Builder.new do |xml|
|
|
1340
1453
|
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
|
|
1341
1454
|
xml['SOAP-ENV'].Header do
|
|
1342
1455
|
xml['ns1'].SessionHeader do
|
|
1343
|
-
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
|
|
1456
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1344
1457
|
end
|
|
1345
1458
|
end
|
|
1346
1459
|
xml['SOAP-ENV'].Body do
|
|
@@ -1354,12 +1467,14 @@ module ZuoraAPI
|
|
|
1354
1467
|
|
|
1355
1468
|
while result != "Completed"
|
|
1356
1469
|
sleep 3
|
|
1357
|
-
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 =>
|
|
1470
|
+
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 => 130)
|
|
1358
1471
|
|
|
1359
1472
|
output_xml = Nokogiri::XML(response_query.body)
|
|
1360
1473
|
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1361
1474
|
status_code = response_query.code if response_query
|
|
1362
|
-
|
|
1475
|
+
|
|
1476
|
+
raise_errors(type: :SOAP, body: output_xml, response: response_query) if result.blank? || result == "Failed"
|
|
1477
|
+
# raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if result.blank? || result == "Failed"
|
|
1363
1478
|
end
|
|
1364
1479
|
|
|
1365
1480
|
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
|
@@ -1378,10 +1493,39 @@ module ZuoraAPI
|
|
|
1378
1493
|
else
|
|
1379
1494
|
return export_file_path
|
|
1380
1495
|
end
|
|
1496
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1497
|
+
if !(tries -= 1).zero?
|
|
1498
|
+
Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
|
|
1499
|
+
self.new_session
|
|
1500
|
+
retry
|
|
1501
|
+
end
|
|
1502
|
+
raise ex
|
|
1503
|
+
|
|
1504
|
+
rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
|
|
1505
|
+
if !(tries -= 1).zero?
|
|
1506
|
+
Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
|
|
1507
|
+
sleep 10
|
|
1508
|
+
retry
|
|
1509
|
+
end
|
|
1510
|
+
raise ex
|
|
1511
|
+
|
|
1512
|
+
rescue *ZUORA_API_ERRORS => ex
|
|
1513
|
+
raise ex
|
|
1514
|
+
|
|
1515
|
+
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
1516
|
+
if !(tries -= 1).zero?
|
|
1517
|
+
Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
|
|
1518
|
+
sleep 5
|
|
1519
|
+
retry
|
|
1520
|
+
end
|
|
1521
|
+
raise ex
|
|
1522
|
+
|
|
1523
|
+
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1524
|
+
raise ex
|
|
1381
1525
|
end
|
|
1382
1526
|
|
|
1383
1527
|
def query(query, parse = false)
|
|
1384
|
-
output_xml, input_xml = self.soap_call(
|
|
1528
|
+
output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true) do |xml|
|
|
1385
1529
|
xml['ns1'].query do
|
|
1386
1530
|
xml['ns1'].queryString query
|
|
1387
1531
|
end
|