zuora_api 1.7.65i → 1.7.66f

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d3a5ce233d3d4b441e52a9d4342db32d616d2bcd23e650ad0e5c09208b5904e
4
- data.tar.gz: 5c1acb4964d32582cb84a05b0b120bde86d3d572fbeb663dff5ad2a58e228448
3
+ metadata.gz: b2ec277d17da6045065c52d109e4e46c6c4abfb9b0024e1196536fd1e3713dd9
4
+ data.tar.gz: f6341f70793093543d78c26028ce8bd7e347d6bdb56bddcf2a3eacacaa3e1d8d
5
5
  SHA512:
6
- metadata.gz: 45f208500da4b73e03a91fd9381fb5408f2007d62f698b97c74a46c5e71616e5b312fd0beaf00a19b977aab868850b83c03e4f8910fa1f2292666e13204e8598
7
- data.tar.gz: '06791a0a95a2031edb03efa889d35f7721f129d3e8318565e7b6a86fef6a2539b361f1ca1fe27e8470b7a43e5d6d29c463de1b0710451f539353b51e599b5903'
6
+ metadata.gz: d9d5c64f3a17b2bab098eed68c888752ad781df5095ae39cce33ba74687cae36785481313dc8915a633788ba52d7fd32feb696fdeb07cd6fc4d3012a146fb2bc
7
+ data.tar.gz: 84ac3d58829be07766fa31cbb964aea48d73da0d77a88ea92067622508ce3296bbda4b153119c08c7b2f19dbc8341e74ac04d9abce7ef1c363a568a7ee9fa1de
@@ -1,4 +1,4 @@
1
- image: ruby:2.6
1
+ image: ruby:2.7
2
2
  stages:
3
3
  - setup
4
4
  - test
@@ -35,6 +35,7 @@ rspec-testing:
35
35
  script:
36
36
  - bundle install
37
37
  - rspec
38
+ coverage: '/\(\d+.\d+\%\) covered/'
38
39
 
39
40
  rubygems-deploy:
40
41
  stage: deploy
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
-
2
+ ruby "2.7.1"
3
3
  # Specify your gem's dependencies in zuora.gemspec
4
4
  gemspec
@@ -40,6 +40,19 @@ module ZuoraAPI
40
40
  def to_s
41
41
  @message || @default_message
42
42
  end
43
+
44
+ def parse_message(message)
45
+ case message
46
+ when /^Invalid Oauth Client Id$/, /^Unable to generate token.$/
47
+ @message = "Invalid login, please check client ID and Client Secret or URL endpoint"
48
+ when /^Forbidden$/
49
+ @message = "The user associated to OAuth credential set has been deactivated."
50
+ when /^Invalid login. User name and password do not match.$/
51
+ @message = "Invalid login, please check username and password or URL endpoint"
52
+ else
53
+ @message = message
54
+ end
55
+ end
43
56
  end
44
57
 
45
58
  class BadEntityError < Error
@@ -177,14 +190,15 @@ module ZuoraAPI
177
190
  end
178
191
 
179
192
  class ZuoraAPITemporaryError < Error
180
- attr_reader :code, :response
193
+ attr_reader :code, :response, :errors
181
194
  attr_writer :default_message
182
195
 
183
- def initialize(message = nil,response=nil, errors = [], successes = [], *args)
196
+ def initialize(message = nil, response = nil, errors = [], successes = [], *args)
184
197
  @code = response.class.to_s == "HTTParty::Response" ? response.code : nil
185
198
  @message = parse_message(message)
186
199
  @response = response
187
200
  @default_message = "There is a temporary error with zuora system."
201
+ @errors = errors
188
202
  end
189
203
 
190
204
  def to_s
@@ -39,8 +39,8 @@ module ZuoraAPI
39
39
 
40
40
  ZUORA_SERVER_ERRORS = [
41
41
  ZuoraAPI::Exceptions::ZuoraAPIInternalServerError,
42
- ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout,
43
- ZuoraAPI::Exceptions::ZuoraAPIReadTimeout,
42
+ ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout,
43
+ ZuoraAPI::Exceptions::ZuoraAPIReadTimeout,
44
44
  ZuoraAPI::Exceptions::ZuoraUnexpectedError
45
45
  ].freeze
