zuora_api 1.7.81 → 1.8.00

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,7 +7,7 @@ module ZuoraAPI
7
7
  class Login
8
8
  ENVIRONMENTS = [TEST = 'Test', SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown', STAGING = 'Staging' ]
9
9
  REGIONS = [EU = 'EU', US = 'US', NA = 'NA' ]
10
- MIN_Endpoints = {'Test': '107.0', 'Sandbox': '107.0', 'Production': '107.0', 'Performance': '107.0', 'Services': '96.0', 'Unknown': '96.0', 'Staging': '107.0'}.freeze
10
+ MIN_Endpoint = '96.0'
11
11
  XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
12
12
 
13
13
  CONNECTION_EXCEPTIONS = [
@@ -21,7 +21,7 @@ module ZuoraAPI
21
21
  ].freeze
22
22
 
23
23
  CONNECTION_READ_EXCEPTIONS = [
24
- Timeout::Error,
24
+ Net::ReadTimeout,
25
25
  Errno::ECONNRESET,
26
26
  Errno::EPIPE
27
27
  ].freeze
@@ -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
 
@@ -50,12 +50,10 @@ module ZuoraAPI
50
50
  raise "URL is nil or empty, but URL is required" if url.nil? || url.empty?
51
51
  # raise "URL is improper. URL must contain zuora.com, zuora.eu, or zuora.na" if /zuora.com|zuora.eu|zuora.na/ === url
52
52
  self.hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil?
53
- self.update_environment
54
- min_endpoint = MIN_Endpoints[self.environment.to_sym]
55
53
  if !/apps\/services\/a\/\d+\.\d$/.match(url.strip)
56
- self.url = "https://#{hostname}/apps/services/a/#{min_endpoint}"
57
- elsif min_endpoint.to_f > url.scan(/(\d+\.\d)$/).dig(0,0).to_f
58
- self.url = url.gsub(/(\d+\.\d)$/, min_endpoint)
54
+ self.url = "https://#{hostname}/apps/services/a/#{MIN_Endpoint}"
55
+ elsif MIN_Endpoint.to_f > url.scan(/(\d+\.\d)$/).dig(0,0).to_f
56
+ self.url = url.gsub(/(\d+\.\d)$/, MIN_Endpoint)
59
57
  else
60
58
  self.url = url
61
59
  end
@@ -67,6 +65,7 @@ module ZuoraAPI
67
65
  self.status = status.blank? ? "Active" : status
68
66
  self.user_info = Hash.new
69
67
  self.update_region
68
+ self.update_environment
70
69
  self.update_zconnect_provider
71
70
  @timeout_sleep = 5
72
71
  end
@@ -156,7 +155,7 @@ module ZuoraAPI
156
155
  # 1. Pass in cookies and optionally custom_authorities, name, and description
157
156
  # 2. Pass in user_id, entity_ids, client_id, client_secret, and optionally custom_authorities, name, and description
158
157
  # https://intranet.zuora.com/confluence/display/Sunburst/Create+an+OAuth+Client+through+API+Gateway#CreateanOAuthClientthroughAPIGateway-ZSession
159
- def get_oauth_client (custom_authorities = [], info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, new_client_id: nil, new_client_secret: nil, cookies: nil, chomp_v1_from_genesis_endpoint: false, use_api_generated_client_secret: false)
158
+ def get_oauth_client (custom_authorities = [], info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, new_client_id: nil, new_client_secret: nil, cookies: nil, chomp_v1_from_genesis_endpoint: false)
160
159
  authorization = ""
161
160
  new_client_id = SecureRandom.uuid if new_client_id.blank?
162
161
  new_client_secret = SecureRandom.hex(10) if new_client_secret.blank?
@@ -186,7 +185,7 @@ module ZuoraAPI
186
185
  oauth_response = HTTParty.post(endpoint, :headers => {'authorization' => authorization, 'Content-Type' => 'application/json'}, :body => {'clientId' => new_client_id, 'clientSecret' => new_client_secret, 'userId' => user_id, 'entityIds' => entity_ids, 'customAuthorities' => custom_authorities, 'additionalInformation' => {'description' => info_desc, 'name' => info_name}}.to_json)
187
186
  output_json = JSON.parse(oauth_response.body)
188
187
  if oauth_response.code == 201
189
- output_json["clientSecret"] = new_client_secret if !use_api_generated_client_secret
188
+ output_json["clientSecret"] = new_client_secret
190
189
  return output_json
191
190
  elsif oauth_response.code == 401 && !oauth_response.message.blank?
192
191
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], oauth_response)
@@ -253,7 +252,7 @@ module ZuoraAPI
253
252
  end
254
253
 
255
254
  def update_environment
256
- if !self.hostname.blank?
255
+ if !self.url.blank?
257
256
  case self.hostname
