zuora_api 1.7.66d → 1.7.66f
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 +264 -187
- data/lib/zuora_api/logins/basic.rb +10 -101
- data/lib/zuora_api/logins/oauth.rb +17 -72
- 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: b2ec277d17da6045065c52d109e4e46c6c4abfb9b0024e1196536fd1e3713dd9
|
|
4
|
+
data.tar.gz: f6341f70793093543d78c26028ce8bd7e347d6bdb56bddcf2a3eacacaa3e1d8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d9d5c64f3a17b2bab098eed68c888752ad781df5095ae39cce33ba74687cae36785481313dc8915a633788ba52d7fd32feb696fdeb07cd6fc4d3012a146fb2bc
|
|
7
|
+
data.tar.gz: 84ac3d58829be07766fa31cbb964aea48d73da0d77a88ea92067622508ce3296bbda4b153119c08c7b2f19dbc8341e74ac04d9abce7ef1c363a568a7ee9fa1de
|
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, 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?
|
|
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)
|
|
@@ -956,7 +1054,7 @@ module ZuoraAPI
|
|
|
956
1054
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
|
957
1055
|
url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
|
|
958
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"}
|
|
959
|
-
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)
|
|
960
1058
|
|
|
961
1059
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
|
|
962
1060
|
|
|
@@ -989,35 +1087,31 @@ module ZuoraAPI
|
|
|
989
1087
|
end
|
|
990
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
|
|
991
1089
|
end
|
|
1090
|
+
|
|
1091
|
+
return des_hash
|
|
992
1092
|
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
|
|
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
|
|
1002
1098
|
end
|
|
1003
1099
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1100
|
+
self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors
|
|
1101
|
+
raise ex
|
|
1102
|
+
|
|
1007
1103
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1008
1104
|
if !tries.zero? && self.status == 'Active'
|
|
1009
1105
|
tries -= 1
|
|
1010
1106
|
Rails.logger.debug("Describe session expired. Starting new session.")
|
|
1011
1107
|
self.new_session
|
|
1012
1108
|
retry
|
|
1013
|
-
else
|
|
1014
|
-
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1015
|
-
raise ex
|
|
1016
1109
|
end
|
|
1110
|
+
|
|
1111
|
+
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1112
|
+
raise ex
|
|
1017
1113
|
rescue => ex
|
|
1018
1114
|
raise ex
|
|
1019
|
-
else
|
|
1020
|
-
return des_hash
|
|
1021
1115
|
end
|
|
1022
1116
|
|
|
1023
1117
|
def rest_call(
|
|
@@ -1030,11 +1124,12 @@ module ZuoraAPI
|
|
|
1030
1124
|
z_session: true,
|
|
1031
1125
|
session_type: :basic,
|
|
1032
1126
|
timeout_retry: false,
|
|
1033
|
-
timeout:
|
|
1127
|
+
timeout: 130,
|
|
1034
1128
|
timeout_sleep_interval: self.timeout_sleep,
|
|
1035
1129
|
multipart: false,
|
|
1036
1130
|
stream_body: false,
|
|
1037
1131
|
output_exception_messages: true,
|
|
1132
|
+
zuora_track_id: nil,
|
|
1038
1133
|
**keyword_args,
|
|
1039
1134
|
&block
|
|
1040
1135
|
)
|
|
@@ -1044,12 +1139,13 @@ module ZuoraAPI
|
|
|
1044
1139
|
|
|
1045
1140
|
authentication_headers = {}
|
|
1046
1141
|
if z_session
|
|
1047
|
-
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) }
|
|
1048
1143
|
if self.entity_id.present?
|
|
1049
1144
|
authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
|
1050
1145
|
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
|
1051
1146
|
end
|
|
1052
1147
|
end
|
|
1148
|
+
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
1053
1149
|
|
|
1054
1150
|
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
|
1055
1151
|
|
|
@@ -1075,10 +1171,12 @@ module ZuoraAPI
|
|
|
1075
1171
|
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
|
1076
1172
|
|
|
1077
1173
|
raise_errors(type: :JSON, body: output_json, response: response)
|
|
1078
|
-
rescue
|
|
1174
|
+
rescue => ex
|
|
1079
1175
|
reset_files(body) if multipart
|
|
1080
1176
|
raise
|
|
1081
1177
|
end
|
|
1178
|
+
|
|
1179
|
+
return [output_json, response]
|
|
1082
1180
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
|
1083
1181
|
if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
|
|
1084
1182
|
session_type = :bearer
|
|
@@ -1113,23 +1211,21 @@ module ZuoraAPI
|
|
|
1113
1211
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1114
1212
|
raise ex
|
|
1115
1213
|
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
|
|
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
|
|
1125
1219
|
end
|
|
1126
1220
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1221
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
1222
|
+
raise ex
|
|
1223
|
+
|
|
1130
1224
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
1225
|
+
|
|
1131
1226
|
if !tries.zero?
|
|
1132
1227
|
tries -= 1
|
|
1228
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
1133
1229
|
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
1134
1230
|
retry
|
|
1135
1231
|
elsif timeout_retry
|
|
@@ -1137,20 +1233,15 @@ module ZuoraAPI
|
|
|
1137
1233
|
retry
|
|
1138
1234
|
end
|
|
1139
1235
|
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)
|
|
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)
|
|
1149
1239
|
raise ex
|
|
1240
|
+
|
|
1150
1241
|
rescue => ex
|
|
1151
1242
|
raise ex
|
|
1152
|
-
|
|
1153
|
-
|
|
1243
|
+
ensure
|
|
1244
|
+
self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
|
|
1154
1245
|
end
|
|
1155
1246
|
|
|
1156
1247
|
def update_create_tenant
|
|
@@ -1172,8 +1263,9 @@ module ZuoraAPI
|
|
|
1172
1263
|
while !response["nextPage"].blank?
|
|
1173
1264
|
url = self.rest_endpoint(response["nextPage"].split('/v1/').last)
|
|
1174
1265
|
Rails.logger.debug("Fetch Catalog URL #{url}")
|
|
1175
|
-
output_json, response = self.rest_call(:
|
|
1176
|
-
|
|
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
|
|
1177
1269
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
|
|
1178
1270
|
end
|
|
1179
1271
|
output_json["products"].each do |product|
|
|
@@ -1199,7 +1291,7 @@ module ZuoraAPI
|
|
|
1199
1291
|
return products, catalog_map
|
|
1200
1292
|
end
|
|
1201
1293
|
|
|
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:
|
|
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)
|
|
1203
1295
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
|
1204
1296
|
|
|
1205
1297
|
retry_count ||= timeout_retries
|
|
@@ -1307,12 +1399,10 @@ module ZuoraAPI
|
|
|
1307
1399
|
if !(retry_count -= 1).zero?
|
|
1308
1400
|
self.new_session
|
|
1309
1401
|
raise response.class
|
|
1310
|
-
else
|
|
1311
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1312
1402
|
end
|
|
1313
|
-
|
|
1314
|
-
raise
|
|
1403
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1315
1404
|
end
|
|
1405
|
+
raise
|
|
1316
1406
|
else
|
|
1317
1407
|
raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
|
|
1318
1408
|
end
|
|
@@ -1322,133 +1412,120 @@ module ZuoraAPI
|
|
|
1322
1412
|
sleep(5)
|
|
1323
1413
|
if (retry_count -= 1) >= 0
|
|
1324
1414
|
retry
|
|
1325
|
-
else
|
|
1326
|
-
Rails.logger.error("File Download Failed")
|
|
1327
|
-
raise
|
|
1328
1415
|
end
|
|
1416
|
+
Rails.logger.error("File Download Failed")
|
|
1417
|
+
raise
|
|
1329
1418
|
end
|
|
1330
1419
|
|
|
1331
1420
|
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
|
|
1421
|
+
tries ||= 3
|
|
1422
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
|
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
|
|
1424
|
+
xml['SOAP-ENV'].Header do
|
|
1425
|
+
xml['ns1'].SessionHeader do
|
|
1426
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1340
1427
|
end
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1428
|
+
end
|
|
1429
|
+
xml['SOAP-ENV'].Body do
|
|
1430
|
+
xml['ns1'].create do
|
|
1431
|
+
xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
|
|
1432
|
+
xml['ns2'].Format 'csv'
|
|
1433
|
+
xml['ns2'].Zip zip
|
|
1434
|
+
xml['ns2'].Name 'googman'
|
|
1435
|
+
xml['ns2'].Query query
|
|
1436
|
+
xml['ns2'].Encrypted encrypted
|
|
1350
1437
|
end
|
|
1351
1438
|
end
|
|
1352
1439
|
end
|
|
1353
1440
|
end
|
|
1441
|
+
end
|
|
1354
1442
|
|
|
1355
|
-
|
|
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)
|
|
1356
1444
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1445
|
+
output_xml = Nokogiri::XML(response_query.body)
|
|
1446
|
+
raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
|
1359
1447
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
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
|
+
|
|
1450
|
+
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
|
1363
1451
|
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
end
|
|
1452
|
+
confirmRequest = Nokogiri::XML::Builder.new do |xml|
|
|
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
|
|
1454
|
+
xml['SOAP-ENV'].Header do
|
|
1455
|
+
xml['ns1'].SessionHeader do
|
|
1456
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1370
1457
|
end
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1458
|
+
end
|
|
1459
|
+
xml['SOAP-ENV'].Body do
|
|
1460
|
+
xml['ns1'].query do
|
|
1461
|
+
xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
|
|
1375
1462
|
end
|
|
1376
1463
|
end
|
|
1377
1464
|
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
|
|
1465
|
+
end
|
|
1466
|
+
result = 'Waiting'
|
|
1387
1467
|
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1468
|
+
while result != "Completed"
|
|
1469
|
+
sleep 3
|
|
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)
|
|
1391
1471
|
|
|
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
|
|
1472
|
+
output_xml = Nokogiri::XML(response_query.body)
|
|
1473
|
+
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1474
|
+
status_code = response_query.code if response_query
|
|
1416
1475
|
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
sleep 10
|
|
1421
|
-
retry
|
|
1422
|
-
else
|
|
1423
|
-
raise ex
|
|
1424
|
-
end
|
|
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"
|
|
1478
|
+
end
|
|
1425
1479
|
|
|
1426
|
-
|
|
1427
|
-
|
|
1480
|
+
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1481
|
+
export_file = get_file(:url => self.fileURL(file_id))
|
|
1482
|
+
export_file_path = export_file.path
|
|
1483
|
+
Rails.logger.debug("=====> Export path #{export_file.path}")
|
|
1484
|
+
|
|
1485
|
+
if extract && zip
|
|
1486
|
+
require "zip"
|
|
1487
|
+
new_path = export_file_path.partition('.zip').first
|
|
1488
|
+
zipped = Zip::File.open(export_file_path)
|
|
1489
|
+
file_handle = zipped.entries.first
|
|
1490
|
+
file_handle.extract(new_path)
|
|
1491
|
+
File.delete(export_file_path)
|
|
1492
|
+
return new_path
|
|
1493
|
+
else
|
|
1494
|
+
return export_file_path
|
|
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
|
|
1428
1503
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
end
|
|
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
|
|
1437
1511
|
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
retry
|
|
1441
|
-
else
|
|
1442
|
-
raise ex
|
|
1443
|
-
end
|
|
1512
|
+
rescue *ZUORA_API_ERRORS => ex
|
|
1513
|
+
raise ex
|
|
1444
1514
|
|
|
1445
|
-
|
|
1446
|
-
|
|
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
|
|
1447
1520
|
end
|
|
1521
|
+
raise ex
|
|
1522
|
+
|
|
1523
|
+
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1524
|
+
raise ex
|
|
1448
1525
|
end
|
|
1449
1526
|
|
|
1450
1527
|
def query(query, parse = false)
|
|
1451
|
-
output_xml, input_xml = self.soap_call(
|
|
1528
|
+
output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true) do |xml|
|
|
1452
1529
|
xml['ns1'].query do
|
|
1453
1530
|
xml['ns1'].queryString query
|
|
1454
1531
|
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
|
|
@@ -48,45 +50,26 @@ module ZuoraAPI
|
|
|
48
50
|
end
|
|
49
51
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
50
52
|
if !tries.zero?
|
|
51
|
-
tries -= 1
|
|
53
|
+
@tries -= 1
|
|
52
54
|
Rails.logger.debug {"Session Invalid"}
|
|
53
55
|
self.new_session(auth_type: :bearer)
|
|
54
56
|
retry
|
|
55
57
|
end
|
|
56
58
|
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
59
|
end
|
|
76
60
|
|
|
77
61
|
def get_bearer_token(zuora_track_id: nil)
|
|
78
|
-
tries ||= 2
|
|
79
62
|
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
63
|
|
|
81
64
|
headers = { "content-type" => "application/x-www-form-urlencoded" }
|
|
82
65
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
83
66
|
|
|
84
67
|
output_json, response = self.rest_call(:method => :post,
|
|
85
|
-
:
|
|
86
|
-
:
|
|
87
|
-
:
|
|
88
|
-
:
|
|
89
|
-
:
|
|
68
|
+
url: self.rest_endpoint.chomp('v1/').concat("oauth/token"),
|
|
69
|
+
z_session: false,
|
|
70
|
+
timeout_retry: true,
|
|
71
|
+
headers: headers,
|
|
72
|
+
body: {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"}
|
|
90
73
|
)
|
|
91
74
|
|
|
92
75
|
self.bearer_token = output_json["access_token"]
|
|
@@ -96,44 +79,6 @@ module ZuoraAPI
|
|
|
96
79
|
self.status = 'Active'
|
|
97
80
|
|
|
98
81
|
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
82
|
end
|
|
138
83
|
|
|
139
84
|
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.66f
|
|
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-14 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
|