46
46
 
@@ -374,8 +374,8 @@ module ZuoraAPI
374
374
  return domain ? endpoint.concat(prefix).concat(url) : prefix.concat(url)
375
375
  end
376
376
 
377
- def rest_domain
378
- return URI(self.rest_endpoint).host
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) if self.status == 'Active'
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: 120,
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
- xml["#{ns1}"].SessionHeader do
451
- xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
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 = { 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'}
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")
@@ -500,39 +535,33 @@ module ZuoraAPI
500
535
  end
501
536
 
502
537
  retry
503
- else
504
- if errors.include?(ex.class)
505
- raise ex
506
- else
507
- return output_xml, input_xml, response
508
- end
509
538
  end
539
+
540
+ raise ex if errors.include?(ex.class)
541
+
542
+ return output_xml, input_xml, response
543
+
510
544
  rescue *ZUORA_API_ERRORS => ex
511
- if errors.include?(ex.class)
512
- raise ex
513
- else
514
- response = ex.response unless response
515
- return output_xml, input_xml, response
516
- end
545
+ raise ex if errors.include?(ex.class)
546
+
547
+ response = ex.response unless response
548
+ return output_xml, input_xml, response
549
+
517
550
  rescue *CONNECTION_EXCEPTIONS => ex
518
- if tries.zero?
519
- if output_exception_messages
520
- if Rails.logger.class.to_s == "Ougai::Logger"
521
- Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
522
- else
523
- Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
524
- end
525
- end
526
- 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
527
556
  end
528
557
 
529
- tries -= 1
530
- sleep(timeout_sleep_interval)
531
- retry
558
+ self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
559
+ raise ex
560
+
532
561
  rescue *CONNECTION_READ_EXCEPTIONS => ex
533
562
  if !tries.zero?
534
563
  tries -= 1
535
-
564
+ self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
536
565
  if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
537
566
  retry
538
567
  elsif timeout_retry
@@ -541,19 +570,79 @@ module ZuoraAPI
541
570
  end
542
571
  end
543
572
 
544
- if output_exception_messages
545
- if Rails.logger.class.to_s == "Ougai::Logger"
546
- Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
547
- else
548
- Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
549
- end
550
- end
551
- 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)
552
575
  raise ex
576
+
553
577
  rescue => ex
554
578
  raise ex
555
- else
556
- return output_xml, input_xml, response
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
557
646
  end
558
647
 
559
648
  def raise_errors(type: :SOAP, body: nil, response: nil)
@@ -570,13 +659,13 @@ module ZuoraAPI
570
659
  end
571
660
 
572
661
  if [502,503].include?(response.code)
573
- raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from #{request_uri}", response)
662
+ raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from 'https://#{rest_domain(endpoint: request_uri)}'", response)
574
663
  end
575
664
 
576
665
  # Check failure response code
577
666
  case response.code
578
667
  when 504
579
- raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{request_uri}", response)
668
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response)
580
669
  when 429
581
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)
582
671
  when 401
@@ -597,6 +686,10 @@ module ZuoraAPI
597
686
  when :SOAP
598
687
  error, success, message = get_soap_error_and_message(body)
599
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
+
600
693
  if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
601
694
  body.xpath(
602
695
  '//ns1:records[@xsi:type="ns2:Export"]',
@@ -658,6 +751,10 @@ module ZuoraAPI
658
751
  when /^GET::400::\/api\/rest\/v1\/reports\/(reportlabels\/)?([a-zA-Z0-9\-_]+)\/report-details$/ # Get report, capture of the id is present if needed in future error responses.
659
752
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
660
753
  end
754
+ when /\/objects\/batch\//
755
+ if body['code'].present? && /61$/.match(body['code'].to_s).present? # if last 2 digits of code are 61
756
+ raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body['message'], nil, body['details'])
757
+ end
661
758
  end
662
759
 
663
760
  body = body.dig("results").present? ? body["results"] : body if body.class == Hash
