zuora_api 1.7.65 → 1.7.66b

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: e57efb2492106ced22eaf4a943801d0f639eab7c8e1e6c5a4a927fe556963007
4
+ data.tar.gz: e21363cc410dd6c49e5513db1fd3561ea9d13ec7390e57b7abf6b966a44314b6
5
5
  SHA512:
6
- metadata.gz: c7846e3e6df13eee656df3d122d98bf1f5694c83751836bd93810d6e3ec6ca6f88ba69b80d67cb04c9f30f4f94d2338c576eacd6d4401be0e27f9c2721f51fce
7
- data.tar.gz: '0543405827032e0d71cf4f9462d565fb94ffb8ccdd76df9e59ccf2fd099ba8f608ff3ec057f1aa2b5577bb4448c583971e550cf69c1285b47736edc1ad3b9b1f'
6
+ metadata.gz: 1869137cefa3e67accb4bd917e4466df8627cf198eff2409420c0176c8e4fe728f8a56d53297a7f7418d7f7b207a1843383c74379cfc5662ec38c19e3e05300a
7
+ data.tar.gz: 037fa29a6add8b326da59402cdd2207c65385d3046869866c3cb2a5cbc2e8935855aeba549fda5239579cf4e3aabd86ce992b3dc1c9284ee166bf8c333b95bbd
@@ -177,14 +177,15 @@ module ZuoraAPI
177
177
  end
178
178
 
179
179
  class ZuoraAPITemporaryError < Error
180
- attr_reader :code, :response
180
+ attr_reader :code, :response, :errors
181
181
  attr_writer :default_message
182
182
 
183
- def initialize(message = nil,response=nil, errors = [], successes = [], *args)
183
+ def initialize(message = nil, response = nil, errors = [], successes = [], *args)
184
184
  @code = response.class.to_s == "HTTParty::Response" ? response.code : nil
185
185
  @message = parse_message(message)
186
186
  @response = response
187
187
  @default_message = "There is a temporary error with zuora system."
188
+ @errors = errors
188
189
  end
189
190
 
190
191
  def to_s
@@ -225,13 +226,14 @@ module ZuoraAPI
225
226
  end
226
227
 
227
228
  class ZuoraAPIReadTimeout < Net::ReadTimeout
228
- attr_reader :code, :response
229
+ attr_reader :code, :response, :request
229
230
  attr_writer :default_message
230
231
 
231
- def initialize(message = nil,response=nil, errors = [], successes = [], *args)
232
+ def initialize(message = nil, response = nil, request = nil, errors = [], successes = [], *args)
232
233
  @code = response.class.to_s == "HTTParty::Response" ? response.code : nil
233
234
  @message = message
234
235
  @response = response
236
+ @request = request
235
237
  @default_message = "Authentication type is not supported by this Login"
236
238
  end
237
239
 
@@ -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
 