258
257
  when /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/
259
258
  self.environment = 'Sandbox'
@@ -276,13 +275,13 @@ module ZuoraAPI
276
275
  end
277
276
 
278
277
  def update_zconnect_provider
279
- update_region if self.region.blank?
280
- update_environment if self.environment.blank?
278
+ region = update_region
279
+ environment = update_environment
281
280
  mappings = {"US" => {"Sandbox" => "ZConnectSbx", "Services" => "ZConnectSvcUS", "Production" => "ZConnectProd", "Performance" => "ZConnectPT1", "Test" => "ZConnectTest", "Staging" => "ZConnectQA", "KubeSTG" => "ZConnectDev", "KubeDEV" => "ZConnectDev", "KubePROD" => "ZConnectDev"},
282
281
  "NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "ZConnectSvcNA", "Production" => "ZConnectProdNA", "Performance" => "ZConnectPT1NA"},
283
282
  "EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "ZConnectSvcEU", "Production" => "ZConnectProdEU", "Performance" => "ZConnectPT1EU", "Test" => "ZConnectTest"},
284
283
  "Unknown" => {"Unknown" => "Unknown"}}
285
- self.zconnect_provider = mappings[self.region][self.environment]
284
+ self.zconnect_provider = mappings[region][environment]
286
285
  end
287
286
 
288
287
  def aqua_endpoint(url="")
@@ -322,8 +321,8 @@ module ZuoraAPI
322
321
  return domain ? endpoint.concat(prefix).concat(url) : prefix.concat(url)
323
322
  end
324
323
 
325
- def rest_domain(endpoint: self.rest_endpoint)
326
- return URI(endpoint).host
324
+ def rest_domain
325
+ return URI(self.rest_endpoint).host
327
326
  end
328
327
 
329
328
  def fileURL(url="")
@@ -335,41 +334,10 @@ module ZuoraAPI
335
334
  end
336
335
 
337
336
  def new_session(auth_type: :basic, debug: false, zuora_track_id: nil)
338
- retries ||= 2
339
- yield
340
-
341
- rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
342
- self.status = 'Invalid'
343
- self.current_error = ex.message
344
- raise
345
- rescue ZuoraAPI::Exceptions::ZuoraAPIError => ex
346
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(ex.message, ex.response)
347
-
348
- rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex
349
- raise ex if retries.zero?
350
-
351
- retries -= 1
352
- sleep(self.timeout_sleep)
353
- retry
354
-
355
- rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
356
- self.log(location: "BasicLogin", exception: ex, message: "Timed out", level: :error)
357
-
358
- self.current_error = "Request timed out. Try again"
359
- self.status = 'Timeout'
360
-
361
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
362
-
363
- rescue EOFError
364
- if self.url.match?(/.*services\d{1,}.zuora.com*/)
365
- self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available."
366
- self.status = 'Not Available'
367
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
368
- end
369
-
370
337
  end
371
338
 
372
339
  def get_session(prefix: false, auth_type: :basic, zuora_track_id: nil)
340
+ Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}") if Rails.env.to_s == 'development'
373
341
  case auth_type
374
342
  when :basic
375
343
  if self.current_session.blank?
@@ -378,13 +346,14 @@ module ZuoraAPI
378
346
  if self.bearer_token.blank? || self.oauth_expired?
379
347
  self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id)
380
348
  end
381
- self.get_z_session(zuora_track_id: zuora_track_id)
349
+ self.get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
382
350
  when 'ZuoraAPI::Basic'
383
351
  self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
384
352
  else
385
353
  self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
386
354
  end
387
355
  end
356
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
388
357
  return prefix ? "ZSession #{self.current_session}" : self.current_session.to_s
389
358
  when :bearer
390
359
  case self.class.to_s
@@ -397,6 +366,8 @@ module ZuoraAPI
397
366
  else
398
367
  raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Unknown Login, does not support Authentication of Type: #{auth_type}")
399
368
  end
369
+
370
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
400
371
  return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
401
372
  end
402
373
  end
@@ -404,18 +375,16 @@ module ZuoraAPI
404
375
  def soap_call(
405
376
  ns1: 'ns1',
406
377
  ns2: 'ns2',
407
- batch_size: nil,
408
- headers: {},
378
+ batch_size: nil,
409
379
  single_transaction: false,
410
380
  debug: false,
411
381
  zuora_track_id: nil,
412
382
  errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
413
383
  z_session: true,
414
384
  timeout_retry: false,
415
- timeout: 130,
385
+ timeout: 120,
416
386
  timeout_sleep_interval: self.timeout_sleep,
417
387
  output_exception_messages: true,
418
- skip_session: false,
419
388
  **keyword_args)
420
389
  tries ||= 2
