zuora_api 1.7.66d → 1.7.66j
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 +1 -1
- data/Gemfile +1 -1
- data/lib/zuora_api/exceptions.rb +13 -0
- data/lib/zuora_api/login.rb +267 -188
- data/lib/zuora_api/logins/basic.rb +10 -101
- data/lib/zuora_api/logins/oauth.rb +17 -81
- data/lib/zuora_api/version.rb +1 -1
- data/zuora_api.gemspec +3 -2
- metadata +22 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46c1d463bc291f1e674a92bc6dc28a35cb9df005a5e773124d752f624ebc9890
|
|
4
|
+
data.tar.gz: bda2d5483c779155ebffd6e7b7f0472f6a19410f0dc47c168449acd3b31378f8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a979bfcd6e7e668d0a87f097973b86b174d977862d002e7a2a60413e98d4a7481345a5a318ba5906b69ee0fdd8d9a18a96494ec93b476a7a16a3137a38352ca9
|
|
7
|
+
data.tar.gz: 794dd0825636ab56d6aa5008fc9a7d9bd0f5e136db6223d426032b4eee16fd3e942842206c5ad39d50e5fa28aab44f7dc2bfa1f779027e03e6ff2e3fedd81075
|
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
|
data/lib/zuora_api/login.rb
CHANGED
|
@@ -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
|
|
@@ -436,9 +464,10 @@ module ZuoraAPI
|
|
|
436
464
|
errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
|
|
437
465
|
z_session: true,
|
|
438
466
|
timeout_retry: false,
|
|
439
|
-
timeout:
|
|
467
|
+
timeout: 130,
|
|
440
468
|
timeout_sleep_interval: self.timeout_sleep,
|
|
441
469
|
output_exception_messages: true,
|
|
470
|
+
skip_session: false,
|
|
442
471
|
**keyword_args)
|
|
443
472
|
tries ||= 2
|
|
444
473
|
xml = Nokogiri::XML::Builder.new do |xml|
|
|
@@ -448,8 +477,10 @@ module ZuoraAPI
|
|
|
448
477
|
'xmlns:api' => "http://api.zuora.com/",
|
|
449
478
|
"xmlns:#{ns1}" => "http://api.zuora.com/") do
|
|
450
479
|
xml['SOAP-ENV'].Header do
|
|
451
|
-
|
|
452
|
-
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
|
|
453
484
|
end
|
|
454
485
|
if single_transaction
|
|
455
486
|
xml["#{ns1}"].CallOptions do
|
|
@@ -467,7 +498,6 @@ module ZuoraAPI
|
|
|
467
498
|
end
|
|
468
499
|
end
|
|
469
500
|
end
|
|
470
|
-
|
|
471
501
|
input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
|
472
502
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
|
473
503
|
Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
@@ -489,7 +519,11 @@ module ZuoraAPI
|
|
|
489
519
|
Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
490
520
|
|
|
491
521
|
raise_errors(type: :SOAP, body: output_xml, response: response)
|
|
522
|
+
|
|
523
|
+
return output_xml, input_xml, response
|
|
524
|
+
|
|
492
525
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
526
|
+
raise if skip_session
|
|
493
527
|
if !tries.zero? && z_session
|
|
494
528
|
tries -= 1
|
|
495
529
|
Rails.logger.debug("SOAP Call - Session Invalid")
|
|
@@ -514,24 +548,20 @@ module ZuoraAPI
|
|
|
514
548
|
return output_xml, input_xml, response
|
|
515
549
|
|
|
516
550
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
517
|
-
if tries.zero?
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
523
|
-
end
|
|
524
|
-
end
|
|
525
|
-
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
|
|
526
556
|
end
|
|
527
557
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
558
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
559
|
+
raise ex
|
|
560
|
+
|
|
531
561
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
532
562
|
if !tries.zero?
|
|
533
563
|
tries -= 1
|
|
534
|
-
|
|
564
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
535
565
|
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
536
566
|
retry
|
|
537
567
|
elsif timeout_retry
|
|
@@ -540,19 +570,79 @@ module ZuoraAPI
|
|
|
540
570
|
end
|
|
541
571
|
end
|
|
542
572
|
|
|
543
|
-
if output_exception_messages
|
|
544
|
-
|
|
545
|
-
Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
546
|
-
else
|
|
547
|
-
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
548
|
-
end
|
|
549
|
-
end
|
|
550
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
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)
|
|
551
575
|
raise ex
|
|
576
|
+
|
|
552
577
|
rescue => ex
|
|
553
578
|
raise ex
|
|
554
|
-
|
|
555
|
-
|
|
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)
|
|
601
|
+
else
|
|
602
|
+
Rails.logger.send(level.to_sym, "#{location} - #{exception.class} #{message}")
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
def exception_args(ex)
|
|
607
|
+
args = {}
|
|
608
|
+
if ex.class == ZuoraAPI::Exceptions::ZuoraAPIRequestLimit
|
|
609
|
+
args.merge!({
|
|
610
|
+
zuora_trace_id: ex.response.headers["zuora-request-id"],
|
|
611
|
+
zuora_track_id: ex.response.request.options[:headers]["Zuora-Track-Id"]
|
|
612
|
+
})
|
|
613
|
+
elsif defined?(ex.response) && ex.response.present?
|
|
614
|
+
args.merge!({
|
|
615
|
+
request: {
|
|
616
|
+
path: ex.response.request.path.to_s,
|
|
617
|
+
method: ex.response.request.http_method.to_s.split("Net::HTTP::").last.upcase,
|
|
618
|
+
params: ex.response.request.raw_body.to_s,
|
|
619
|
+
headers: ex.response.request.options[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h.to_s,
|
|
620
|
+
},
|
|
621
|
+
response: {
|
|
622
|
+
status: ex.response.code,
|
|
623
|
+
params: ex.response.body.to_s,
|
|
624
|
+
headers: ex.response.headers.to_s,
|
|
625
|
+
},
|
|
626
|
+
zuora_trace_id: ex.response.headers["zuora-request-id"],
|
|
627
|
+
zuora_track_id: ex.response.request.options[:headers]["Zuora-Track-Id"],
|
|
628
|
+
})
|
|
629
|
+
elsif defined?(ex.request) && ex.request.present?
|
|
630
|
+
args.merge!({
|
|
631
|
+
request: {
|
|
632
|
+
path: ex.request.path.to_s,
|
|
633
|
+
method: ex.request.http_method.to_s.split("Net::HTTP::").last.upcase,
|
|
634
|
+
params: ex.request.options[:body],
|
|
635
|
+
headers: ex.request.options[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h.to_s
|
|
636
|
+
}
|
|
637
|
+
})
|
|
638
|
+
args.merge!({
|
|
639
|
+
zuora_track_id: ex.request.options[:headers]["Zuora-Track-Id"]
|
|
640
|
+
}) if ex.request.options[:headers]["Zuora-Track-Id"].present?
|
|
641
|
+
end
|
|
642
|
+
rescue => ex
|
|
643
|
+
Rails.logger.error("Failed to create exception arguments", ex, args)
|
|
644
|
+
ensure
|
|
645
|
+
return args
|
|
556
646
|
end
|
|
557
647
|
|
|
558
648
|
def raise_errors(type: :SOAP, body: nil, response: nil)
|
|
@@ -569,13 +659,13 @@ module ZuoraAPI
|
|
|
569
659
|
end
|
|
570
660
|
|
|
571
661
|
if [502,503].include?(response.code)
|
|
572
|
-
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)
|
|
573
663
|
end
|
|
574
664
|
|
|
575
665
|
# Check failure response code
|
|
576
666
|
case response.code
|
|
577
667
|
when 504
|
|
578
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from
|
|
668
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response)
|
|
579
669
|
when 429
|
|
580
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)
|
|
581
671
|
when 401
|
|
@@ -596,6 +686,10 @@ module ZuoraAPI
|
|
|
596
686
|
when :SOAP
|
|
597
687
|
error, success, message = get_soap_error_and_message(body)
|
|
598
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
|
+
|
|
599
693
|
if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
|
|
600
694
|
body.xpath(
|
|
601
695
|
'//ns1:records[@xsi:type="ns2:Export"]',
|
|
@@ -700,7 +794,11 @@ module ZuoraAPI
|
|
|
700
794
|
end
|
|
701
795
|
|
|
702
796
|
if body['error'] == 'Unauthorized' && body['status'] == 401
|
|
703
|
-
|
|
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
|
|
704
802
|
end
|
|
705
803
|
#Authentication failed
|
|
706
804
|
if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
|
|
@@ -827,6 +925,8 @@ module ZuoraAPI
|
|
|
827
925
|
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
|
|
828
926
|
when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
|
|
829
927
|
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
928
|
+
when /414 Request-URI Too Large/
|
|
929
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Request URL is too long", response)
|
|
830
930
|
else
|
|
831
931
|
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
832
932
|
end
|
|
@@ -896,7 +996,7 @@ module ZuoraAPI
|
|
|
896
996
|
raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
|
|
897
997
|
end
|
|
898
998
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
899
|
-
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/
|
|
999
|
+
when /^INVALID_VERSION/, /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/
|
|
900
1000
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
901
1001
|
when /.*UNEXPECTED_ERROR/
|
|
902
1002
|
raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
|
|
@@ -956,7 +1056,7 @@ module ZuoraAPI
|
|
|
956
1056
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
|
957
1057
|
url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
|
|
958
1058
|
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"}
|
|
959
|
-
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout =>
|
|
1059
|
+
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 130)
|
|
960
1060
|
|
|
961
1061
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
|
|
962
1062
|
|
|
@@ -989,35 +1089,31 @@ module ZuoraAPI
|
|
|
989
1089
|
end
|
|
990
1090
|
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
|
|
991
1091
|
end
|
|
1092
|
+
|
|
1093
|
+
return des_hash
|
|
992
1094
|
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
993
|
-
if tries.zero?
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
Rails.logger.error("Describe - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
|
|
999
|
-
end
|
|
1000
|
-
end
|
|
1001
|
-
raise ex
|
|
1095
|
+
if !tries.zero?
|
|
1096
|
+
tries -= 1
|
|
1097
|
+
self.log(location: "Describe", exception: ex, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :debug)
|
|
1098
|
+
sleep(self.timeout_sleep)
|
|
1099
|
+
retry
|
|
1002
1100
|
end
|
|
1003
1101
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1102
|
+
self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors
|
|
1103
|
+
raise ex
|
|
1104
|
+
|
|
1007
1105
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1008
1106
|
if !tries.zero? && self.status == 'Active'
|
|
1009
1107
|
tries -= 1
|
|
1010
1108
|
Rails.logger.debug("Describe session expired. Starting new session.")
|
|
1011
1109
|
self.new_session
|
|
1012
1110
|
retry
|
|
1013
|
-
else
|
|
1014
|
-
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1015
|
-
raise ex
|
|
1016
1111
|
end
|
|
1112
|
+
|
|
1113
|
+
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1114
|
+
raise ex
|
|
1017
1115
|
rescue => ex
|
|
1018
1116
|
raise ex
|
|
1019
|
-
else
|
|
1020
|
-
return des_hash
|
|
1021
1117
|
end
|
|
1022
1118
|
|
|
1023
1119
|
def rest_call(
|
|
@@ -1030,11 +1126,12 @@ module ZuoraAPI
|
|
|
1030
1126
|
z_session: true,
|
|
1031
1127
|
session_type: :basic,
|
|
1032
1128
|
timeout_retry: false,
|
|
1033
|
-
timeout:
|
|
1129
|
+
timeout: 130,
|
|
1034
1130
|
timeout_sleep_interval: self.timeout_sleep,
|
|
1035
1131
|
multipart: false,
|
|
1036
1132
|
stream_body: false,
|
|
1037
1133
|
output_exception_messages: true,
|
|
1134
|
+
zuora_track_id: nil,
|
|
1038
1135
|
**keyword_args,
|
|
1039
1136
|
&block
|
|
1040
1137
|
)
|
|
@@ -1044,12 +1141,13 @@ module ZuoraAPI
|
|
|
1044
1141
|
|
|
1045
1142
|
authentication_headers = {}
|
|
1046
1143
|
if z_session
|
|
1047
|
-
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type) }
|
|
1144
|
+
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type, zuora_track_id: zuora_track_id) }
|
|
1048
1145
|
if self.entity_id.present?
|
|
1049
1146
|
authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
|
1050
1147
|
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
|
1051
1148
|
end
|
|
1052
1149
|
end
|
|
1150
|
+
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
1053
1151
|
|
|
1054
1152
|
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
|
1055
1153
|
|
|
@@ -1075,10 +1173,12 @@ module ZuoraAPI
|
|
|
1075
1173
|
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
|
1076
1174
|
|
|
1077
1175
|
raise_errors(type: :JSON, body: output_json, response: response)
|
|
1078
|
-
rescue
|
|
1176
|
+
rescue => ex
|
|
1079
1177
|
reset_files(body) if multipart
|
|
1080
1178
|
raise
|
|
1081
1179
|
end
|
|
1180
|
+
|
|
1181
|
+
return [output_json, response]
|
|
1082
1182
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
|
1083
1183
|
if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
|
|
1084
1184
|
session_type = :bearer
|
|
@@ -1113,23 +1213,21 @@ module ZuoraAPI
|
|
|
1113
1213
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1114
1214
|
raise ex
|
|
1115
1215
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
1116
|
-
if tries.zero?
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1122
|
-
end
|
|
1123
|
-
end
|
|
1124
|
-
raise ex
|
|
1216
|
+
if !tries.zero?
|
|
1217
|
+
tries -= 1
|
|
1218
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
1219
|
+
sleep(timeout_sleep_interval)
|
|
1220
|
+
retry
|
|
1125
1221
|
end
|
|
1126
1222
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1223
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
1224
|
+
raise ex
|
|
1225
|
+
|
|
1130
1226
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
1227
|
+
|
|
1131
1228
|
if !tries.zero?
|
|
1132
1229
|
tries -= 1
|
|
1230
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
1133
1231
|
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
1134
1232
|
retry
|
|
1135
1233
|
elsif timeout_retry
|
|
@@ -1137,20 +1235,15 @@ module ZuoraAPI
|
|
|
1137
1235
|
retry
|
|
1138
1236
|
end
|
|
1139
1237
|
end
|
|
1140
|
-
|
|
1141
|
-
if output_exception_messages
|
|
1142
|
-
|
|
1143
|
-
Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
1144
|
-
else
|
|
1145
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1146
|
-
end
|
|
1147
|
-
end
|
|
1148
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
1238
|
+
|
|
1239
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
1240
|
+
ex = ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
1149
1241
|
raise ex
|
|
1242
|
+
|
|
1150
1243
|
rescue => ex
|
|
1151
1244
|
raise ex
|
|
1152
|
-
|
|
1153
|
-
|
|
1245
|
+
ensure
|
|
1246
|
+
self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
|
|
1154
1247
|
end
|
|
1155
1248
|
|
|
1156
1249
|
def update_create_tenant
|
|
@@ -1172,8 +1265,9 @@ module ZuoraAPI
|
|
|
1172
1265
|
while !response["nextPage"].blank?
|
|
1173
1266
|
url = self.rest_endpoint(response["nextPage"].split('/v1/').last)
|
|
1174
1267
|
Rails.logger.debug("Fetch Catalog URL #{url}")
|
|
1175
|
-
output_json, response = self.rest_call(:
|
|
1176
|
-
|
|
1268
|
+
output_json, response = self.rest_call(debug: false, url: url, timeout_retry: true)
|
|
1269
|
+
|
|
1270
|
+
if !/(true|t|yes|y|1)$/.match(output_json['success'].to_s) || output_json['success'].class != TrueClass
|
|
1177
1271
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
|
|
1178
1272
|
end
|
|
1179
1273
|
output_json["products"].each do |product|
|
|
@@ -1199,7 +1293,7 @@ module ZuoraAPI
|
|
|
1199
1293
|
return products, catalog_map
|
|
1200
1294
|
end
|
|
1201
1295
|
|
|
1202
|
-
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:
|
|
1296
|
+
def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout: 130, session_type: :basic, **execute_params)
|
|
1203
1297
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
|
1204
1298
|
|
|
1205
1299
|
retry_count ||= timeout_retries
|
|
@@ -1307,12 +1401,10 @@ module ZuoraAPI
|
|
|
1307
1401
|
if !(retry_count -= 1).zero?
|
|
1308
1402
|
self.new_session
|
|
1309
1403
|
raise response.class
|
|
1310
|
-
else
|
|
1311
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1312
1404
|
end
|
|
1313
|
-
|
|
1314
|
-
raise
|
|
1405
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1315
1406
|
end
|
|
1407
|
+
raise
|
|
1316
1408
|
else
|
|
1317
1409
|
raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
|
|
1318
1410
|
end
|
|
@@ -1322,133 +1414,120 @@ module ZuoraAPI
|
|
|
1322
1414
|
sleep(5)
|
|
1323
1415
|
if (retry_count -= 1) >= 0
|
|
1324
1416
|
retry
|
|
1325
|
-
else
|
|
1326
|
-
Rails.logger.error("File Download Failed")
|
|
1327
|
-
raise
|
|
1328
1417
|
end
|
|
1418
|
+
Rails.logger.error("File Download Failed")
|
|
1419
|
+
raise
|
|
1329
1420
|
end
|
|
1330
1421
|
|
|
1331
1422
|
def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
xml['SOAP-ENV'].
|
|
1336
|
-
xml['
|
|
1337
|
-
xml['ns1'].
|
|
1338
|
-
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1339
|
-
end
|
|
1423
|
+
tries ||= 3
|
|
1424
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
|
1425
|
+
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
|
|
1426
|
+
xml['SOAP-ENV'].Header do
|
|
1427
|
+
xml['ns1'].SessionHeader do
|
|
1428
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1340
1429
|
end
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1430
|
+
end
|
|
1431
|
+
xml['SOAP-ENV'].Body do
|
|
1432
|
+
xml['ns1'].create do
|
|
1433
|
+
xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
|
|
1434
|
+
xml['ns2'].Format 'csv'
|
|
1435
|
+
xml['ns2'].Zip zip
|
|
1436
|
+
xml['ns2'].Name 'googman'
|
|
1437
|
+
xml['ns2'].Query query
|
|
1438
|
+
xml['ns2'].Encrypted encrypted
|
|
1350
1439
|
end
|
|
1351
1440
|
end
|
|
1352
1441
|
end
|
|
1353
1442
|
end
|
|
1443
|
+
end
|
|
1354
1444
|
|
|
1355
|
-
|
|
1445
|
+
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)
|
|
1356
1446
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1447
|
+
output_xml = Nokogiri::XML(response_query.body)
|
|
1448
|
+
raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
|
1359
1449
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1450
|
+
# raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
|
1451
|
+
|
|
1452
|
+
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
|
1363
1453
|
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
end
|
|
1454
|
+
confirmRequest = Nokogiri::XML::Builder.new do |xml|
|
|
1455
|
+
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
|
|
1456
|
+
xml['SOAP-ENV'].Header do
|
|
1457
|
+
xml['ns1'].SessionHeader do
|
|
1458
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1370
1459
|
end
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1460
|
+
end
|
|
1461
|
+
xml['SOAP-ENV'].Body do
|
|
1462
|
+
xml['ns1'].query do
|
|
1463
|
+
xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
|
|
1375
1464
|
end
|
|
1376
1465
|
end
|
|
1377
1466
|
end
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
while result != "Completed"
|
|
1381
|
-
sleep 3
|
|
1382
|
-
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)
|
|
1383
|
-
|
|
1384
|
-
output_xml = Nokogiri::XML(response_query.body)
|
|
1385
|
-
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1386
|
-
status_code = response_query.code if response_query
|
|
1467
|
+
end
|
|
1468
|
+
result = 'Waiting'
|
|
1387
1469
|
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1470
|
+
while result != "Completed"
|
|
1471
|
+
sleep 3
|
|
1472
|
+
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)
|
|
1391
1473
|
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
Rails.logger.debug("=====> Export path #{export_file.path}")
|
|
1396
|
-
|
|
1397
|
-
if extract && zip
|
|
1398
|
-
require "zip"
|
|
1399
|
-
new_path = export_file_path.partition('.zip').first
|
|
1400
|
-
zipped = Zip::File.open(export_file_path)
|
|
1401
|
-
file_handle = zipped.entries.first
|
|
1402
|
-
file_handle.extract(new_path)
|
|
1403
|
-
File.delete(export_file_path)
|
|
1404
|
-
return new_path
|
|
1405
|
-
else
|
|
1406
|
-
return export_file_path
|
|
1407
|
-
end
|
|
1408
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1409
|
-
if !(tries -= 1).zero?
|
|
1410
|
-
Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
|
|
1411
|
-
self.new_session
|
|
1412
|
-
retry
|
|
1413
|
-
else
|
|
1414
|
-
raise ex
|
|
1415
|
-
end
|
|
1474
|
+
output_xml = Nokogiri::XML(response_query.body)
|
|
1475
|
+
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1476
|
+
status_code = response_query.code if response_query
|
|
1416
1477
|
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
sleep 10
|
|
1421
|
-
retry
|
|
1422
|
-
else
|
|
1423
|
-
raise ex
|
|
1424
|
-
end
|
|
1478
|
+
raise_errors(type: :SOAP, body: output_xml, response: response_query) if result.blank? || result == "Failed"
|
|
1479
|
+
# raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if result.blank? || result == "Failed"
|
|
1480
|
+
end
|
|
1425
1481
|
|
|
1426
|
-
|
|
1427
|
-
|
|
1482
|
+
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1483
|
+
export_file = get_file(:url => self.fileURL(file_id))
|
|
1484
|
+
export_file_path = export_file.path
|
|
1485
|
+
Rails.logger.debug("=====> Export path #{export_file.path}")
|
|
1486
|
+
|
|
1487
|
+
if extract && zip
|
|
1488
|
+
require "zip"
|
|
1489
|
+
new_path = export_file_path.partition('.zip').first
|
|
1490
|
+
zipped = Zip::File.open(export_file_path)
|
|
1491
|
+
file_handle = zipped.entries.first
|
|
1492
|
+
file_handle.extract(new_path)
|
|
1493
|
+
File.delete(export_file_path)
|
|
1494
|
+
return new_path
|
|
1495
|
+
else
|
|
1496
|
+
return export_file_path
|
|
1497
|
+
end
|
|
1498
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1499
|
+
if !(tries -= 1).zero?
|
|
1500
|
+
Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
|
|
1501
|
+
self.new_session
|
|
1502
|
+
retry
|
|
1503
|
+
end
|
|
1504
|
+
raise ex
|
|
1428
1505
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
end
|
|
1506
|
+
rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
|
|
1507
|
+
if !(tries -= 1).zero?
|
|
1508
|
+
Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
|
|
1509
|
+
sleep 10
|
|
1510
|
+
retry
|
|
1511
|
+
end
|
|
1512
|
+
raise ex
|
|
1437
1513
|
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
retry
|
|
1441
|
-
else
|
|
1442
|
-
raise ex
|
|
1443
|
-
end
|
|
1514
|
+
rescue *ZUORA_API_ERRORS => ex
|
|
1515
|
+
raise ex
|
|
1444
1516
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1517
|
+
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
1518
|
+
if !(tries -= 1).zero?
|
|
1519
|
+
Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
|
|
1520
|
+
sleep 5
|
|
1521
|
+
retry
|
|
1447
1522
|
end
|
|
1523
|
+
raise ex
|
|
1524
|
+
|
|
1525
|
+
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1526
|
+
raise ex
|
|
1448
1527
|
end
|
|
1449
1528
|
|
|
1450
1529
|
def query(query, parse = false)
|
|
1451
|
-
output_xml, input_xml = self.soap_call(
|
|
1530
|
+
output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true) do |xml|
|
|
1452
1531
|
xml['ns1'].query do
|
|
1453
1532
|
xml['ns1'].queryString query
|
|
1454
1533
|
end
|
|
@@ -10,113 +10,22 @@ module ZuoraAPI
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def new_session(auth_type: :basic, debug: false, zuora_track_id: nil)
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
super do
|
|
14
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
|
|
15
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Basic Login but either 'Username' or 'Password' were not passed.") if (self.password.blank? && self.username.blank?)
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
xml['api'].login do
|
|
22
|
-
xml['api'].username self.username
|
|
23
|
-
xml['api'].password self.password
|
|
24
|
-
xml['api'].entityId self.entity_id if !self.entity_id.blank?
|
|
25
|
-
end
|
|
17
|
+
output_xml, input_xml, response = soap_call(timeout_retry: true, skip_session: true, zuora_track_id: zuora_track_id) do |xml|
|
|
18
|
+
xml['api'].login do
|
|
19
|
+
xml['api'].username self.username
|
|
20
|
+
xml['api'].password self.password
|
|
21
|
+
xml['api'].entityId self.entity_id if !self.entity_id.blank?
|
|
26
22
|
end
|
|
27
23
|
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
|
31
|
-
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
|
32
|
-
Rails.logger.debug('Connect') {"SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
|
33
|
-
|
|
34
|
-
headers = { 'Content-Type' => "text/xml; charset=utf-8" }
|
|
35
|
-
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
36
24
|
|
|
37
|
-
response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => headers, :timeout => 10)
|
|
38
|
-
output_xml = Nokogiri::XML(response_query.body)
|
|
39
|
-
Rails.logger.debug('Connect') {"Response Code: #{response_query.code} SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
|
40
|
-
|
|
41
|
-
if !response_query.success?
|
|
42
|
-
self.current_session = nil
|
|
43
|
-
if output_xml.namespaces.size > 0 && output_xml.xpath('//soapenv:Fault').size > 0
|
|
44
|
-
self.current_error = output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
|
45
|
-
if self.current_error.include?('deactivated')
|
|
46
|
-
self.status = 'Deactivated'
|
|
47
|
-
self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
|
|
48
|
-
self.errors[:username] = self.current_error
|
|
49
|
-
elsif self.current_error.include?('inactive')
|
|
50
|
-
self.status = 'Inactive'
|
|
51
|
-
self.current_error = 'Inactive user login, please check with Zuora tenant administrator'
|
|
52
|
-
self.errors[:username] = self.current_error
|
|
53
|
-
elsif self.current_error.include?("invalid username or password") || self.current_error.include?("Invalid login. User name and password do not match.")
|
|
54
|
-
self.status = 'Invalid Login'
|
|
55
|
-
self.current_error = 'Invalid login, please check username and password or URL endpoint'
|
|
56
|
-
self.errors[:username] = self.current_error
|
|
57
|
-
self.errors[:password] = self.current_error
|
|
58
|
-
elsif self.current_error.include?('unsupported version')
|
|
59
|
-
self.status = 'Unsupported API Version'
|
|
60
|
-
self.current_error = 'Unsupported API version, please verify URL endpoint'
|
|
61
|
-
self.errors[:url] = self.current_error
|
|
62
|
-
elsif self.current_error.include?('invalid api version')
|
|
63
|
-
self.status = 'Invalid API Version'
|
|
64
|
-
self.current_error = 'Invalid API version, please verify URL endpoint'
|
|
65
|
-
self.errors[:url] = self.current_error
|
|
66
|
-
elsif self.current_error.include?('invalid session')
|
|
67
|
-
self.status = 'Invalid Session'
|
|
68
|
-
self.current_error = 'Session invalid, please update session and verify URL endpoint'
|
|
69
|
-
self.errors[:session] = self.current_error
|
|
70
|
-
elsif self.current_error.include?('Your IP address')
|
|
71
|
-
self.status = 'Restricted IP'
|
|
72
|
-
self.current_error = 'IP restricted, contact Zuora tenant administrator and remove IP restriction'
|
|
73
|
-
self.errors[:base] = self.current_error
|
|
74
|
-
elsif self.current_error.include?('This account has been locked')
|
|
75
|
-
self.status = 'Locked'
|
|
76
|
-
self.current_error = 'Locked user login, please wait or navigate to Zuora to unlock user'
|
|
77
|
-
self.errors[:username] = self.current_error
|
|
78
|
-
elsif self.current_error.include?('Entity not exist:')
|
|
79
|
-
self.status = 'Entity Missing'
|
|
80
|
-
self.errors[:base] = self.current_error
|
|
81
|
-
else
|
|
82
|
-
self.status = 'Unknown'
|
|
83
|
-
self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
|
|
84
|
-
self.errors[:base] = self.current_error
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
else
|
|
88
|
-
self.status = 'Unknown'
|
|
89
|
-
self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
|
|
90
|
-
self.errors[:base] = self.current_error
|
|
91
|
-
end
|
|
92
|
-
else
|
|
93
|
-
#Username & password combo
|
|
94
25
|
retrieved_session = output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
|
|
95
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.",
|
|
96
|
-
self.status = 'Active'
|
|
26
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.", response) if retrieved_session.blank?
|
|
97
27
|
self.current_session = retrieved_session
|
|
98
|
-
|
|
99
|
-
return self.status
|
|
100
|
-
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
101
|
-
if !tries.zero?
|
|
102
|
-
tries -= 1
|
|
103
|
-
sleep(self.timeout_sleep)
|
|
104
|
-
retry
|
|
105
|
-
else
|
|
106
|
-
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
107
|
-
Rails.logger.error("BasicLogin - Timed out", ex)
|
|
108
|
-
else
|
|
109
|
-
Rails.logger.error("BasicLogin - #{ex.class} Timed out")
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
self.current_error = "Request timed out. Try again"
|
|
113
|
-
self.status = 'Timeout'
|
|
114
|
-
return self.status
|
|
115
|
-
end
|
|
116
|
-
rescue EOFError
|
|
117
|
-
if self.url.match?(/.*services\d{1,}.zuora.com*/)
|
|
118
|
-
self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available."
|
|
119
|
-
self.status = 'Not Available'
|
|
28
|
+
self.status = 'Active'
|
|
120
29
|
return self.status
|
|
121
30
|
end
|
|
122
31
|
end
|
|
@@ -12,16 +12,18 @@ module ZuoraAPI
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def new_session(auth_type: nil, zuora_track_id: nil)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
super do
|
|
16
|
+
if auth_type == :bearer
|
|
17
|
+
get_bearer_token(zuora_track_id: zuora_track_id)
|
|
18
|
+
elsif auth_type == :basic
|
|
19
|
+
get_bearer_token(zuora_track_id: zuora_track_id) if self.oauth_expired?
|
|
20
|
+
get_z_session(zuora_track_id: zuora_track_id)
|
|
21
|
+
else
|
|
22
|
+
get_bearer_token(zuora_track_id: zuora_track_id) if self.oauth_expired?
|
|
23
|
+
get_z_session(zuora_track_id: zuora_track_id)
|
|
24
|
+
end
|
|
25
|
+
return self.status
|
|
23
26
|
end
|
|
24
|
-
return self.status
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def get_active_bearer_token
|
|
@@ -30,7 +32,6 @@ module ZuoraAPI
|
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def get_z_session(debug: false, zuora_track_id: nil)
|
|
33
|
-
tries ||= 2
|
|
34
35
|
headers = self.entity_id.present? ? {"Zuora-Entity-Ids" => self.entity_id } : {}
|
|
35
36
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
36
37
|
output_json, response = self.rest_call(:url => self.rest_endpoint("connections"), :session_type => :bearer, :headers => headers)
|
|
@@ -44,49 +45,22 @@ module ZuoraAPI
|
|
|
44
45
|
headers: response.headers.to_s,
|
|
45
46
|
}
|
|
46
47
|
})
|
|
47
|
-
raise ZuoraAPI::Exceptions::
|
|
48
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Failure Parsing Cookie Headers", response)
|
|
48
49
|
end
|
|
49
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
50
|
-
if !tries.zero?
|
|
51
|
-
tries -= 1
|
|
52
|
-
Rails.logger.debug {"Session Invalid"}
|
|
53
|
-
self.new_session(auth_type: :bearer)
|
|
54
|
-
retry
|
|
55
|
-
end
|
|
56
|
-
raise ex
|
|
57
|
-
|
|
58
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
|
59
|
-
raise ex
|
|
60
|
-
|
|
61
|
-
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
62
|
-
if !tries.zero?
|
|
63
|
-
tries -= 1
|
|
64
|
-
sleep(self.timeout_sleep)
|
|
65
|
-
retry
|
|
66
|
-
end
|
|
67
|
-
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
68
|
-
Rails.logger.error("OAuthLogin - Timed out", ex)
|
|
69
|
-
else
|
|
70
|
-
Rails.logger.error("OAuthLogin - #{ex.class} Timed out")
|
|
71
|
-
end
|
|
72
|
-
self.current_error = "Request timed out. Try again"
|
|
73
|
-
self.status = 'Timeout'
|
|
74
|
-
return self.status
|
|
75
50
|
end
|
|
76
51
|
|
|
77
52
|
def get_bearer_token(zuora_track_id: nil)
|
|
78
|
-
tries ||= 2
|
|
79
53
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if self.oauth_client_id.blank? || self.oauth_secret.blank?
|
|
80
54
|
|
|
81
55
|
headers = { "content-type" => "application/x-www-form-urlencoded" }
|
|
82
56
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
83
57
|
|
|
84
58
|
output_json, response = self.rest_call(:method => :post,
|
|
85
|
-
:
|
|
86
|
-
:
|
|
87
|
-
:
|
|
88
|
-
:
|
|
89
|
-
:
|
|
59
|
+
url: self.rest_endpoint.chomp('v1/').concat("oauth/token"),
|
|
60
|
+
z_session: false,
|
|
61
|
+
timeout_retry: true,
|
|
62
|
+
headers: headers,
|
|
63
|
+
body: {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"}
|
|
90
64
|
)
|
|
91
65
|
|
|
92
66
|
self.bearer_token = output_json["access_token"]
|
|
@@ -96,44 +70,6 @@ module ZuoraAPI
|
|
|
96
70
|
self.status = 'Active'
|
|
97
71
|
|
|
98
72
|
return self.status
|
|
99
|
-
|
|
100
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex
|
|
101
|
-
raise ex if tries.zero?
|
|
102
|
-
|
|
103
|
-
tries -= 1
|
|
104
|
-
sleep(self.timeout_sleep)
|
|
105
|
-
retry
|
|
106
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
107
|
-
self.bearer_token = nil
|
|
108
|
-
self.oauth_session_expires_at = nil
|
|
109
|
-
self.current_error = ex.message
|
|
110
|
-
case ex.message
|
|
111
|
-
when "Forbidden"
|
|
112
|
-
self.current_error = "The user associated to OAuth credential set has been deactivated."
|
|
113
|
-
self.status = 'Deactivated'
|
|
114
|
-
else
|
|
115
|
-
self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
|
|
116
|
-
self.status = 'Invalid Login'
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
return self.status
|
|
120
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
|
121
|
-
raise ex
|
|
122
|
-
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
123
|
-
if !tries.zero?
|
|
124
|
-
tries -= 1
|
|
125
|
-
sleep(self.timeout_sleep)
|
|
126
|
-
retry
|
|
127
|
-
else
|
|
128
|
-
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
129
|
-
Rails.logger.error("OAuthLogin - Timed out will retry after #{self.timeout_sleep} seconds", ex)
|
|
130
|
-
else
|
|
131
|
-
Rails.logger.error("OAuthLogin - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
|
|
132
|
-
end
|
|
133
|
-
self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
|
|
134
|
-
self.status = 'Timeout'
|
|
135
|
-
return self.status
|
|
136
|
-
end
|
|
137
73
|
end
|
|
138
74
|
|
|
139
75
|
def oauth_expired?
|
data/lib/zuora_api/version.rb
CHANGED
data/zuora_api.gemspec
CHANGED
|
@@ -18,11 +18,12 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
-
spec.add_development_dependency "bundler"
|
|
21
|
+
spec.add_development_dependency "bundler"
|
|
22
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
|
23
23
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
24
24
|
spec.add_development_dependency("webmock")
|
|
25
|
-
spec.add_development_dependency("simplecov")
|
|
25
|
+
spec.add_development_dependency("simplecov", "~> 0.18.5")
|
|
26
|
+
spec.add_dependency("ougai")
|
|
26
27
|
spec.add_dependency("nokogiri")
|
|
27
28
|
spec.add_dependency("httparty")
|
|
28
29
|
spec.add_dependency("rubyzip")
|
metadata
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zuora_api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.7.
|
|
4
|
+
version: 1.7.66j
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Zuora Strategic Solutions Group
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-06-
|
|
11
|
+
date: 2020-06-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -68,12 +68,26 @@ dependencies:
|
|
|
68
68
|
version: '0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: simplecov
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.18.5
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.18.5
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: ougai
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
72
86
|
requirements:
|
|
73
87
|
- - ">="
|
|
74
88
|
- !ruby/object:Gem::Version
|
|
75
89
|
version: '0'
|
|
76
|
-
type: :
|
|
90
|
+
type: :runtime
|
|
77
91
|
prerelease: false
|
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
93
|
requirements:
|
|
@@ -186,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
186
200
|
- !ruby/object:Gem::Version
|
|
187
201
|
version: 1.3.1
|
|
188
202
|
requirements: []
|
|
189
|
-
rubygems_version: 3.
|
|
203
|
+
rubygems_version: 3.1.2
|
|
190
204
|
signing_key:
|
|
191
205
|
specification_version: 4
|
|
192
206
|
summary: Gem that provides easy integration to Zuora
|