zuora_api 1.7.81 → 1.8.00

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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