@@ -697,7 +794,11 @@ module ZuoraAPI
697
794
  end
698
795
 
699
796
  if body['error'] == 'Unauthorized' && body['status'] == 401
700
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
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
701
802
  end
702
803
  #Authentication failed
703
804
  if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
@@ -953,7 +1054,7 @@ module ZuoraAPI
953
1054
  base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
954
1055
  url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
955
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"}
956
- response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
1057
+ response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 130)
957
1058
 
958
1059
  raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
959
1060
 
@@ -986,35 +1087,31 @@ module ZuoraAPI
986
1087
  end
987
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
988
1089
  end
1090
+
1091
+ return des_hash
989
1092
  rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
990
- if tries.zero?
991
- if log_errors
992
- if Rails.logger.class.to_s == "Ougai::Logger"
993
- Rails.logger.error("Describe - Timed out will retry after #{self.timeout_sleep} seconds", ex)
994
- else
995
- Rails.logger.error("Describe - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
996
- end
997
- end
998
- 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
999
1098
  end
1000
1099
 
1001
- tries -= 1
1002
- sleep(self.timeout_sleep)
1003
- retry
1100
+ self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors
1101
+ raise ex
1102
+
1004
1103
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1005
1104
  if !tries.zero? && self.status == 'Active'
1006
1105
  tries -= 1
1007
1106
  Rails.logger.debug("Describe session expired. Starting new session.")
1008
1107
  self.new_session
1009
1108
  retry
1010
- else
1011
- Rails.logger.error("Describe session expired. Starting new session.") if log_errors
1012
- raise ex
1013
1109
  end
1110
+
1111
+ Rails.logger.error("Describe session expired. Starting new session.") if log_errors
1112
+ raise ex
1014
1113
  rescue => ex
1015
1114
  raise ex
1016
- else
1017
- return des_hash
1018
1115
  end
1019
1116
 
1020
1117
  def rest_call(
@@ -1027,11 +1124,12 @@ module ZuoraAPI
1027
1124
  z_session: true,
1028
1125
  session_type: :basic,
1029
1126
  timeout_retry: false,
1030
- timeout: 120,
1127
+ timeout: 130,
1031
1128
  timeout_sleep_interval: self.timeout_sleep,
1032
1129
  multipart: false,
1033
1130
  stream_body: false,
1034
1131
  output_exception_messages: true,
1132
+ zuora_track_id: nil,
1035
1133
  **keyword_args,
1036
1134
  &block
1037
1135
  )
@@ -1041,12 +1139,13 @@ module ZuoraAPI
1041
1139
 
1042
1140
  authentication_headers = {}
1043
1141
  if z_session
1044
- 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) }
1045
1143
  if self.entity_id.present?
1046
1144
  authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
1047
1145
  authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
1048
1146
  end
1049
1147
  end
1148
+ headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
1050
1149
 
1051
1150
  modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
1052
1151
 
@@ -1072,18 +1171,20 @@ module ZuoraAPI
1072
1171
  Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
1073
1172
 
1074
1173
  raise_errors(type: :JSON, body: output_json, response: response)
1075
- rescue
1174
+ rescue => ex
1076
1175
  reset_files(body) if multipart
1077
1176
  raise
1078
1177
  end
1178
+
1179
+ return [output_json, response]
1079
1180
  rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
1080
1181
  if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
1081
1182
  session_type = :bearer
1082
1183
  retry
1083
- else
1084
- Rails.logger.debug("Rest Call - Session Bad Auth type")
1085
- raise ex
1086
1184
  end
1185
+ Rails.logger.debug("Rest Call - Session Bad Auth type")
1186
+ raise ex
1187
+
1087
1188
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1088
1189
  if !tries.zero? && z_session
1089
1190
  tries -= 1
@@ -1096,40 +1197,35 @@ module ZuoraAPI
1096
1197
  end
1097
1198
 
1098
1199
  retry
1099
- else
1100
- if errors.include?(ex.class)
1101
- raise ex
1102
- else
1103
- return [output_json, response]
1104
- end
1105
1200
  end