421
390
  xml = Nokogiri::XML::Builder.new do |xml|
@@ -425,10 +394,8 @@ module ZuoraAPI
425
394
  'xmlns:api' => "http://api.zuora.com/",
426
395
  "xmlns:#{ns1}" => "http://api.zuora.com/") do
427
396
  xml['SOAP-ENV'].Header do
428
- if !skip_session
429
- xml["#{ns1}"].SessionHeader do
430
- xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
431
- end
397
+ xml["#{ns1}"].SessionHeader do
398
+ xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
432
399
  end
433
400
  if single_transaction
434
401
  xml["#{ns1}"].CallOptions do
@@ -446,11 +413,12 @@ module ZuoraAPI
446
413
  end
447
414
  end
448
415
  end
416
+
449
417
  input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
450
418
  input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
451
419
  Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
452
420
 
453
- headers.merge!({ 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'})
421
+ headers = { 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'}
454
422
  headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
455
423
 
456
424
  request = HTTParty::Request.new(
@@ -467,11 +435,7 @@ module ZuoraAPI
467
435
  Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
468
436
 
469
437
  raise_errors(type: :SOAP, body: output_xml, response: response)
470
-
471
- return output_xml, input_xml, response
472
-
473
438
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
474
- raise if skip_session
475
439
  if !tries.zero? && z_session
476
440
  tries -= 1
477
441
  Rails.logger.debug("SOAP Call - Session Invalid")
@@ -483,33 +447,39 @@ module ZuoraAPI
483
447
  end
484
448
 
485
449
  retry
450
+ else
451
+ if errors.include?(ex.class)
452
+ raise ex
453
+ else
454
+ return output_xml, input_xml, response
455
+ end
486
456
  end
487
-
488
- raise ex if errors.include?(ex.class)
489
-
490
- return output_xml, input_xml, response
491
-
492
457
  rescue *ZUORA_API_ERRORS => ex
493
- raise ex if errors.include?(ex.class)
494
-
495
- response = ex.response unless response
496
- return output_xml, input_xml, response
497
-
458
+ if errors.include?(ex.class)
459
+ raise ex
460
+ else
461
+ response = ex.response unless response
462
+ return output_xml, input_xml, response
463
+ end
498
464
  rescue *CONNECTION_EXCEPTIONS => ex
499
- if !tries.zero?
500
- tries -= 1
501
- self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
502
- sleep(timeout_sleep_interval)
503
- retry
465
+ if tries.zero?
466
+ if output_exception_messages
467
+ if Rails.logger.class.to_s == "Ougai::Logger"
468
+ Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
469
+ else
470
+ Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
471
+ end
472
+ end
473
+ raise ex
504
474
  end
505
475
 
506
- self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
507
- raise ex
508
-
476
+ tries -= 1
477
+ sleep(timeout_sleep_interval)
478
+ retry
509
479
  rescue *CONNECTION_READ_EXCEPTIONS => ex
510
480
  if !tries.zero?
511
481
  tries -= 1
512
- self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
482
+
513
483
  if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
514
484
  retry
515
485
  elsif timeout_retry
@@ -518,74 +488,19 @@ module ZuoraAPI
518
488
  end
519
489
  end
520
490
 
521
- self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
522
- ex = ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read/write timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.is_a?(Timeout::Error) && !ex.instance_of?(ZuoraAPI::Exceptions::ZuoraAPIReadTimeout)
491
+ if output_exception_messages
492
+ if Rails.logger.class.to_s == "Ougai::Logger"
493
+ Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
494
+ else
495
+ Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
496
+ end
497
+ end
498
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
523
499
  raise ex
524
-
525
500
  rescue => ex
526
501
  raise ex
527
- ensure
528
- self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
529
- end
530
-
531
- def error_logger(ex)
532
- exception_args = Rails.logger.with_fields.merge(self.exception_args(ex))
533
- case ex
534
- when ZuoraAPI::Exceptions::ZuoraAPIUnkownError, ZuoraAPI::Exceptions::ZuoraDataIntegrity
535
- Rails.logger.error('Zuora Unknown/Integrity Error', ex, exception_args)
536
- when ZuoraAPI::Exceptions::ZuoraAPIRequestLimit
537
- Rails.logger.info('Zuora APILimit Reached', ex, exception_args)
538
- when *(ZuoraAPI::Login::ZUORA_API_ERRORS-ZuoraAPI::Login::ZUORA_SERVER_ERRORS)
539
- #Rails.logger.debug('Zuora API Error', ex, self.exception_args(ex))
540
- when *ZuoraAPI::Login::ZUORA_SERVER_ERRORS
541
- Rails.logger.error('Zuora Server Error', ex, exception_args)
542
- end
543
- end
544
-
545
- def log(location: "Rest Call", exception: nil, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :info )
546
- level = :debug if ![:debug, :info, :warn, :error, :fatal].include?(level)
547
- if Rails.logger.class.to_s == "Ougai::Logger"
548
- Rails.logger.send(level.to_sym, "#{location} - #{message}", exception)
549
- else
550
- Rails.logger.send(level.to_sym, "#{location} - #{exception.class} #{message}")
551
- end
552
- end
553
-
554
- def exception_args(ex)
555
- args = {}
556
- if defined?(ex.response) && ex.response.present?
557
- args.merge!({
558
- request: {
559
- path: ex.response.request.path.to_s,
560
- method: ex.response.request.http_method.to_s.split("Net::HTTP::").last.upcase,
561
- params: ex.response.request.raw_body.to_s,
562
- headers: ex.response.request.options[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h.to_s,
563
- },
564
- response: {
565
- status: ex.response.code,
566
- params: ex.response.body.to_s,
567
- headers: ex.response.headers.to_s,
568
- },
569
- zuora_trace_id: ex.response.headers["zuora-request-id"],
570
- zuora_track_id: ex.response.request.options[:headers]["Zuora-Track-Id"],
571
- })
572
- elsif defined?(ex.request) && ex.request.present?
573
- args.merge!({
574
- request: {
575
- path: ex.request.path.to_s,
576
- method: ex.request.http_method.to_s.split("Net::HTTP::").last.upcase,
577
- params: ex.request.options[:body],
578
- headers: ex.request.options[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h.to_s
579
- }
580
- })
581
- args.merge!({
582
- zuora_track_id: ex.request.options[:headers]["Zuora-Track-Id"]
583
- }) if ex.request.options[:headers]["Zuora-Track-Id"].present?
584
- end
585
- rescue => ex
586
- Rails.logger.error("Failed to create exception arguments", ex, args)
587
- ensure
588
- return args
502
+ else
503
+ return output_xml, input_xml, response
589
504
  end
590
505
 
591
506
  def raise_errors(type: :SOAP, body: nil, response: nil)
@@ -602,13 +517,13 @@ module ZuoraAPI
602
517
  end
603
518
 
604
519
  if [502,503].include?(response.code)
605
- raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from 'https://#{rest_domain(endpoint: request_uri)}'", response)
520
+ raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from #{request_uri}", response)
606
521
  end
607
522
 
608
523
  # Check failure response code
609
524
  case response.code
610
525
  when 504
611
- raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response)
526
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{request_uri}", response)
612
527
  when 429
613
528
  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)
614
529
  when 401
@@ -629,10 +544,6 @@ module ZuoraAPI
629
544
  when :SOAP
630
545
  error, success, message = get_soap_error_and_message(body)
631
546
 
632
- if body.xpath('//fns:LoginFault', 'fns' =>'http://fault.api.zuora.com/').present?
633
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response)
634
- end
635
-
636
547
  if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
637
548
  body.xpath(
638
549
  '//ns1:records[@xsi:type="ns2:Export"]',
@@ -640,12 +551,12 @@ module ZuoraAPI
640
551
  ).present?
641
552
  result = body.xpath('//ns2:Status', 'ns2' => 'http://object.api.zuora.com/').text
642
553
  if result == 'Failed'
643
- message = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
644
- error = 'FATAL_ERROR'
645
- if message.present?
646
- identifier, new_message = message.scan(/^([\w\d]{16})\: (.*)/).first
647
- error, message = ['UNEXPECTED_ERROR', new_message] if new_message.present?
554
+ reason = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
555
+ if reason.present?
556
+ message = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
557
+ 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'
648
558
  else
559
+ error = 'FATAL_ERROR'
649
560
  message = 'Export failed due to unknown reason. Consult api logs.'
650
561
  end
651
562
  end
@@ -694,31 +605,14 @@ module ZuoraAPI
694
605
  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.
695
606
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
696
607
  end
697
- when /\/objects\/batch\//
698
- if body['code'].present? && /61$/.match(body['code'].to_s).present? # if last 2 digits of code are 61
699
- raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body['message'], nil, body['details'])
700
- end
701
- when /^\/api\/v1\/payment_plans.*/
702
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['error'], response) if body['error']
703
608
  end
704
609
 
705
610
  body = body.dig("results").present? ? body["results"] : body if body.class == Hash
706
611
  if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
707
- reason_keys = %w(reasons errors)
708
- message_keys = %w(message title)
709
- messages_array, codes_array = [[],[]]
710
- reason_keys.each do |rsn_key|
711
- message_keys.each do |msg_key|
712
- messages_array = body.fetch(rsn_key, []).map {|error| error[msg_key]}.compact
713
- break if messages_array.present?
714
- end
715
- codes_array = body.fetch(rsn_key, []).map {|error| error['code']}.compact
716
- break if messages_array.present? && codes_array.present?
717
- end
718
- if body.dig('error').class == Hash
719
- messages_array = messages_array.push(body.dig("error", 'message')).compact
720
- codes_array = codes_array.push(body.dig("error", 'code')).compact
721
- end
612
+ messages_array = body.fetch("reasons", []).map {|error| error['message']}.compact
613
+ messages_array = messages_array.push(body.dig("error", 'message')).compact if body.dig('error').class == Hash
614
+ codes_array = body.fetch("reasons", []).map {|error| error['code']}.compact
615
+ codes_array = codes_array.push(body.dig("error", 'code')).compact if body.dig('error').class == Hash
722
616
 
723
617
  if body['message'] == 'request exceeded limit'
724
618
  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)