@@ -474,12 +474,16 @@ module ZuoraAPI
474
474
  headers = { 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'}
475
475
  headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
476
476
 
477
- response = HTTParty.post(
477
+ request = HTTParty::Request.new(
478
+ Net::HTTP::Post,
478
479
  self.url,
479
- :body => xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip,
480
- :headers => headers,
481
- :timeout => timeout
480
+ body: xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip,
481
+ headers: headers,
482
+ timeout: timeout,
482
483
  )
484
+
485
+ response = request.perform
486
+
483
487
  output_xml = Nokogiri::XML(response.body)
484
488
  Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
485
489
 
@@ -496,20 +500,18 @@ module ZuoraAPI
496
500
  end
497
501
 
498
502
  retry
499
- else
500
- if errors.include?(ex.class)
501
- raise ex
502
- else
503
- return output_xml, input_xml, response
504
- end
505
503
  end
504
+
505
+ raise ex if errors.include?(ex.class)
506
+
507
+ return output_xml, input_xml, response
508
+
506
509
  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
510
+ raise ex if errors.include?(ex.class)
511
+
512
+ response = ex.response unless response
513
+ return output_xml, input_xml, response
514
+
513
515
  rescue *CONNECTION_EXCEPTIONS => ex
514
516
  if tries.zero?
515
517
  if output_exception_messages
@@ -526,34 +528,26 @@ module ZuoraAPI
526
528
  sleep(timeout_sleep_interval)
527
529
  retry
528
530
  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
531
+ if !tries.zero?
532
+ tries -= 1
533
+
534
+ if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
535
+ retry
536
+ elsif timeout_retry
537
+ sleep(timeout_sleep_interval)
538
+ retry
536
539
  end
537
- raise ex
538
540
  end
539
541
 
540
- tries -= 1
541
-
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
547
- 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
542
+ if output_exception_messages
543
+ if Rails.logger.class.to_s == "Ougai::Logger"
544
+ Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
545
+ else
546
+ Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
554
547
  end
555
- raise ex
556
548
  end
549
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
550
+ raise ex
557
551
  rescue => ex
558
552
  raise ex
559
553
  else
@@ -561,24 +555,33 @@ module ZuoraAPI
561
555
  end
562
556
 
563
557
  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}"
558
+ request_uri, request_path, match_string = "", "", ""
559
+ if response.class.to_s == "HTTP::Message"
560
+ request_uri = response.http_header.request_uri.to_s
561
+ request_path = response.http_header.request_uri.path
562
+ match_string = "#{response.http_header.request_method}::#{response.code}::#{request_uri}"
563
+ else
564
+ request = response.request
565
+ request_uri = response.request.uri
566
+ request_path = request.path.path
567
+ match_string = "#{request.http_method.to_s.split("Net::HTTP::").last.upcase}::#{response.code}::#{request_path}"
568
+ end
566
569
 
567
570
  if [502,503].include?(response.code)
568
- raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from #{response.request.uri}", response)
571
+ raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from #{request_uri}", response)
569
572
  end
570
573
 
571
574
  # Check failure response code
572
575
  case response.code
573
576
  when 504
574
- raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{response.request.uri}", response)
577
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{request_uri}", response)
575
578
  when 429
576
579
  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
580
  when 401
578
581
 
579
582
  else
580
583
  if body.class == Hash
581
- case response.request.path.path
584
+ case request_path
582
585
  when /^\/v1\/connections$/
583
586
  response_headers = response.headers.to_h
584
587
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing cookies for authentication call", response) if response_headers['set-cookie'].blank?
@@ -602,7 +605,7 @@ module ZuoraAPI
602
605
  reason = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
603
606
  if reason.present?
604
607
  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'
608
+ 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
609
  else
607
610
  error = 'FATAL_ERROR'
608
611
  message = 'Export failed due to unknown reason. Consult api logs.'
@@ -624,23 +627,10 @@ module ZuoraAPI
624
627
  end
625
628
  end
626
629
 
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
-
630
+ self.errors_via_content_type(response: response, type: :xml)
631
+
642
632
  when :JSON
643
- case request.path.path
633
+ case request_path
644
634
  when /^\/query\/jobs.*/ #DataQuery Paths
645
635
  return if body.class != Hash
646
636
  case match_string
@@ -660,12 +650,16 @@ module ZuoraAPI
660
650
  if reporting_message&.include?("com.zuora.rest.RestUsageException: The user does not have permissions for this API.")
661
651
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response)
662
652
  elsif reporting_message&.include?("500 Internal Server Error")
663
- raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Internal Server Error. The Reporting API is down. Contact Support.")
653
+ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Internal Server Error. The Reporting API is down. Contact Support.", response)
664
654
  end
665
655
  case match_string
666
656
  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
657
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
668
658
  end
659
+ when /\/objects\/batch\//
660
+ if body['code'].present? && /61$/.match(body['code'].to_s).present? # if last 2 digits of code are 61
661
+ raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body['message'], nil, body['details'])
662
+ end
669
663
  end
670
664
 
