zuora_api 1.7.65 → 1.7.66g

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