@@ -750,11 +644,7 @@ module ZuoraAPI
750
644
  end
751
645
 
752
646
  if body['error'] == 'Unauthorized' && body['status'] == 401
753
- if body['message'].present?
754
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(body['message'], response)
755
- else
756
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
757
- end
647
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
758
648
  end
759
649
  #Authentication failed
760
650
  if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
@@ -861,7 +751,7 @@ module ZuoraAPI
861
751
  output_json = JSON.parse(response.body)
862
752
  self.raise_errors(type: :JSON, body: output_json, response: response)
863
753
 
864
- elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml') || response_content_types.include?('application/soap+xml')) and type != :xml
754
+ elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml')) and type != :xml
865
755
  output_xml = Nokogiri::XML(response.body)
866
756
  self.raise_errors(type: :SOAP, body: output_xml, response: response)
867
757
 
@@ -881,8 +771,6 @@ module ZuoraAPI
881
771
  raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
882
772
  when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
883
773
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
884
- when /414 Request-URI Too Large/
885
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Request URL is too long", response)
886
774
  else
887
775
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
888
776
  end
@@ -909,11 +797,6 @@ module ZuoraAPI
909
797
  message = body.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text
910
798
  end
911
799
 
912
- if error.blank? || message.blank?
913
- error = body.xpath('//soapenv:Value', 'soapenv'=>'http://www.w3.org/2003/05/soap-envelope').text
914
- message = body.xpath('//soapenv:Text', 'soapenv'=>'http://www.w3.org/2003/05/soap-envelope').text
915
- end
916
-
917
800
  #Update/Create/Delete Calls with multiple requests and responses