1201
+
1202
+ raise ex if errors.include?(ex.class)
1203
+ return [output_json, response]
1204
+
1106
1205
  rescue *ZUORA_API_ERRORS => ex
1107
- if errors.include?(ex.class)
1108
- raise ex
1109
- else
1110
- response = ex.response unless response
1111
- return [output_json, response]
1112
- end
1206
+ raise ex if errors.include?(ex.class)
1207
+
1208
+ response = ex.response unless response
1209
+ return [output_json, response]
1210
+
1113
1211
  rescue ZuoraAPI::Exceptions::BadEntityError => ex
1114
1212
  raise ex
1115
1213
  rescue *CONNECTION_EXCEPTIONS => ex
1116
- if tries.zero?
1117
- if output_exception_messages
1118
- if Rails.logger.class.to_s == "Ougai::Logger"
1119
- Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
1120
- else
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
- tries -= 1
1128
- sleep(timeout_sleep_interval)
1129
- retry
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
- if Rails.logger.class.to_s == "Ougai::Logger"
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
- else
1153
- return [output_json, response]
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(:debug => false, :url => url, :errors => [ZuoraAPI::Exceptions::ZuoraAPISessionError], :timeout_retry => true )
1176
- if !output_json['success'] =~ (/(true|t|yes|y|1)$/i) || output_json['success'].class != TrueClass
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: 120, session_type: :basic, **execute_params)
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
- else
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
- begin
1333
- tries ||= 3
1334
- request = Nokogiri::XML::Builder.new do |xml|
1335
- 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
1336
- xml['SOAP-ENV'].Header do
1337
- xml['ns1'].SessionHeader do
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
- xml['SOAP-ENV'].Body do
1342
- xml['ns1'].create do
1343
- xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
1344
- xml['ns2'].Format 'csv'
1345
- xml['ns2'].Zip zip
1346
- xml['ns2'].Name 'googman'
1347
- xml['ns2'].Query query
1348
- xml['ns2'].Encrypted encrypted
1349
- end
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
- 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 => 120)
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
- output_xml = Nokogiri::XML(response_query.body)
1358
- raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
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
- # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
1361
-
1362
- id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
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
- confirmRequest = Nokogiri::XML::Builder.new do |xml|
1365
- 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
1366
- xml['SOAP-ENV'].Header do
1367
- xml['ns1'].SessionHeader do
1368
- xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
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
- xml['SOAP-ENV'].Body do
1372
- xml['ns1'].query do
1373
- xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
1374
- end
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
- result = 'Waiting'
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
- raise_errors(type: :SOAP, body: output_xml, response: response_query) if result.blank? || result == "Failed"
1389
- # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if result.blank? || result == "Failed"
1390
- end
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
- file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
1393
- export_file = get_file(:url => self.fileURL(file_id))
1394
- export_file_path = export_file.path
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
- rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
1418
- if !(tries -= 1).zero?
1419
- Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
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
- rescue *ZUORA_API_ERRORS => ex
1427
- raise ex
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
- rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
1430
- if !(tries -= 1).zero?
1431
- Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
1432
- sleep 5
1433
- retry
1434
- else
1435
- raise ex
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
- rescue Errno::ECONNRESET => ex
1439
- if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
1440
- retry
1441
- else
1442
- raise ex
1443
- end
1512
+ rescue *ZUORA_API_ERRORS => ex
1513
+ raise ex
1444
1514
 
1445
- rescue ZuoraAPI::Exceptions::BadEntityError => ex
1446
- raise ex
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({:debug => false, :timeout_retry => true}) do |xml|
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
- raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
14
- raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Basic Login but either 'Username' or 'Password' were not passed.") if (self.password.blank? && self.username.blank?)
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
- tries ||= 2
17
- request = Nokogiri::XML::Builder.new do |xml|
18
- xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' =>"http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:api' => "http://api.zuora.com/" ) do
19
- xml['SOAP-ENV'].Header
20
- xml['SOAP-ENV'].Body do
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.", response_query) if retrieved_session.blank?
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
- end
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
- if auth_type == :bearer
16
- get_bearer_token(zuora_track_id: zuora_track_id)
17
- elsif auth_type == :basic
18
- get_bearer_token(zuora_track_id: zuora_track_id) if self.oauth_expired?
19
- get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
20
- else
21
- get_bearer_token(zuora_track_id: zuora_track_id)
22
- get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
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
@@ -37,52 +39,37 @@ module ZuoraAPI
37
39
  begin
