zuora_api 1.7.66b → 1.7.66h
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +2 -1
- data/Gemfile +1 -1
- data/lib/zuora_api/exceptions.rb +13 -0
- data/lib/zuora_api/login.rb +267 -189
- data/lib/zuora_api/logins/basic.rb +10 -101
- data/lib/zuora_api/logins/oauth.rb +17 -83
- 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: f249f52bbfd3bc0ab1973ecdfa9bacf5d61d8c115f2c84a662c35df5479ffe88
|
|
4
|
+
data.tar.gz: 486c87116df598676c3939b0ef9bb15be136b1d84d5836077ab382476eedfd3a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85cdae2878399c64bd5bda7bcffb7e18b57651abebcf6d909efaa11d0af253103232c70229db86f5564b18ef24dce3b1f4c3fa56ffa67bd98905e7920352974e
|
|
7
|
+
data.tar.gz: b7db4bcfa9cab99ca10f9545ccfeba97a75f555fd64d718ea3d9f267706c9339e2af0f47837d1cecc53c624b901158881d870051b522af2894b12e9afb84b6d9
|
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
|
|
@@ -428,16 +456,18 @@ module ZuoraAPI
|
|
|
428
456
|
def soap_call(
|
|
429
457
|
ns1: 'ns1',
|
|
430
458
|
ns2: 'ns2',
|
|
431
|
-
batch_size: nil,
|
|
459
|
+
batch_size: nil,
|
|
460
|
+
headers: {},
|
|
432
461
|
single_transaction: false,
|
|
433
462
|
debug: false,
|
|
434
463
|
zuora_track_id: nil,
|
|
435
464
|
errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
|
|
436
465
|
z_session: true,
|
|
437
466
|
timeout_retry: false,
|
|
438
|
-
timeout:
|
|
467
|
+
timeout: 130,
|
|
439
468
|
timeout_sleep_interval: self.timeout_sleep,
|
|
440
469
|
output_exception_messages: true,
|
|
470
|
+
skip_session: false,
|
|
441
471
|
**keyword_args)
|
|
442
472
|
tries ||= 2
|
|
443
473
|
xml = Nokogiri::XML::Builder.new do |xml|
|
|
@@ -447,8 +477,10 @@ module ZuoraAPI
|
|
|
447
477
|
'xmlns:api' => "http://api.zuora.com/",
|
|
448
478
|
"xmlns:#{ns1}" => "http://api.zuora.com/") do
|
|
449
479
|
xml['SOAP-ENV'].Header do
|
|
450
|
-
|
|
451
|
-
xml["#{ns1}"].
|
|
480
|
+
if !skip_session
|
|
481
|
+
xml["#{ns1}"].SessionHeader do
|
|
482
|
+
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
483
|
+
end
|
|
452
484
|
end
|
|
453
485
|
if single_transaction
|
|
454
486
|
xml["#{ns1}"].CallOptions do
|
|
@@ -466,12 +498,11 @@ module ZuoraAPI
|
|
|
466
498
|
end
|
|
467
499
|
end
|
|
468
500
|
end
|
|
469
|
-
|
|
470
501
|
input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
|
471
502
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
|
472
503
|
Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
473
504
|
|
|
474
|
-
headers
|
|
505
|
+
headers.merge!({ 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'})
|
|
475
506
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
476
507
|
|
|
477
508
|
request = HTTParty::Request.new(
|
|
@@ -488,7 +519,11 @@ module ZuoraAPI
|
|
|
488
519
|
Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
489
520
|
|
|
490
521
|
raise_errors(type: :SOAP, body: output_xml, response: response)
|
|
522
|
+
|
|
523
|
+
return output_xml, input_xml, response
|
|
524
|
+
|
|
491
525
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
526
|
+
raise if skip_session
|
|
492
527
|
if !tries.zero? && z_session
|
|
493
528
|
tries -= 1
|
|
494
529
|
Rails.logger.debug("SOAP Call - Session Invalid")
|
|
@@ -513,24 +548,20 @@ module ZuoraAPI
|
|
|
513
548
|
return output_xml, input_xml, response
|
|
514
549
|
|
|
515
550
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
516
|
-
if tries.zero?
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
522
|
-
end
|
|
523
|
-
end
|
|
524
|
-
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
|
|
525
556
|
end
|
|
526
557
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
558
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
559
|
+
raise ex
|
|
560
|
+
|
|
530
561
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
531
562
|
if !tries.zero?
|
|
532
563
|
tries -= 1
|
|
533
|
-
|
|
564
|
+
self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
534
565
|
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
535
566
|
retry
|
|
536
567
|
elsif timeout_retry
|
|
@@ -539,19 +570,79 @@ module ZuoraAPI
|
|
|
539
570
|
end
|
|
540
571
|
end
|
|
541
572
|
|
|
542
|
-
if output_exception_messages
|
|
543
|
-
|
|
544
|
-
Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
545
|
-
else
|
|
546
|
-
Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
547
|
-
end
|
|
548
|
-
end
|
|
549
|
-
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)
|
|
550
575
|
raise ex
|
|
576
|
+
|
|
551
577
|
rescue => ex
|
|
552
578
|
raise ex
|
|
553
|
-
|
|
554
|
-
|
|
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
|
|
555
646
|
end
|
|
556
647
|
|
|
557
648
|
def raise_errors(type: :SOAP, body: nil, response: nil)
|
|
@@ -568,13 +659,13 @@ module ZuoraAPI
|
|
|
568
659
|
end
|
|
569
660
|
|
|
570
661
|
if [502,503].include?(response.code)
|
|
571
|
-
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)
|
|
572
663
|
end
|
|
573
664
|
|
|
574
665
|
# Check failure response code
|
|
575
666
|
case response.code
|
|
576
667
|
when 504
|
|
577
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from
|
|
668
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response)
|
|
578
669
|
when 429
|
|
579
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)
|
|
580
671
|
when 401
|
|
@@ -595,6 +686,10 @@ module ZuoraAPI
|
|
|
595
686
|
when :SOAP
|
|
596
687
|
error, success, message = get_soap_error_and_message(body)
|
|
597
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
|
+
|
|
598
693
|
if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
|
|
599
694
|
body.xpath(
|
|
600
695
|
'//ns1:records[@xsi:type="ns2:Export"]',
|
|
@@ -699,7 +794,11 @@ module ZuoraAPI
|
|
|
699
794
|
end
|
|
700
795
|
|
|
701
796
|
if body['error'] == 'Unauthorized' && body['status'] == 401
|
|
702
|
-
|
|
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
|
|
703
802
|
end
|
|
704
803
|
#Authentication failed
|
|
705
804
|
if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
|
|
@@ -955,7 +1054,7 @@ module ZuoraAPI
|
|
|
955
1054
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
|
956
1055
|
url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
|
|
957
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"}
|
|
958
|
-
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)
|
|
959
1058
|
|
|
960
1059
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
|
|
961
1060
|
|
|
@@ -988,35 +1087,31 @@ module ZuoraAPI
|
|
|
988
1087
|
end
|
|
989
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
|
|
990
1089
|
end
|
|
1090
|
+
|
|
1091
|
+
return des_hash
|
|
991
1092
|
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
992
|
-
if tries.zero?
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
Rails.logger.error("Describe - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
|
|
998
|
-
end
|
|
999
|
-
end
|
|
1000
|
-
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
|
|
1001
1098
|
end
|
|
1002
1099
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1100
|
+
self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors
|
|
1101
|
+
raise ex
|
|
1102
|
+
|
|
1006
1103
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1007
1104
|
if !tries.zero? && self.status == 'Active'
|
|
1008
1105
|
tries -= 1
|
|
1009
1106
|
Rails.logger.debug("Describe session expired. Starting new session.")
|
|
1010
1107
|
self.new_session
|
|
1011
1108
|
retry
|
|
1012
|
-
else
|
|
1013
|
-
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1014
|
-
raise ex
|
|
1015
1109
|
end
|
|
1110
|
+
|
|
1111
|
+
Rails.logger.error("Describe session expired. Starting new session.") if log_errors
|
|
1112
|
+
raise ex
|
|
1016
1113
|
rescue => ex
|
|
1017
1114
|
raise ex
|
|
1018
|
-
else
|
|
1019
|
-
return des_hash
|
|
1020
1115
|
end
|
|
1021
1116
|
|
|
1022
1117
|
def rest_call(
|
|
@@ -1029,11 +1124,12 @@ module ZuoraAPI
|
|
|
1029
1124
|
z_session: true,
|
|
1030
1125
|
session_type: :basic,
|
|
1031
1126
|
timeout_retry: false,
|
|
1032
|
-
timeout:
|
|
1127
|
+
timeout: 130,
|
|
1033
1128
|
timeout_sleep_interval: self.timeout_sleep,
|
|
1034
1129
|
multipart: false,
|
|
1035
1130
|
stream_body: false,
|
|
1036
1131
|
output_exception_messages: true,
|
|
1132
|
+
zuora_track_id: nil,
|
|
1037
1133
|
**keyword_args,
|
|
1038
1134
|
&block
|
|
1039
1135
|
)
|
|
@@ -1043,12 +1139,13 @@ module ZuoraAPI
|
|
|
1043
1139
|
|
|
1044
1140
|
authentication_headers = {}
|
|
1045
1141
|
if z_session
|
|
1046
|
-
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) }
|
|
1047
1143
|
if self.entity_id.present?
|
|
1048
1144
|
authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
|
1049
1145
|
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
|
1050
1146
|
end
|
|
1051
1147
|
end
|
|
1148
|
+
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
1052
1149
|
|
|
1053
1150
|
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
|
1054
1151
|
|
|
@@ -1074,10 +1171,12 @@ module ZuoraAPI
|
|
|
1074
1171
|
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
|
1075
1172
|
|
|
1076
1173
|
raise_errors(type: :JSON, body: output_json, response: response)
|
|
1077
|
-
rescue
|
|
1174
|
+
rescue => ex
|
|
1078
1175
|
reset_files(body) if multipart
|
|
1079
1176
|
raise
|
|
1080
1177
|
end
|
|
1178
|
+
|
|
1179
|
+
return [output_json, response]
|
|
1081
1180
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
|
1082
1181
|
if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
|
|
1083
1182
|
session_type = :bearer
|
|
@@ -1112,23 +1211,21 @@ module ZuoraAPI
|
|
|
1112
1211
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1113
1212
|
raise ex
|
|
1114
1213
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
1115
|
-
if tries.zero?
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1121
|
-
end
|
|
1122
|
-
end
|
|
1123
|
-
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
|
|
1124
1219
|
end
|
|
1125
1220
|
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1221
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
|
|
1222
|
+
raise ex
|
|
1223
|
+
|
|
1129
1224
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
1225
|
+
|
|
1130
1226
|
if !tries.zero?
|
|
1131
1227
|
tries -= 1
|
|
1228
|
+
self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
|
|
1132
1229
|
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
1133
1230
|
retry
|
|
1134
1231
|
elsif timeout_retry
|
|
@@ -1136,20 +1233,15 @@ module ZuoraAPI
|
|
|
1136
1233
|
retry
|
|
1137
1234
|
end
|
|
1138
1235
|
end
|
|
1139
|
-
|
|
1140
|
-
if output_exception_messages
|
|
1141
|
-
|
|
1142
|
-
Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
|
|
1143
|
-
else
|
|
1144
|
-
Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
|
|
1145
|
-
end
|
|
1146
|
-
end
|
|
1147
|
-
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)
|
|
1148
1239
|
raise ex
|
|
1240
|
+
|
|
1149
1241
|
rescue => ex
|
|
1150
1242
|
raise ex
|
|
1151
|
-
|
|
1152
|
-
|
|
1243
|
+
ensure
|
|
1244
|
+
self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
|
|
1153
1245
|
end
|
|
1154
1246
|
|
|
1155
1247
|
def update_create_tenant
|
|
@@ -1171,8 +1263,9 @@ module ZuoraAPI
|
|
|
1171
1263
|
while !response["nextPage"].blank?
|
|
1172
1264
|
url = self.rest_endpoint(response["nextPage"].split('/v1/').last)
|
|
1173
1265
|
Rails.logger.debug("Fetch Catalog URL #{url}")
|
|
1174
|
-
output_json, response = self.rest_call(:
|
|
1175
|
-
|
|
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
|
|
1176
1269
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
|
|
1177
1270
|
end
|
|
1178
1271
|
output_json["products"].each do |product|
|
|
@@ -1198,7 +1291,7 @@ module ZuoraAPI
|
|
|
1198
1291
|
return products, catalog_map
|
|
1199
1292
|
end
|
|
1200
1293
|
|
|
1201
|
-
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)
|
|
1202
1295
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
|
1203
1296
|
|
|
1204
1297
|
retry_count ||= timeout_retries
|
|
@@ -1306,12 +1399,10 @@ module ZuoraAPI
|
|
|
1306
1399
|
if !(retry_count -= 1).zero?
|
|
1307
1400
|
self.new_session
|
|
1308
1401
|
raise response.class
|
|
1309
|
-
else
|
|
1310
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1311
1402
|
end
|
|
1312
|
-
|
|
1313
|
-
raise
|
|
1403
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
|
1314
1404
|
end
|
|
1405
|
+
raise
|
|
1315
1406
|
else
|
|
1316
1407
|
raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
|
|
1317
1408
|
end
|
|
@@ -1321,133 +1412,120 @@ module ZuoraAPI
|
|
|
1321
1412
|
sleep(5)
|
|
1322
1413
|
if (retry_count -= 1) >= 0
|
|
1323
1414
|
retry
|
|
1324
|
-
else
|
|
1325
|
-
Rails.logger.error("File Download Failed")
|
|
1326
|
-
raise
|
|
1327
1415
|
end
|
|
1416
|
+
Rails.logger.error("File Download Failed")
|
|
1417
|
+
raise
|
|
1328
1418
|
end
|
|
1329
1419
|
|
|
1330
1420
|
def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
xml['SOAP-ENV'].
|
|
1335
|
-
xml['
|
|
1336
|
-
xml['ns1'].
|
|
1337
|
-
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
|
|
1338
|
-
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)
|
|
1339
1427
|
end
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
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
|
|
1349
1437
|
end
|
|
1350
1438
|
end
|
|
1351
1439
|
end
|
|
1352
1440
|
end
|
|
1441
|
+
end
|
|
1353
1442
|
|
|
1354
|
-
|
|
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)
|
|
1355
1444
|
|
|
1356
|
-
|
|
1357
|
-
|
|
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"
|
|
1358
1447
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
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
|
|
1362
1451
|
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
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)
|
|
1369
1457
|
end
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
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}'"
|
|
1374
1462
|
end
|
|
1375
1463
|
end
|
|
1376
1464
|
end
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
while result != "Completed"
|
|
1380
|
-
sleep 3
|
|
1381
|
-
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)
|
|
1382
|
-
|
|
1383
|
-
output_xml = Nokogiri::XML(response_query.body)
|
|
1384
|
-
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
|
1385
|
-
status_code = response_query.code if response_query
|
|
1465
|
+
end
|
|
1466
|
+
result = 'Waiting'
|
|
1386
1467
|
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
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)
|
|
1390
1471
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
Rails.logger.debug("=====> Export path #{export_file.path}")
|
|
1395
|
-
|
|
1396
|
-
if extract && zip
|
|
1397
|
-
require "zip"
|
|
1398
|
-
new_path = export_file_path.partition('.zip').first
|
|
1399
|
-
zipped = Zip::File.open(export_file_path)
|
|
1400
|
-
file_handle = zipped.entries.first
|
|
1401
|
-
file_handle.extract(new_path)
|
|
1402
|
-
File.delete(export_file_path)
|
|
1403
|
-
return new_path
|
|
1404
|
-
else
|
|
1405
|
-
return export_file_path
|
|
1406
|
-
end
|
|
1407
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
1408
|
-
if !(tries -= 1).zero?
|
|
1409
|
-
Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
|
|
1410
|
-
self.new_session
|
|
1411
|
-
retry
|
|
1412
|
-
else
|
|
1413
|
-
raise ex
|
|
1414
|
-
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
|
|
1415
1475
|
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
sleep 10
|
|
1420
|
-
retry
|
|
1421
|
-
else
|
|
1422
|
-
raise ex
|
|
1423
|
-
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
|
|
1424
1479
|
|
|
1425
|
-
|
|
1426
|
-
|
|
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
|
|
1427
1503
|
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
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
|
|
1436
1511
|
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
retry
|
|
1440
|
-
else
|
|
1441
|
-
raise ex
|
|
1442
|
-
end
|
|
1512
|
+
rescue *ZUORA_API_ERRORS => ex
|
|
1513
|
+
raise ex
|
|
1443
1514
|
|
|
1444
|
-
|
|
1445
|
-
|
|
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
|
|
1446
1520
|
end
|
|
1521
|
+
raise ex
|
|
1522
|
+
|
|
1523
|
+
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
1524
|
+
raise ex
|
|
1447
1525
|
end
|
|
1448
1526
|
|
|
1449
1527
|
def query(query, parse = false)
|
|
1450
|
-
output_xml, input_xml = self.soap_call(
|
|
1528
|
+
output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true) do |xml|
|
|
1451
1529
|
xml['ns1'].query do
|
|
1452
1530
|
xml['ns1'].queryString query
|
|
1453
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
|
|
@@ -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,51 +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 if errors.include?(ex.class)
|
|
57
|
-
return [output_json, response]
|
|
58
|
-
|
|
59
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
|
60
|
-
raise ex if errors.include?(ex.class)
|
|
61
|
-
return [output_json, response]
|
|
62
|
-
|
|
63
|
-
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
64
|
-
if !tries.zero?
|
|
65
|
-
tries -= 1
|
|
66
|
-
sleep(self.timeout_sleep)
|
|
67
|
-
retry
|
|
68
|
-
end
|
|
69
|
-
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
70
|
-
Rails.logger.error("OAuthLogin - Timed out", ex)
|
|
71
|
-
else
|
|
72
|
-
Rails.logger.error("OAuthLogin - #{ex.class} Timed out")
|
|
73
|
-
end
|
|
74
|
-
self.current_error = "Request timed out. Try again"
|
|
75
|
-
self.status = 'Timeout'
|
|
76
|
-
return self.status
|
|
77
50
|
end
|
|
78
51
|
|
|
79
52
|
def get_bearer_token(zuora_track_id: nil)
|
|
80
|
-
tries ||= 2
|
|
81
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?
|
|
82
54
|
|
|
83
55
|
headers = { "content-type" => "application/x-www-form-urlencoded" }
|
|
84
56
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
85
57
|
|
|
86
58
|
output_json, response = self.rest_call(:method => :post,
|
|
87
|
-
:
|
|
88
|
-
:
|
|
89
|
-
:
|
|
90
|
-
:
|
|
91
|
-
:
|
|
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"}
|
|
92
64
|
)
|
|
93
65
|
|
|
94
66
|
self.bearer_token = output_json["access_token"]
|
|
@@ -98,44 +70,6 @@ module ZuoraAPI
|
|
|
98
70
|
self.status = 'Active'
|
|
99
71
|
|
|
100
72
|
return self.status
|
|
101
|
-
|
|
102
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex
|
|
103
|
-
raise ex if tries.zero?
|
|
104
|
-
|
|
105
|
-
tries -= 1
|
|
106
|
-
sleep(self.timeout_sleep)
|
|
107
|
-
retry
|
|
108
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
109
|
-
self.bearer_token = nil
|
|
110
|
-
self.oauth_session_expires_at = nil
|
|
111
|
-
self.current_error = ex.message
|
|
112
|
-
case ex.message
|
|
113
|
-
when "Forbidden"
|
|
114
|
-
self.current_error = "The user associated to OAuth credential set has been deactivated."
|
|
115
|
-
self.status = 'Deactivated'
|
|
116
|
-
else
|
|
117
|
-
self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
|
|
118
|
-
self.status = 'Invalid Login'
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
return self.status
|
|
122
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
|
123
|
-
raise ex
|
|
124
|
-
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
125
|
-
if !tries.zero?
|
|
126
|
-
tries -= 1
|
|
127
|
-
sleep(self.timeout_sleep)
|
|
128
|
-
retry
|
|
129
|
-
else
|
|
130
|
-
if Rails.logger.class.to_s == "Ougai::Logger"
|
|
131
|
-
Rails.logger.error("OAuthLogin - Timed out will retry after #{self.timeout_sleep} seconds", ex)
|
|
132
|
-
else
|
|
133
|
-
Rails.logger.error("OAuthLogin - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
|
|
134
|
-
end
|
|
135
|
-
self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
|
|
136
|
-
self.status = 'Timeout'
|
|
137
|
-
return self.status
|
|
138
|
-
end
|
|
139
73
|
end
|
|
140
74
|
|
|
141
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.66h
|
|
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-16 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
|