918
801
  if body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').size > 0 && body.xpath('//ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
919
802
  error = []
@@ -957,22 +840,17 @@ module ZuoraAPI
957
840
  raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
958
841
  end
959
842
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
960
- when /^INVALID_VERSION/, /invalid/, /^DUPLICATE_VALUE/, /^REQUEST_REJECTED/, /INVALID_ID/, /MAX_RECORDS_EXCEEDED/, /INVALID_FIELD/, /MALFORMED_QUERY/, /NO_PERMISSION/, /PDF_QUERY_ERROR/, /MISSING_REQUIRED_VALUE/, /INVALID_TYPE/, /TRANSACTION_FAILED/, /API_DISABLED/, /CANNOT_DELETE/, /ACCOUNTING_PERIOD_CLOSED/
843
+ when /invalid/, /^DUPLICATE_VALUE/, /^REQUEST_REJECTED/, /INVALID_ID/, /MAX_RECORDS_EXCEEDED/, /INVALID_FIELD/, /MALFORMED_QUERY/, /NO_PERMISSION/, /PDF_QUERY_ERROR/, /MISSING_REQUIRED_VALUE/, /INVALID_TYPE/, /TRANSACTION_FAILED/, /API_DISABLED/, /CANNOT_DELETE/, /ACCOUNTING_PERIOD_CLOSED/
961
844
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
962
845
  when /.*UNEXPECTED_ERROR/
963
846
  raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
964
847
  when /.*soapenv:Server.*/
965
848
  if /^Invalid value.*for type.*|^Id is invalid|^date string can not be less than 19 charactors$/.match(message).present?
966
849
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
967
- elsif /^unknown$|^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
850
+ elsif /^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
968
851
  raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
969
852
  end
970
853
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
971
- when /soapenv:Receiver/
972
- if /^com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character.*$/.match(message).present?
973
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
974
- end
975
- raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
976
854
  else
977
855
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Z:#{error}::#{message}", response, errors, success)
978
856
  end
@@ -1022,7 +900,7 @@ module ZuoraAPI
1022
900
  base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
1023
901
  url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
1024
902
  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"}
1025
- response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 130)
903
+ response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
1026
904
 
1027
905
  raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
1028
906
 
@@ -1055,31 +933,35 @@ module ZuoraAPI
1055
933
  end
1056
934
  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
1057
935
  end