671
665
  body = body.dig("results").present? ? body["results"] : body if body.class == Hash
@@ -726,7 +720,6 @@ module ZuoraAPI
726
720
  if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
727
721
  raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
728
722
  end
729
-
730
723
  #Internal Server Error
731
724
  if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(60)
732
725
  if messages_array.uniq.size == 1
@@ -737,6 +730,11 @@ module ZuoraAPI
737
730
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("#{messages_array.join(', ')}", response)
738
731
  end
739
732
 
733
+ #Retryiable Service Error
734
+ if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(61)
735
+ raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{messages_array.join(', ')}", response)
736
+ end
737
+
740
738
  #Request exceeded limit
741
739
  if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70)
742
740
  raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", response)
@@ -789,26 +787,56 @@ module ZuoraAPI
789
787
  end
790
788
  end
791
789
 
790
+ if body.class == Hash && body['message'].present?
791
+ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(body['message'], response) if response.code == 500
792
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['message'], response) if ![200,201].include?(response.code)
793
+ end
794
+
795
+ self.errors_via_content_type(response: response, type: :json)
796
+
792
797
  #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
798
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(response.body, response) if ![200,201].include?(response.code)
799
+ end
800
+ end
801
+
802
+ def errors_via_content_type(response: nil, type: :xml)
803
+ response_content_types = response.headers.transform_keys(&:downcase).fetch('content-type', []).first || ""
804
+
805
+ if response_content_types.include?('application/json') && type != :json
806
+ output_json = JSON.parse(response.body)
807
+ self.raise_errors(type: :JSON, body: output_json, response: response)
808
+
809
+ elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml')) and type != :xml
810
+ output_xml = Nokogiri::XML(response.body)
811
+ self.raise_errors(type: :SOAP, body: output_xml, response: response)
812
+
813
+ elsif response_content_types.include?('text/html')
814
+ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Akamai Error", response) if response.headers.fetch('server', '') == 'AkamaiGHost'
815
+
816
+ parse_body = Nokogiri::HTML(response.body)
817
+ error_title = parse_body.xpath('//h2').text
818
+ error_title = parse_body.xpath('//h1').text if error_title.blank?
819
+ error_message = parse_body.xpath('//p').text
820
+
821
+ error_message = error_title if error_message.blank?
822
+
823
+ if error_title.present?
824
+ case error_title
825
+ when /Service Unavailable/
826
+ raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
827
+ when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
828
+ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
829
+ else
830
+ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
808
831
  end
809
832
  end
833
+
834
+ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Http response body is missing", response) if response.body.blank?
810
835
  end
836
+
837
+ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(response.body, response) if response.code == 500
811
838
  end
839
+
812
840
 
813
841
  def get_soap_error_and_message(body)
814
842
  error = body.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text
@@ -872,9 +900,9 @@ module ZuoraAPI
872
900
  when /.*UNEXPECTED_ERROR/
873
901
  raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
874
902
  when /.*soapenv:Server.*/
875
- if /^Invalid value.*for type.*|^Id is invalid/.match(message).present?
903
+ if /^Invalid value.*for type.*|^Id is invalid|^date string can not be less than 19 charactors$/.match(message).present?
876
904
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
877
- elsif /^Invalid white space character \(.*\) in text to output$/.match(message).present?
905
+ elsif /^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
878
906
  raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
879
907
  end
880
908
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
@@ -1025,7 +1053,7 @@ module ZuoraAPI
1025
1053
  modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
1026
1054
 
1027
1055
  begin
1028
- response = HTTParty::Request.new(
1056
+ request = HTTParty::Request.new(
1029
1057
  "Net::HTTP::#{method.to_s.capitalize}".constantize,
1030
1058
  url,
1031
1059
  body: body,
@@ -1033,7 +1061,9 @@ module ZuoraAPI
1033
1061
  timeout: timeout,
1034
1062
  multipart: multipart,
1035
1063
  stream_body: stream_body
1036
- ).perform(&block)
1064
+ )
1065
+
1066
+ response = request.perform(&block)
1037
1067
 