38
40
  self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=')
39
41
  rescue NoMethodError => ex
40
- Rails.logger.fatal("Failure Parsing Cookie Headers", response.headers.to_s)
42
+ Rails.logger.fatal("Failure Parsing Cookie Headers", {
43
+ response: {
44
+ status: response.code,
45
+ params: response.body.to_s,
46
+ headers: response.headers.to_s,
47
+ }
48
+ })
41
49
  raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Failure Parsing Cookie Headers")
42
50
  end
43
51
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
44
52
  if !tries.zero?
45
- tries -= 1
53
+ @tries -= 1
46
54
  Rails.logger.debug {"Session Invalid"}
47
55
  self.new_session(auth_type: :bearer)
48
56
  retry
49
57
  end
50
- raise ex if errors.include?(ex.class)
51
- return [output_json, response]
52
-
53
- rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
54
- raise ex if errors.include?(ex.class)
55
- return [output_json, response]
56
-
57
- rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
58
- if !tries.zero?
59
- tries -= 1
60
- sleep(self.timeout_sleep)
61
- retry
62
- end
63
- if Rails.logger.class.to_s == "Ougai::Logger"
64
- Rails.logger.error("OAuthLogin - Timed out", ex)
65
- else
66
- Rails.logger.error("OAuthLogin - #{ex.class} Timed out")
67
- end
68
- self.current_error = "Request timed out. Try again"
69
- self.status = 'Timeout'
70
- return self.status
58
+ raise ex
71
59
  end
72
60
 
73
61
  def get_bearer_token(zuora_track_id: nil)
74
- tries ||= 2
75
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?
76
63
 
77
64
  headers = { "content-type" => "application/x-www-form-urlencoded" }
78
65
  headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
79
66
 
80
67
  output_json, response = self.rest_call(:method => :post,
81
- :url => self.rest_endpoint.chomp('v1/').concat("oauth/token"),
82
- :z_session => false,
83
- :session_type => :bearer,
84
- :headers => headers,
85
- :body => {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"}
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"}
86
73
  )
87
74
 
88
75
  self.bearer_token = output_json["access_token"]
@@ -92,44 +79,6 @@ module ZuoraAPI
92
79
  self.status = 'Active'
93
80
 
94
81
  return self.status
95
-
96
- rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex
97
- raise ex if tries.zero?
98
-
99
- tries -= 1
100
- sleep(self.timeout_sleep)
101
- retry
102
- rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
103
- self.bearer_token = nil
104
- self.oauth_session_expires_at = nil
105
- self.current_error = ex.message
106
- case ex.message
107
- when "Forbidden"
108
- self.current_error = "The user associated to OAuth credential set has been deactivated."
109
- self.status = 'Deactivated'
110
- else
111
- self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
112
- self.status = 'Invalid Login'
113
- end
114
-
115
- return self.status
116
- rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
117
- raise ex
118
- rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
119
- if !tries.zero?
120
- tries -= 1
121
- sleep(self.timeout_sleep)
122
- retry
123
- else
124
- if Rails.logger.class.to_s == "Ougai::Logger"
125
- Rails.logger.error("OAuthLogin - Timed out will retry after #{self.timeout_sleep} seconds", ex)
126
- else
127
- Rails.logger.error("OAuthLogin - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
128
- end
129
- self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
130
- self.status = 'Timeout'
131
- return self.status
132
- end
133
82
  end
134
83
 
135
84
  def oauth_expired?
@@ -1,3 +1,3 @@
1
1
  module ZuoraAPI
2
- VERSION = "1.7.65i"
2
+ VERSION = "1.7.66f"
3
3
  end
@@ -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", "~> 1.12"
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.65i
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-05-28 00:00:00.000000000 Z
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: '1.12'
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: '1.12'
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: :development
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.0.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