1058
-
1059
- return des_hash
1060
936
  rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
1061
- if !tries.zero?
1062
- tries -= 1
1063
- self.log(location: "Describe", exception: ex, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :debug)
1064
- sleep(self.timeout_sleep)
1065
- retry
937
+ if tries.zero?
938
+ if log_errors
939
+ if Rails.logger.class.to_s == "Ougai::Logger"
940
+ Rails.logger.error("Describe - Timed out will retry after #{self.timeout_sleep} seconds", ex)
941
+ else
942
+ Rails.logger.error("Describe - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
943
+ end
944
+ end
945
+ raise ex
1066
946
  end
1067
947
 
1068
- self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors
1069
- raise ex
1070
-
948
+ tries -= 1
949
+ sleep(self.timeout_sleep)
950
+ retry
1071
951
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1072
952
  if !tries.zero? && self.status == 'Active'
1073
953
  tries -= 1
1074
954
  Rails.logger.debug("Describe session expired. Starting new session.")
1075
955
  self.new_session
1076
956
  retry
957
+ else
958
+ Rails.logger.error("Describe session expired. Starting new session.") if log_errors
959
+ raise ex
1077
960
  end
1078
-
1079
- Rails.logger.error("Describe session expired. Starting new session.") if log_errors
1080
- raise ex
1081
961
  rescue => ex
1082
962
  raise ex
963
+ else
964
+ return des_hash
1083
965
  end
1084
966
 
1085
967
  def rest_call(
@@ -1092,12 +974,11 @@ module ZuoraAPI
1092
974
  z_session: true,
1093
975
  session_type: :basic,
1094
976
  timeout_retry: false,
1095
- timeout: 130,
977
+ timeout: 120,
1096
978
  timeout_sleep_interval: self.timeout_sleep,
1097
979
  multipart: false,
1098
980
  stream_body: false,
1099
981
  output_exception_messages: true,
1100
- zuora_track_id: nil,
1101
982
  **keyword_args,
1102
983
  &block
1103
984
  )
@@ -1107,13 +988,12 @@ module ZuoraAPI
1107
988
 
1108
989
  authentication_headers = {}
1109
990
  if z_session
1110
- authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type, zuora_track_id: zuora_track_id) }
991
+ authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type) }
1111
992
  if self.entity_id.present?
1112
993
  authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
1113
994
  authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
1114
995
  end
1115
996
  end
1116
- headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
1117
997
 
1118
998
  modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
1119
999
 
@@ -1139,20 +1019,18 @@ module ZuoraAPI
1139
1019
  Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
1140
1020
 
1141
1021
  raise_errors(type: :JSON, body: output_json, response: response)
1142
- rescue => ex
1022
+ rescue
1143
1023
  reset_files(body) if multipart
1144
1024
  raise
1145
1025
  end
1146
-
1147
- return [output_json, response]
1148
1026
  rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
1149
1027
  if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
1150
1028
  session_type = :bearer
1151
1029
  retry
1030
+ else
1031
+ Rails.logger.debug("Rest Call - Session Bad Auth type")
1032
+ raise ex
1152
1033
  end
1153
- Rails.logger.debug("Rest Call - Session Bad Auth type")
1154
- raise ex
1155
-
1156
1034
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1157
1035
  if !tries.zero? && z_session
1158
1036
  tries -= 1
@@ -1165,35 +1043,40 @@ module ZuoraAPI
1165
1043
  end
1166
1044
 
1167
1045
  retry
1046
+ else
1047
+ if errors.include?(ex.class)
1048
+ raise ex
1049
+ else
1050
+ return [output_json, response]
1051
+ end
1168
1052
  end
1169
-
1170
- raise ex if errors.include?(ex.class)
1171
- return [output_json, response]
1172
-
1173
1053
  rescue *ZUORA_API_ERRORS => ex
1174
- raise ex if errors.include?(ex.class)
1175
-
1176
- response = ex.response unless response
1177
- return [output_json, response]
1178
-
1054
+ if errors.include?(ex.class)
1055
+ raise ex
1056
+ else
1057
+ response = ex.response unless response
1058
+ return [output_json, response]
1059
+ end
1179
1060
  rescue ZuoraAPI::Exceptions::BadEntityError => ex
1180
1061
  raise ex
1181
1062
  rescue *CONNECTION_EXCEPTIONS => ex
1182
- if !tries.zero?
1183
- tries -= 1
1184
- self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
1185
- sleep(timeout_sleep_interval)
1186
- retry
1063
+ if tries.zero?
1064
+ if output_exception_messages
1065
+ if Rails.logger.class.to_s == "Ougai::Logger"
1066
+ Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
1067
+ else
1068
+ Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
1069
+ end
1070
+ end
1071
+ raise ex
1187
1072
  end
1188
1073
 