1038
1068
  Rails.logger.debug("Response Code: #{response.code}") if debug
1039
1069
  begin
@@ -1052,10 +1082,10 @@ module ZuoraAPI
1052
1082
  if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
1053
1083
  session_type = :bearer
1054
1084
  retry
1055
- else
1056
- Rails.logger.debug("Rest Call - Session Bad Auth type")
1057
- raise ex
1058
1085
  end
1086
+ Rails.logger.debug("Rest Call - Session Bad Auth type")
1087
+ raise ex
1088
+
1059
1089
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1060
1090
  if !tries.zero? && z_session
1061
1091
  tries -= 1
@@ -1068,20 +1098,17 @@ module ZuoraAPI
1068
1098
  end
1069
1099
 
1070
1100
  retry
1071
- else
1072
- if errors.include?(ex.class)
1073
- raise ex
1074
- else
1075
- return [output_json, response]
1076
- end
1077
1101
  end
1102
+
1103
+ raise ex if errors.include?(ex.class)
1104
+ return [output_json, response]
1105
+
1078
1106
  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
1107
+ raise ex if errors.include?(ex.class)
1108
+
1109
+ response = ex.response unless response
1110
+ return [output_json, response]
1111
+
1085
1112
  rescue ZuoraAPI::Exceptions::BadEntityError => ex
1086
1113
  raise ex
1087
1114
  rescue *CONNECTION_EXCEPTIONS => ex
@@ -1100,34 +1127,25 @@ module ZuoraAPI
1100
1127
  sleep(timeout_sleep_interval)
1101
1128
  retry
1102
1129
  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
1130
+ if !tries.zero?
1131
+ tries -= 1
1132
+ if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
1133
+ retry
1134
+ elsif timeout_retry
1135
+ sleep(timeout_sleep_interval)
1136
+ retry
1110
1137
  end
1111
- raise ex
1112
1138
  end
1113
-
1114
- tries -= 1
1115
-
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
1139
+
1140
+ if output_exception_messages
1141
+ if Rails.logger.class.to_s == "Ougai::Logger"
1142
+ Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
1143
+ else
1144
+ Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
1128
1145
  end
1129
- raise ex
1130
1146
  end
1147
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
1148
+ raise ex
1131
1149
  rescue => ex
1132
1150
  raise ex
1133
1151
  else
@@ -1183,6 +1201,8 @@ module ZuoraAPI
1183
1201
  def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout: 120, session_type: :basic, **execute_params)
1184
1202
  raise "file_path must be of class Pathname" if file_path.class != Pathname
1185
1203
 
1204
+ retry_count ||= timeout_retries
1205
+
1186
1206
  #Make sure directory exists
1187
1207
  require 'fileutils'
1188
1208
  FileUtils.mkdir_p(file_path) unless File.exists?(file_path)
@@ -1200,7 +1220,6 @@ module ZuoraAPI
1200
1220
  headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
1201
1221
 
1202
1222
  response_save = nil
1203
- retry_count ||= timeout_retries
1204
1223
  http.request_get(uri.request_uri, headers) do |response|
1205
1224
  response_save = response
1206
1225
  status_code = response.code if response
@@ -1308,75 +1327,122 @@ module ZuoraAPI
1308
1327
  end
1309
1328
  end
1310
1329
 
1311
- def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
1312
- request = Nokogiri::XML::Builder.new do |xml|
1313
- 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
- xml['SOAP-ENV'].Header do
1315
- xml['ns1'].SessionHeader do
1316
- xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
1330
+ def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
1331
+ begin
1332
+ tries ||= 3
1333
+ request = Nokogiri::XML::Builder.new do |xml|
1334
+ 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
1335
+ xml['SOAP-ENV'].Header do
1336
+ xml['ns1'].SessionHeader do
1337
+ xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
1338
+ end
1317
1339
  end