1189
- self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
1190
- raise ex
1191
-
1074
+ tries -= 1
1075
+ sleep(timeout_sleep_interval)
1076
+ retry
1192
1077
  rescue *CONNECTION_READ_EXCEPTIONS => ex
1193
-
1194
1078
  if !tries.zero?
1195
1079
  tries -= 1
1196
- self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
1197
1080
  if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
1198
1081
  retry
1199
1082
  elsif timeout_retry
@@ -1201,15 +1084,20 @@ module ZuoraAPI
1201
1084
  retry
1202
1085
  end
1203
1086
  end
1204
-
1205
- self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
1206
- ex = ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read/write timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.is_a?(Timeout::Error) && !ex.instance_of?(ZuoraAPI::Exceptions::ZuoraAPIReadTimeout)
1087
+
1088
+ if output_exception_messages
1089
+ if Rails.logger.class.to_s == "Ougai::Logger"
1090
+ Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
1091
+ else
1092
+ Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
1093
+ end
1094
+ end
1095
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
1207
1096
  raise ex
1208
-
1209
1097
  rescue => ex
1210
1098
  raise ex
1211
- ensure
1212
- self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
1099
+ else
1100
+ return [output_json, response]
1213
1101
  end
1214
1102
 
1215
1103
  def update_create_tenant
@@ -1231,9 +1119,8 @@ module ZuoraAPI
1231
1119
  while !response["nextPage"].blank?
1232
1120
  url = self.rest_endpoint(response["nextPage"].split('/v1/').last)
1233
1121
  Rails.logger.debug("Fetch Catalog URL #{url}")
1234
- output_json, response = self.rest_call(debug: false, url: url, timeout_retry: true)
1235
-
1236
- if !/(true|t|yes|y|1)$/.match(output_json['success'].to_s) || output_json['success'].class != TrueClass
1122
+ output_json, response = self.rest_call(:debug => false, :url => url, :errors => [ZuoraAPI::Exceptions::ZuoraAPISessionError], :timeout_retry => true )
1123
+ if !output_json['success'] =~ (/(true|t|yes|y|1)$/i) || output_json['success'].class != TrueClass
1237
1124
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
1238
1125
  end
1239
1126
  output_json["products"].each do |product|
@@ -1259,7 +1146,7 @@ module ZuoraAPI
1259
1146
  return products, catalog_map
1260
1147
  end
1261
1148
 
1262
- 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)
1149
+ 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)
1263
1150
  raise "file_path must be of class Pathname" if file_path.class != Pathname
1264
1151
 
1265
1152
  retry_count ||= timeout_retries
@@ -1364,20 +1251,14 @@ module ZuoraAPI
1364
1251
  return file_handle
1365
1252
  when Net::HTTPUnauthorized
1366
1253
  if z_session
1367
- unless (retry_count -= 1).zero?
1254
+ if !(retry_count -= 1).zero?
1368
1255
  self.new_session
1369
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError, 'Retrying'
1256
+ raise response.class
1257
+ else
1258
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
1370
1259
  end
1371
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
1372
- end
1373
- raise
1374
- when Net::HTTPNotFound
1375
- if url.include?(self.fileURL)
1376
- raise ZuoraAPI::Exceptions::FileDownloadError.new(
1377
- "The current tenant does not have a file with id '#{url.split('/').last}'"
1378
- )
1379
1260
  else
1380
- raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
1261
+ raise
1381
1262
  end
1382
1263
  else
1383
1264
  raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
@@ -1388,81 +1269,133 @@ module ZuoraAPI
1388
1269
  sleep(5)
1389
1270
  if (retry_count -= 1) >= 0
1390
1271
  retry
1272
+ else
1273
+ Rails.logger.error("File Download Failed")
1274
+ raise
1391
1275
  end
1392
- Rails.logger.error("File Download Failed")
1393
- raise
1394
1276
  end
1395
1277
 
1396
1278
  def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
1397
- tries ||= 3
1398
-
1399
- output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true, zuora_track_id: z_track_id) do |xml|
1400
- xml['ns1'].create do
1401
- xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
1402
- xml['ns2'].Format 'csv'
1403
- xml['ns2'].Zip zip
1404
- xml['ns2'].Name 'googman'
1405
- xml['ns2'].Query query
1406
- xml['ns2'].Encrypted encrypted
1279
+ begin
1280
+ tries ||= 3
1281
+ request = Nokogiri::XML::Builder.new do |xml|
1282
+ 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
1283
+ xml['SOAP-ENV'].Header do
1284
+ xml['ns1'].SessionHeader do
1285
+ xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
1286
+ end
1287
+ end
1288
+ xml['SOAP-ENV'].Body do
1289
+ xml['ns1'].create do
1290
+ xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
1291
+ xml['ns2'].Format 'csv'
1292
+ xml['ns2'].Zip zip
1293
+ xml['ns2'].Name 'googman'
1294
+ xml['ns2'].Query query
1295
+ xml['ns2'].Encrypted encrypted
1296
+ end
1297
+ end
1298
+ end
1407
1299
  end
1408
1300
  end
1409
- end
1410
-
1411
- id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
1412
-
1413
- result = 'Waiting'
1414
- while result != "Completed"
1415
- sleep 3
1416
- output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true, zuora_track_id: z_track_id) do |xml|
1417
- xml['ns1'].query do
1418
- xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
1301
+
1302
+ 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)
1303
+
1304
+ output_xml = Nokogiri::XML(response_query.body)
1305
+ raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
1306
+
1307
+ # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
1308
+
1309
+ id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
1310
+
1311
+ confirmRequest = Nokogiri::XML::Builder.new do |xml|
1312
+ 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
1313
+ xml['SOAP-ENV'].Header do
1314
+ xml['ns1'].SessionHeader do
1315
+ xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
1316
+ end
1317
+ end
1318
+ xml['SOAP-ENV'].Body do
1319
+ xml['ns1'].query do
1320
+ xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
1321
+ end
1322
+ end
1419
1323
  end
1420
1324
  end
1421
- result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
1422
- end
1325
+ result = 'Waiting'
1423
1326
 
1424
- file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
1425
- export_file = get_file(:url => self.fileURL(file_id))
1426
- export_file_path = export_file.path
1427
-
1428
- if extract && zip
1429
- require "zip"
1430
- new_path = export_file_path.partition('.zip').first
1431
- zipped = Zip::File.open(export_file_path)
1432
- file_handle = zipped.entries.first
1433
- file_handle.extract(new_path)
1434
- File.delete(export_file_path)
1435
- return new_path
1436
- else
1437
- return export_file_path
1438
- end
1439
- rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1440
- if !(tries -= 1).zero?
1441
- Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
1442
- self.new_session
1443
- retry
1444
- end
1445
- raise ex
1327
+ while result != "Completed"
1328
+ sleep 3
1329
+ 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)
1446
1330
 
1447
- rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
1448
- if !(tries -= 1).zero?
1449
- Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
1450
- sleep(self.timeout_sleep)
1451
- retry
1452
- end
1453
- raise ex
1454
-
1455
- rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
1456
- if !(tries -= 1).zero?
1457
- Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
1458
- sleep(self.timeout_sleep)
1459
- retry
1331
+ output_xml = Nokogiri::XML(response_query.body)
1332
+ result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
1333
+ status_code = response_query.code if response_query
1334
+
1335
+ raise_errors(type: :SOAP, body: output_xml, response: response_query) if result.blank? || result == "Failed"
1336
+ # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if result.blank? || result == "Failed"
1337
+ end
1338
+
1339
+ file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
1340
+ export_file = get_file(:url => self.fileURL(file_id))
1341
+ export_file_path = export_file.path
1342
+ Rails.logger.debug("=====> Export path #{export_file.path}")
1343
+
1344
+ if extract && zip
1345
+ require "zip"
1346
+ new_path = export_file_path.partition('.zip').first
1347
+ zipped = Zip::File.open(export_file_path)
1348
+ file_handle = zipped.entries.first
1349
+ file_handle.extract(new_path)
1350
+ File.delete(export_file_path)
1351
+ return new_path
1352
+ else
1353
+ return export_file_path
1354
+ end
1355
+ rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1356
+ if !(tries -= 1).zero?
1357
+ Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
1358
+ self.new_session
1359
+ retry
1360
+ else
1361
+ raise ex
1362
+ end
1363
+
1364
+ rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
1365
+ if !(tries -= 1).zero?
1366
+ Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
1367
+ sleep 10
1368
+ retry
1369
+ else
1370
+ raise ex
1371
+ end
1372
+
1373
+ rescue *ZUORA_API_ERRORS => ex
1374
+ raise ex
1375
+
1376
+ rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
1377
+ if !(tries -= 1).zero?
1378
+ Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
1379
+ sleep 5
1380
+ retry
1381
+ else
1382
+ raise ex
1383
+ end
1384
+
1385
+ rescue Errno::ECONNRESET => ex
1386
+ if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
1387
+ retry
1388
+ else
1389
+ raise ex
1390
+ end
1391
+
1392
+ rescue ZuoraAPI::Exceptions::BadEntityError => ex
1393
+ raise ex
1460
1394
  end
1461
- raise ex
1462
1395
  end
1463
1396
 
1464
1397
  def query(query, parse = false)
1465
- output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true) do |xml|
1398
+ output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
1466
1399
  xml['ns1'].query do
1467
1400
  xml['ns1'].queryString query
1468
1401
  end