1318
- end
1319
- xml['SOAP-ENV'].Body do
1320
- xml['ns1'].create do
1321
- xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
1322
- xml['ns2'].Format 'csv'
1323
- xml['ns2'].Zip zip
1324
- xml['ns2'].Name 'googman'
1325
- xml['ns2'].Query query
1326
- xml['ns2'].Encrypted encrypted
1340
+ xml['SOAP-ENV'].Body do
1341
+ xml['ns1'].create do
1342
+ xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
1343
+ xml['ns2'].Format 'csv'
1344
+ xml['ns2'].Zip zip
1345
+ xml['ns2'].Name 'googman'
1346
+ xml['ns2'].Query query
1347
+ xml['ns2'].Encrypted encrypted
1348
+ end
1327
1349
  end
1328
1350
  end
1329
1351
  end
1330
1352
  end
1331
- end
1332
1353
 
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)
1354
+ 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)
1334
1355
 
1335
- 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"
1337
- id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
1356
+ output_xml = Nokogiri::XML(response_query.body)
1357
+ raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
1338
1358
 
1339
- confirmRequest = Nokogiri::XML::Builder.new do |xml|
1340
- 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
- xml['SOAP-ENV'].Header do
1342
- xml['ns1'].SessionHeader do
1343
- xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
1359
+ # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
1360
+
1361
+ id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
1362
+
1363
+ confirmRequest = Nokogiri::XML::Builder.new do |xml|
1364
+ 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
1365
+ xml['SOAP-ENV'].Header do
1366
+ xml['ns1'].SessionHeader do
1367
+ xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
1368
+ end
1344
1369
  end
1345
- end
1346
- xml['SOAP-ENV'].Body do
1347
- xml['ns1'].query do
1348
- xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
1370
+ xml['SOAP-ENV'].Body do
1371
+ xml['ns1'].query do
1372
+ xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
1373
+ end
1349
1374
  end
1350
1375
  end
1351
1376
  end
1352
- end
1353
- result = 'Waiting'
1377
+ result = 'Waiting'
1354
1378
 
1355
- while result != "Completed"
1356
- 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)
1379
+ while result != "Completed"
1380
+ sleep 3
1381
+ response_query = HTTParty.post(self.url, body: confirmRequest.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8", "Z-Track-Id" => z_track_id}, :timeout => 120)
1358
1382
 
1359
- output_xml = Nokogiri::XML(response_query.body)
1360
- result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
1361
- 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"
1363
- end
1383
+ output_xml = Nokogiri::XML(response_query.body)
1384
+ result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
1385
+ status_code = response_query.code if response_query
1364
1386
 
1365
- file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
1366
- export_file = get_file(:url => self.fileURL(file_id))
1367
- export_file_path = export_file.path
1368
- Rails.logger.debug("=====> Export path #{export_file.path}")
1369
-
1370
- if extract && zip
1371
- require "zip"
1372
- new_path = export_file_path.partition('.zip').first
1373
- zipped = Zip::File.open(export_file_path)
1374
- file_handle = zipped.entries.first
1375
- file_handle.extract(new_path)
1376
- File.delete(export_file_path)
1377
- return new_path
1378
- else
1379
- return export_file_path
1387
+ raise_errors(type: :SOAP, body: output_xml, response: response_query) if result.blank? || result == "Failed"
1388
+ # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if result.blank? || result == "Failed"
1389
+ end
1390
+
1391
+ file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
1392
+ export_file = get_file(:url => self.fileURL(file_id))
1393
+ export_file_path = export_file.path
1394
+ Rails.logger.debug("=====> Export path #{export_file.path}")
1395
+
1396
+ if extract && zip
1397
+ require "zip"
1398
+ new_path = export_file_path.partition('.zip').first
1399
+ zipped = Zip::File.open(export_file_path)
1400
+ file_handle = zipped.entries.first
1401
+ file_handle.extract(new_path)
1402
+ File.delete(export_file_path)
1403
+ return new_path
1404
+ else
1405
+ return export_file_path
1406
+ end
1407
+ rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1408
+ if !(tries -= 1).zero?
1409
+ Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
1410
+ self.new_session
1411
+ retry
1412
+ else
1413
+ raise ex
1414
+ end
1415
+
1416
+ rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
1417
+ if !(tries -= 1).zero?
1418
+ Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
1419
+ sleep 10
1420
+ retry
1421
+ else
1422
+ raise ex
1423
+ end
1424
+
1425
+ rescue *ZUORA_API_ERRORS => ex
1426
+ raise ex
1427
+
1428
+ rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
1429
+ if !(tries -= 1).zero?
1430
+ Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
1431
+ sleep 5
1432
+ retry
1433
+ else
1434
+ raise ex
1435
+ end
1436
+
1437
+ rescue Errno::ECONNRESET => ex
1438
+ if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
1439
+ retry
1440
+ else
1441
+ raise ex
1442
+ end
1443
+
1444
+ rescue ZuoraAPI::Exceptions::BadEntityError => ex
1445
+ raise ex
1380
1446
  end
1381
1447
  end
1382
1448
 
@@ -37,7 +37,13 @@ module ZuoraAPI
37
37
  begin
38
38
  self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=')
39
39
  rescue NoMethodError => ex
40
- Rails.logger.fatal("Failure Parsing Cookie Headers", response.headers.to_s)
40
+ Rails.logger.fatal("Failure Parsing Cookie Headers", {
41
+ response: {
42
+ status: response.code,
43
+ params: response.body.to_s,
44
+ headers: response.headers.to_s,
45
+ }
46
+ })
41
47
  raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Failure Parsing Cookie Headers")
42
48
  end
43
49
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
@@ -46,34 +52,28 @@ module ZuoraAPI
46
52
  Rails.logger.debug {"Session Invalid"}
47
53
  self.new_session(auth_type: :bearer)
48
54
  retry
49
- else
50
- if errors.include?(ex.class)
51
- raise ex
52
- else
53
- return [output_json, response]
54
- end
55
55
  end
56
+ raise ex if errors.include?(ex.class)
57
+ return [output_json, response]
58
+
56
59
  rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
57
- if errors.include?(ex.class)
58
- raise ex
59
- else
60
- return [output_json, response]
61
- end
60
+ raise ex if errors.include?(ex.class)
61
+ return [output_json, response]
62
+
62
63
  rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
63
64
  if !tries.zero?
64
65
  tries -= 1
65
66
  sleep(self.timeout_sleep)
66
67
  retry
68
+ end
69
+ if Rails.logger.class.to_s == "Ougai::Logger"
70
+ Rails.logger.error("OAuthLogin - Timed out", ex)
67
71
  else
68
- if Rails.logger.class.to_s == "Ougai::Logger"
69
- Rails.logger.error("OAuthLogin - Timed out", ex)
70
- else
71
- Rails.logger.error("OAuthLogin - #{ex.class} Timed out")
72
- end
73
- self.current_error = "Request timed out. Try again"
74
- self.status = 'Timeout'
75
- return self.status
72
+ Rails.logger.error("OAuthLogin - #{ex.class} Timed out")
76
73
  end
74
+ self.current_error = "Request timed out. Try again"
75
+ self.status = 'Timeout'
76
+ return self.status
77
77
  end
78
78
 
79
79
  def get_bearer_token(zuora_track_id: nil)
@@ -1,3 +1,3 @@
1
1
  module ZuoraAPI
2
- VERSION = "1.7.65"
2
+ VERSION = "1.7.66b"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zuora_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.65
4
+ version: 1.7.66b
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-04-24 00:00:00.000000000 Z
11
+ date: 2020-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -182,9 +182,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
182
182
  version: '0'
183
183
  required_rubygems_version: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - ">="
185
+ - - ">"
186
186
  - !ruby/object:Gem::Version
187
- version: '0'
187
+ version: 1.3.1
188
188
  requirements: []
189
189
  rubygems_version: 3.0.3
190
190
  signing_key: