zuora_api 1.7.66 → 1.7.80

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff05150108e2fbba1a069083c46b53d4b43d95d95d4cfb4bcd82d10881e80091
4
- data.tar.gz: b8543c688b33ee85357716df5e1f93b7cafef3702074914355aa30960b8726dd
3
+ metadata.gz: b0865872f720e280a3a4805d314d27a3e2649b861495f80cf8523f4eb43f2c1e
4
+ data.tar.gz: cc80008e33f6b47245acc1a0b8cdb0ec326f4a714c842e434b25bd5643e94123
5
5
  SHA512:
6
- metadata.gz: 9b2a8309a4a1c88a13be63df6eb96c08d27e25076b379c740b7eddd1898a60f46249388e7279d98e67fd72469e49f1a6abdc5c7f3a62aa32905909c100de46ad
7
- data.tar.gz: 0a706abfa46ed54f332f903a2af7c118dfda2aaa6f61a280b9c2f989fb19790484aefcabed72bbcdc9b5ab37a2befb46913d2771ab6a924095c34ec80a8a595c
6
+ metadata.gz: 051c3a5244695357f0ecf6a42ee1eda7981c0145ed3b50d9e0b751dbbdf6e4aba1d7e36e69eec28056e2fb3b56888c48113699d32ab0f6479272e339b3c1ade2
7
+ data.tar.gz: f20c6fd7e534de55b5b94120e812ba19e18fda5f41e63f8f9183fb66d8ea4a0a01f441918d84196b2aa027724228b63332f54aea94b9515142534d5fff15574c
data/.gitignore CHANGED
@@ -7,4 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
- .idea
10
+ .idea
11
+ .DS_Store
@@ -1,21 +1,8 @@
1
- image: ruby:2.6
1
+ image: ruby:2.7
2
2
  stages:
3
- - setup
4
3
  - test
5
4
  - deploy
6
5
 
7
- setup:
8
- stage: setup
9
- allow_failure: true
10
- cache:
11
- key: gems
12
- paths:
13
- - vendor/bundle
14
- script:
15
- - apt-get update -qy
16
- - apt-get install -y nodejs
17
- - bundle install
18
-
19
6
  rubocop-testing:
20
7
  stage: test
21
8
  allow_failure: true
@@ -30,11 +17,24 @@ security-testing:
30
17
  - gem install brakeman
31
18
  - brakeman
32
19
 
33
- rspec-testing:
20
+ ruby:test:
34
21
  stage: test
22
+ cache:
23
+ key: ruby:$RUBY_VERSION-rails:$RAILS_VERSION
24
+ paths:
25
+ - vendor/ruby
26
+ parallel:
27
+ matrix:
28
+ - RUBY_VERSION: "2.7"
29
+ RAILS_VERSION: ["5.0", "5.1", "5.2", "6.0"]
30
+ before_script:
31
+ - bundle config set path 'vendor/ruby'
32
+ - bundle config --global gemfile "gemfiles/Gemfile-rails.$RAILS_VERSION.x"
33
+ - bundle install
35
34
  script:
36
- - bundle install
37
- - rspec
35
+ - bundle exec rails -v
36
+ - bundle exec rspec
37
+ coverage: '/\(\d+.\d+\%\) covered/'
38
38
 
39
39
  rubygems-deploy:
40
40
  stage: deploy
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
-
2
+ ruby "2.7.2"
3
3
  # Specify your gem's dependencies in zuora.gemspec
4
4
  gemspec
@@ -0,0 +1,12 @@
1
+ ---
2
+ apiVersion: backstage.io/v1alpha1
3
+ kind: Component
4
+ metadata:
5
+ annotations:
6
+ backstage.io/techdocs-ref: "gitlab:https://gitlab.zeta.tools/extension-products/shared-libraries/zuora-gem.git"
7
+ description: "Zuora API Rails Gem"
8
+ name: Zuora-Gem
9
+ spec:
10
+ lifecycle: production
11
+ owner: connect@zuora.com
12
+ type: library
@@ -0,0 +1,147 @@
1
+ # Zuora Gem
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/zuora_api.svg)](https://badge.fury.io/rb/zuora_api) [![coverage report](https://gitlab.0.ecc.auw2.zuora/extension-products/shared-libraries/zuora-gem/badges/master/coverage.svg)](https://gitlab.0.ecc.auw2.zuora/extension-products/shared-libraries/zuora-gem/commits/master)
4
+
5
+ ## Installation
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'zuora_api'
10
+ ```
11
+ Then execute `bundle install` in your terminal
12
+
13
+ ## Usage
14
+
15
+ ### Zuora Login Object
16
+ In order to make API calls a Zuora Login object must be created
17
+
18
+ ```ruby
19
+ zuora_client = ZuoraAPI::Login.new(username: "username", password: "password", url: "url")
20
+ ```
21
+
22
+ | Name | Type | Description | Example |
23
+ | ------------------- | ----------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | username | `Attribute` | Username to the Zuora environment | `zuora_client.username = "username"` |
25
+ | password | `Attribute` | password to the Zuora environment | `zuora_client.password = "Password"` |
26
+ | url | `Attribute` | Endpoint to the Zuora tenant | `zuora_client.url = "www.zuora.com"` |
27
+ | wsdl_number | `Attribute` | WSDL number of the zuora login | `wsdl = zuora_client.wsdl_number` |
28
+ | status | `Attribute` | Status of the login | `zuora_client.status` |
29
+ | current_session | `Attribute` | Current session for the login | `zuora_client.current_session` |
30
+ | environment | `Attribute` | environment of the login | `zuora_client.environment` |
31
+ | errors | `Attribute` | Any errors that the login has based on the login call | `zuora_client.errors` |
32
+ | current_error | `Attribute` | Current error from the new_session call | `zuora_client.current_error` |
33
+ | user_info | `Attribute` | Information related to the login | `zuora_client.user_info` |
34
+ | tenant_id | `Attribute` | Tenant ID the login is associated to | `zuora_client.tenant_id` |
35
+ | tenant_name | `Attribute` | Tenant Name of tenant the login is associated to | `zuora_client.tenant_name` |
36
+ | entity_id | `Attribute` | Current entity the login session is associated to | `zuora_client.entity_id` |
37
+ | rest_call | `Method` | Executes a REST call | `zuora_client.rest_call()` |
38
+ | soap_call | `Method` | Executes a SOAP call | `output_xml, input_xml = zuora_client.soap_call() do `|xml, args|` xml['ns1'].query do xml['ns1'].queryString "select id, name from account" end end` |
39
+ | query | `Method` | Executes a query call | `zuora_client.query("select id, name from account")` |
40
+ | getDataSourceExport | `Method` | Pulls a data source export with the given query and returns the file location | `zuora_client.getDataSourceExport("select id, name from account")` |
41
+ | describe_call | `Method` | Performs the describe call against the Zuora tenant for all objects or a specific object | `response = zuora_client.describe_call("Account")` |
42
+ | createJournalRun | `Method` | Creates a Journal Run | `zuora_client.createJournalRun(call)` |
43
+ | checkJRStatus | `Method` | Checks the status of a journal run | `zuora_client.checkJRStatus(journal_run_id)` |
44
+ | update_environment | `Method` | Sets the login's environment based on the url | `zuora_client.update_environment` |
45
+ | aqua_endpoint | `Method` | Returns the AQuA endpoint for the login based off the environment | `zuora_client.aqua_endpoint` |
46
+ | rest_endpoint | `Method` | Returns the REST endpoint for the login based off the environment | `zuora_client.rest_endpoint` |
47
+ | fileURL | `Method` | Returns the URL for files | `zuora_client.fileURL` |
48
+ | dateFormat | `Method` | Returns the data format syntax based on the wsdl_number | `zuora_client.dateFormat` |
49
+ | new_session | `Method` | Create a new session | `zuora_client.new_session` |
50
+ | get_session | `Method` | Returns the current session | `zuora_client.get_session`|
51
+
52
+ ## Rest Call
53
+ ```ruby
54
+ zuora_client.rest_call(method: :get, body: {}, url: zuora_client.rest_endpoint("catalog/products?pageSize=4"))
55
+ ```
56
+
57
+ ### Soap Call
58
+ Returns both output and input XML
59
+
60
+ ```ruby
61
+ zuora_client.soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false)
62
+ ```
63
+
64
+ Example Call
65
+
66
+ ```ruby
67
+ output_xml, input_xml = zuora_client.soap_call() do |xml, args|
68
+ xml['ns1'].query do
69
+ xml['ns1'].queryString "select id, name from account"
70
+ end
71
+ end
72
+ ```
73
+ ### Query
74
+ ```ruby
75
+ zuora_client.query("select id from account")
76
+ ```
77
+ ### Data Export
78
+ Returns the file location of the data source export after downloading from Zuora
79
+
80
+ ```ruby
81
+ zuora_client.getDataSourceExport("select id from account")
82
+ ```
83
+
84
+ | Name | Description | Default | Example |
85
+ | --------- | ---------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------- |
86
+ | query | The query to execute | `N/A` | `zuora_client.getDataSourceExport("select id from account")` |
87
+ | zip | Indicates if the data source export should be a zip | `true` | `zuora_client.getDataSourceExport("select id from account", zip: false)` |
88
+ | extract | Indicates if the data source export should be extracted if it is a zip | `true` | `zuora_client.getDataSourceExport("select id from account", extract: false)` |
89
+ | encrypted | Indicates if the data source export should be encrypted | `false` | `zuora_client.getDataSourceExport("select id from account", encrypted: true)` |
90
+
91
+ ### Describe Call
92
+ This returns all available objects from the describe call as a hash. This response can be accessed by using response["Account"] to retrieve all related data about that object.
93
+
94
+ ```ruby
95
+ response = zuora_client.describe_call("Account")
96
+ ```
97
+ This returns all information and fields related to that object model as a hash.
98
+
99
+ ```ruby
100
+ response = zuora_client.describe_call()
101
+ ```
102
+
103
+ ### Journal Run
104
+ ```ruby
105
+ zuora_client.createJournalRun(call)
106
+ ```
107
+
108
+ ## Insights API
109
+
110
+ In order to make API calls a Zuora Login object must be created by running:
111
+
112
+ ```ruby
113
+ insightsapi = InsightsAPI::Login.new(api_token: "api token", url: "Nw1.api.insights.zuora.com/api/")
114
+ ```
115
+
116
+ Note that the login will default to the insights production url.
117
+
118
+ ```ruby
119
+ Date format: "YYYY-MM-DDT00:00:00Z"
120
+ ```
121
+
122
+ ### Uploading Data into Insights
123
+ ```ruby
124
+ insightsapi.upload_into_insights(dataSourceName, recordType, batchDate, filePath)
125
+ ```
126
+ dataSourceName: What system the data is coming from.
127
+ recordType: The type of records ie: "EVENTS, ATTRIBUTES, and METRICS"
128
+ batachDate: The date the data applies to.
129
+
130
+ ### Describing Insights Data
131
+ ```ruby
132
+ insightsapi.describe(type: "ACCOUNT/USER", object: "ATTRIBUTES/EVENTS/SEGMENTS/METRICS")
133
+ ```
134
+ Returns json payload describing attributes, events, metrics for each Account or User.
135
+
136
+ ### Downloading Data from Insights
137
+ ```ruby
138
+ insightsapi.data_export_insights(objecttype, segmentuuid, startDate: nil, endDate: nil, tries: 30)
139
+ ```
140
+ ```ruby
141
+ insightsapi.data_export_insights_file(objecttype, segmentuuid, startDate: nil, endDate: nil, tries: 30)
142
+ ```
143
+ Both do the same thing except one returns a url(data_export_insights) to download the file yourself and the other returns an actual Ruby temporary file(data_export_insights_file).
144
+
145
+ objectype: "ACCOUNT/USER"
146
+
147
+ segmentuuid: A single or array of string or int of a segment uuid(s) that you get from the describe call. The csv holds a column with a bool that represents if that User or Account belongs to that segment.
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: "../"
4
+
5
+ gem "rails", "~> 5.0.0"
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: "../"
4
+
5
+ gem "rails", "~> 5.1.0"
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: "../"
4
+
5
+ gem "rails", "~> 5.2.0"
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: "../"
4
+
5
+ gem "rails", "~> 6.0.0"
@@ -40,6 +40,19 @@ module ZuoraAPI
40
40
  def to_s
41
41
  @message || @default_message
42
42
  end
43
+
44
+ def parse_message(message)
45
+ case message
46
+ when /^Invalid Oauth Client Id$/, /^Unable to generate token.$/
47
+ @message = "Invalid login, please check client ID and Client Secret or URL endpoint"
48
+ when /^Forbidden$/
49
+ @message = "The user associated to OAuth credential set has been deactivated."
50
+ when /^Invalid login. User name and password do not match.$/
51
+ @message = "Invalid login, please check username and password or URL endpoint"
52
+ else
53
+ @message = message
54
+ end
55
+ end
43
56
  end
44
57
 
45
58
  class BadEntityError < Error
@@ -177,14 +190,15 @@ module ZuoraAPI
177
190
  end
178
191
 
179
192
  class ZuoraAPITemporaryError < Error
180
- attr_reader :code, :response
193
+ attr_reader :code, :response, :errors
181
194
  attr_writer :default_message
182
195
 
183
- def initialize(message = nil,response=nil, errors = [], successes = [], *args)
196
+ def initialize(message = nil, response = nil, errors = [], successes = [], *args)
184
197
  @code = response.class.to_s == "HTTParty::Response" ? response.code : nil
185
198
  @message = parse_message(message)
186
199
  @response = response
187
200
  @default_message = "There is a temporary error with zuora system."
201
+ @errors = errors
188
202
  end
189
203
 
190
204
  def to_s
@@ -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_Endpoint = '96.0'
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
11
11
  XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
12
12
 
13
13
  CONNECTION_EXCEPTIONS = [
@@ -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,10 +50,12 @@ 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]
53
55
  if !/apps\/services\/a\/\d+\.\d$/.match(url.strip)
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)
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)
57
59
  else
58
60
  self.url = url
59
61
  end
@@ -65,36 +67,18 @@ module ZuoraAPI
65
67
  self.status = status.blank? ? "Active" : status
66
68
  self.user_info = Hash.new
67
69
  self.update_region
68
- self.update_environment
69
70
  self.update_zconnect_provider
70
71
  @timeout_sleep = 5
71
72
  end
72
73
 
73
74
  def get_identity(cookies)
74
75
  zsession = cookies["ZSession"]
75
- zconnect_accesstoken = get_zconnect_accesstoken(cookies)
76
76
  begin
77
77
  if !zsession.blank?
78
78
  response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
79
79
  output_json = JSON.parse(response.body)
80
- elsif zconnect_accesstoken.present?
81
- begin
82
- code = zconnect_accesstoken.split("#!").last
83
- encrypted_token, tenant_id = Base64.decode64(code).split(":")
84
- body = {'token' => encrypted_token}.to_json
85
- rescue => ex
86
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie")
87
- end
88
- Rails.logger.info("Using ZConnect cookie in get_identity method")
89
-
90
- response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
91
- output_json = JSON.parse(response.body)
92
80
  else
93
- if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
94
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
95
- else
96
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
97
- end
81
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
98
82
  end
99
83
  rescue JSON::ParserError => ex
100
84
  output_json = {}
@@ -105,21 +89,12 @@ module ZuoraAPI
105
89
 
106
90
  def get_full_nav(cookies)
107
91
  zsession = cookies["ZSession"]
108
- zconnect_accesstoken = get_zconnect_accesstoken(cookies)
109
92
  begin
110
93
  if zsession.present?
111
94
  response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
112
95
  output_json = JSON.parse(response.body)
113
- elsif zconnect_accesstoken.present?
114
- Rails.logger.info("Using ZConnect cookie in get_full_nav method")
115
- response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
116
- output_json = JSON.parse(response.body)
117
96
  else
118
- if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
119
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
120
- else
121
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
122
- end
97
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
123
98
  end
124
99
  rescue JSON::ParserError => ex
125
100
  output_json = {}
@@ -130,21 +105,12 @@ module ZuoraAPI
130
105
 
131
106
  def set_nav(state, cookies)
132
107
  zsession = cookies["ZSession"]
133
- zconnect_accesstoken = get_zconnect_accesstoken(cookies)
134
108
  begin
135
109
  if !zsession.blank?
136
110
  response = HTTParty.put("https://#{self.hostname}/apps/v1/preference/navigation", :body => state.to_json, :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
137
111
  output_json = JSON.parse(response.body)
138
- elsif !zconnect_accesstoken.blank?
139
- Rails.logger.info("Using ZConnect cookie in set_nav method")
140
- response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/navigationstate", :body => state.to_json, :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
141
- output_json = JSON.parse(response.body)
142
112
  else
143
- if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
144
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
145
- else
146
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
147
- end
113
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
148
114
  end
149
115
  rescue JSON::ParserError => ex
150
116
  output_json = {}
@@ -155,21 +121,12 @@ module ZuoraAPI
155
121
 
156
122
  def refresh_nav(cookies)
157
123
  zsession = cookies["ZSession"]
158
- zconnect_accesstoken = get_zconnect_accesstoken(cookies)
159
124
  begin
160
125
  if !zsession.blank?
161
126
  response = HTTParty.post("https://#{self.hostname}/apps/v1/navigation/fetch", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
162
127
  output_json = JSON.parse(response.body)
163
- elsif !zconnect_accesstoken.blank?
164
- Rails.logger.info("Using ZConnect cookie in refresh_nav method")
165
- response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/refresh-navbarcache", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
166
- output_json = JSON.parse(response.body)
167
128
  else
168
- if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
169
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
170
- else
171
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
172
- end
129
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
173
130
  end
174
131
  rescue JSON::ParserError => ex
175
132
  output_json = {}
@@ -178,15 +135,6 @@ module ZuoraAPI
178
135
  return output_json
179
136
  end
180
137
 
181
- def get_zconnect_accesstoken(cookies)
182
- accesstoken = nil
183
- self.update_zconnect_provider
184
- if !cookies[self.zconnect_provider].nil? && !cookies[self.zconnect_provider].empty?
185
- accesstoken = cookies[self.zconnect_provider]
186
- end
187
- return accesstoken
188
- end
189
-
190
138
  def reporting_url(path)
191
139
  map = {"US" => {"Sandbox" => "https://zconnectsandbox.zuora.com/api/rest/v1/",
192
140
  "Production" => "https://zconnect.zuora.com/api/rest/v1/",
@@ -208,7 +156,7 @@ module ZuoraAPI
208
156
  # 1. Pass in cookies and optionally custom_authorities, name, and description
209
157
  # 2. Pass in user_id, entity_ids, client_id, client_secret, and optionally custom_authorities, name, and description
210
158
  # https://intranet.zuora.com/confluence/display/Sunburst/Create+an+OAuth+Client+through+API+Gateway#CreateanOAuthClientthroughAPIGateway-ZSession
211
- 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)
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)
212
160
  authorization = ""
213
161
  new_client_id = SecureRandom.uuid if new_client_id.blank?
214
162
  new_client_secret = SecureRandom.hex(10) if new_client_secret.blank?
@@ -234,11 +182,11 @@ module ZuoraAPI
234
182
  end
235
183
 
236
184
  if !authorization.blank? && !user_id.blank? && !entity_ids.blank?
237
- endpoint = self.rest_endpoint("genesis/clients")
185
+ endpoint = chomp_v1_from_genesis_endpoint ? self.rest_endpoint.chomp("v1/").concat("genesis/clients") : self.rest_endpoint("genesis/clients")
238
186
  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)
239
187
  output_json = JSON.parse(oauth_response.body)
240
188
  if oauth_response.code == 201
241
- output_json["clientSecret"] = new_client_secret
189
+ output_json["clientSecret"] = new_client_secret if !use_api_generated_client_secret
242
190
  return output_json
243
191
  elsif oauth_response.code == 401 && !oauth_response.message.blank?
244
192
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], oauth_response)
@@ -305,7 +253,7 @@ module ZuoraAPI
305
253
  end
306
254
 
307
255
  def update_environment
308
- if !self.url.blank?
256
+ if !self.hostname.blank?
309
257
  case self.hostname
310
258
  when /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/
311
259
  self.environment = 'Sandbox'
@@ -328,13 +276,13 @@ module ZuoraAPI
328
276
  end
329
277
 
330
278
  def update_zconnect_provider
331
- region = update_region
332
- environment = update_environment
279
+ update_region if self.region.blank?
280
+ update_environment if self.environment.blank?
333
281
  mappings = {"US" => {"Sandbox" => "ZConnectSbx", "Services" => "ZConnectSvcUS", "Production" => "ZConnectProd", "Performance" => "ZConnectPT1", "Test" => "ZConnectTest", "Staging" => "ZConnectQA", "KubeSTG" => "ZConnectDev", "KubeDEV" => "ZConnectDev", "KubePROD" => "ZConnectDev"},
334
282
  "NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "ZConnectSvcNA", "Production" => "ZConnectProdNA", "Performance" => "ZConnectPT1NA"},
335
283
  "EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "ZConnectSvcEU", "Production" => "ZConnectProdEU", "Performance" => "ZConnectPT1EU", "Test" => "ZConnectTest"},
336
284
  "Unknown" => {"Unknown" => "Unknown"}}
337
- self.zconnect_provider = mappings[region][environment]
285
+ self.zconnect_provider = mappings[self.region][self.environment]
338
286
  end
339
287
 
340
288
  def aqua_endpoint(url="")
@@ -374,8 +322,8 @@ module ZuoraAPI
374
322
  return domain ? endpoint.concat(prefix).concat(url) : prefix.concat(url)
375
323
  end
376
324
 
377
- def rest_domain
378
- return URI(self.rest_endpoint).host
325
+ def rest_domain(endpoint: self.rest_endpoint)
326
+ return URI(endpoint).host
379
327
  end
380
328
 
381
329
  def fileURL(url="")
@@ -387,10 +335,41 @@ module ZuoraAPI
387
335
  end
388
336
 
389
337
  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
+
390
370
  end
391
371
 
392
372
  def get_session(prefix: false, auth_type: :basic, zuora_track_id: nil)
393
- Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}") if Rails.env.to_s == 'development'
394
373
  case auth_type
395
374
  when :basic
396
375
  if self.current_session.blank?
@@ -399,14 +378,13 @@ module ZuoraAPI
399
378
  if self.bearer_token.blank? || self.oauth_expired?
400
379
  self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id)
401
380
  end
402
- self.get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
381
+ self.get_z_session(zuora_track_id: zuora_track_id)
403
382
  when 'ZuoraAPI::Basic'
404
383
  self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
405
384
  else
406
385
  self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
407
386
  end
408
387
  end
409
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
410
388
  return prefix ? "ZSession #{self.current_session}" : self.current_session.to_s
411
389
  when :bearer
412
390
  case self.class.to_s
@@ -419,8 +397,6 @@ module ZuoraAPI
419
397
  else
420
398
  raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Unknown Login, does not support Authentication of Type: #{auth_type}")
421
399
  end
422
-
423
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
424
400
  return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
425
401
  end
426
402
  end
@@ -428,16 +404,18 @@ module ZuoraAPI
428
404
  def soap_call(
429
405
  ns1: 'ns1',
430
406
  ns2: 'ns2',
431
- batch_size: nil,
407
+ batch_size: nil,
408
+ headers: {},
432
409
  single_transaction: false,
433
410
  debug: false,
434
411
  zuora_track_id: nil,
435
412
  errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
436
413
  z_session: true,
437
414
  timeout_retry: false,
438
- timeout: 120,
415
+ timeout: 130,
439
416
  timeout_sleep_interval: self.timeout_sleep,
440
417
  output_exception_messages: true,
418
+ skip_session: false,
441
419
  **keyword_args)
442
420
  tries ||= 2
443
421
  xml = Nokogiri::XML::Builder.new do |xml|
@@ -447,8 +425,10 @@ module ZuoraAPI
447
425
  'xmlns:api' => "http://api.zuora.com/",
448
426
  "xmlns:#{ns1}" => "http://api.zuora.com/") do
449
427
  xml['SOAP-ENV'].Header do
450
- xml["#{ns1}"].SessionHeader do
451
- xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
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
452
432
  end
453
433
  if single_transaction
454
434
  xml["#{ns1}"].CallOptions do
@@ -466,12 +446,11 @@ module ZuoraAPI
466
446
  end
467
447
  end
468
448
  end
469
-
470
449
  input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
471
450
  input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
472
451
  Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
473
452
 
474
- headers = { 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'}
453
+ headers.merge!({ 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'})
475
454
  headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
476
455
 
477
456
  request = HTTParty::Request.new(
@@ -488,7 +467,11 @@ module ZuoraAPI
488
467
  Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
489
468
 
490
469
  raise_errors(type: :SOAP, body: output_xml, response: response)
470
+
471
+ return output_xml, input_xml, response
472
+
491
473
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
474
+ raise if skip_session
492
475
  if !tries.zero? && z_session
493
476
  tries -= 1
494
477
  Rails.logger.debug("SOAP Call - Session Invalid")
@@ -500,39 +483,33 @@ module ZuoraAPI
500
483
  end
501
484
 
502
485
  retry
503
- else
504
- if errors.include?(ex.class)
505
- raise ex
506
- else
507
- return output_xml, input_xml, response
508
- end
509
486
  end
487
+
488
+ raise ex if errors.include?(ex.class)
489
+
490
+ return output_xml, input_xml, response
491
+
510
492
  rescue *ZUORA_API_ERRORS => ex
511
- if errors.include?(ex.class)
512
- raise ex
513
- else
514
- response = ex.response unless response
515
- return output_xml, input_xml, response
516
- end
493
+ raise ex if errors.include?(ex.class)
494
+
495
+ response = ex.response unless response
496
+ return output_xml, input_xml, response
497
+
517
498
  rescue *CONNECTION_EXCEPTIONS => ex
518
- if tries.zero?
519
- if output_exception_messages
520
- if Rails.logger.class.to_s == "Ougai::Logger"
521
- Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
522
- else
523
- Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
524
- end
525
- end
526
- raise ex
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
527
504
  end
528
505
 
529
- tries -= 1
530
- sleep(timeout_sleep_interval)
531
- retry
506
+ self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
507
+ raise ex
508
+
532
509
  rescue *CONNECTION_READ_EXCEPTIONS => ex
533
510
  if !tries.zero?
534
511
  tries -= 1
535
-
512
+ self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
536
513
  if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
537
514
  retry
538
515
  elsif timeout_retry
@@ -541,19 +518,74 @@ module ZuoraAPI
541
518
  end
542
519
  end
543
520
 
544
- if output_exception_messages
545
- if Rails.logger.class.to_s == "Ougai::Logger"
546
- Rails.logger.error("SOAP Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
547
- else
548
- Rails.logger.error("SOAP Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
549
- end
550
- end
551
- raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
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 timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.instance_of?(Net::ReadTimeout)
552
523
  raise ex
524
+
553
525
  rescue => ex
554
526
  raise ex
555
- else
556
- return output_xml, input_xml, response
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
557
589
  end
558
590
 
559
591
  def raise_errors(type: :SOAP, body: nil, response: nil)
@@ -570,13 +602,13 @@ module ZuoraAPI
570
602
  end
571
603
 
572
604
  if [502,503].include?(response.code)
573
- raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from #{request_uri}", response)
605
+ raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from 'https://#{rest_domain(endpoint: request_uri)}'", response)
574
606
  end
575
607
 
576
608
  # Check failure response code
577
609
  case response.code
578
610
  when 504
579
- raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{request_uri}", response)
611
+ raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response)
580
612
  when 429
581
613
  raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("The total number of concurrent requests has exceeded the limit allowed by the system. Please resubmit your request later.", response)
582
614
  when 401
@@ -597,6 +629,10 @@ module ZuoraAPI
597
629
  when :SOAP
598
630
  error, success, message = get_soap_error_and_message(body)
599
631
 
632
+ if body.xpath('//fns:LoginFault', 'fns' =>'http://fault.api.zuora.com/').present?
633
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response)
634
+ end
635
+
600
636
  if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
601
637
  body.xpath(
602
638
  '//ns1:records[@xsi:type="ns2:Export"]',
@@ -604,12 +640,12 @@ module ZuoraAPI
604
640
  ).present?
605
641
  result = body.xpath('//ns2:Status', 'ns2' => 'http://object.api.zuora.com/').text
606
642
  if result == 'Failed'
607
- reason = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
608
- if reason.present?
609
- message = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text
610
- 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'
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?
611
648
  else
612
- error = 'FATAL_ERROR'
613
649
  message = 'Export failed due to unknown reason. Consult api logs.'
614
650
  end
615
651
  end
@@ -658,14 +694,31 @@ module ZuoraAPI
658
694
  when /^GET::400::\/api\/rest\/v1\/reports\/(reportlabels\/)?([a-zA-Z0-9\-_]+)\/report-details$/ # Get report, capture of the id is present if needed in future error responses.
659
695
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
660
696
  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']
661
703
  end
662
704
 
663
705
  body = body.dig("results").present? ? body["results"] : body if body.class == Hash
664
706
  if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
665
- messages_array = body.fetch("reasons", []).map {|error| error['message']}.compact
666
- messages_array = messages_array.push(body.dig("error", 'message')).compact if body.dig('error').class == Hash
667
- codes_array = body.fetch("reasons", []).map {|error| error['code']}.compact
668
- codes_array = codes_array.push(body.dig("error", 'code')).compact if body.dig('error').class == Hash
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
669
722
 
670
723
  if body['message'] == 'request exceeded limit'
671
724
  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)
@@ -697,7 +750,11 @@ module ZuoraAPI
697
750
  end
698
751
 
699
752
  if body['error'] == 'Unauthorized' && body['status'] == 401
700
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
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
701
758
  end
702
759
  #Authentication failed
703
760
  if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
@@ -804,7 +861,7 @@ module ZuoraAPI
804
861
  output_json = JSON.parse(response.body)
805
862
  self.raise_errors(type: :JSON, body: output_json, response: response)
806
863
 
807
- elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml')) and type != :xml
864
+ elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml') || response_content_types.include?('application/soap+xml')) and type != :xml
808
865
  output_xml = Nokogiri::XML(response.body)
809
866
  self.raise_errors(type: :SOAP, body: output_xml, response: response)
810
867
 
@@ -824,6 +881,8 @@ module ZuoraAPI
824
881
  raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
825
882
  when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
826
883
  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)
827
886
  else
828
887
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
829
888
  end
@@ -850,6 +909,11 @@ module ZuoraAPI
850
909
  message = body.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text
851
910
  end
852
911
 
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
+
853
917
  #Update/Create/Delete Calls with multiple requests and responses
854
918
  if body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').size > 0 && body.xpath('//ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
855
919
  error = []
@@ -893,17 +957,22 @@ module ZuoraAPI
893
957
  raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
894
958
  end
895
959
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
896
- 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/
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/
897
961
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
898
962
  when /.*UNEXPECTED_ERROR/
899
963
  raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
900
964
  when /.*soapenv:Server.*/
901
965
  if /^Invalid value.*for type.*|^Id is invalid|^date string can not be less than 19 charactors$/.match(message).present?
902
966
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
903
- elsif /^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
967
+ elsif /^unknown$|^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
904
968
  raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
905
969
  end
906
970
  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)
907
976
  else
908
977
  raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Z:#{error}::#{message}", response, errors, success)
909
978
  end
@@ -953,7 +1022,7 @@ module ZuoraAPI
953
1022
  base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
954
1023
  url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
955
1024
  headers = self.entity_id.present? ? {"Zuora-Entity-Ids" => self.entity_id, 'Content-Type' => "text/xml; charset=utf-8"} : {'Content-Type' => "text/xml; charset=utf-8"}
956
- response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
1025
+ response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 130)
957
1026
 
958
1027
  raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
959
1028
 
@@ -986,35 +1055,31 @@ module ZuoraAPI
986
1055
  end
987
1056
  des_hash[:related_objects] = output_xml.xpath(".//related-objects").xpath(".//object").map{ |x| [x.xpath(".//name").text.to_sym, [ [:url, x.attributes["href"].value], [:label, x.xpath(".//name").text ] ].to_h] }.to_h
988
1057
  end
1058
+
1059
+ return des_hash
989
1060
  rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
990
- if tries.zero?
991
- if log_errors
992
- if Rails.logger.class.to_s == "Ougai::Logger"
993
- Rails.logger.error("Describe - Timed out will retry after #{self.timeout_sleep} seconds", ex)
994
- else
995
- Rails.logger.error("Describe - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
996
- end
997
- end
998
- raise ex
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
999
1066
  end
1000
1067
 
1001
- tries -= 1
1002
- sleep(self.timeout_sleep)
1003
- retry
1068
+ self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors
1069
+ raise ex
1070
+
1004
1071
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1005
1072
  if !tries.zero? && self.status == 'Active'
1006
1073
  tries -= 1
1007
1074
  Rails.logger.debug("Describe session expired. Starting new session.")
1008
1075
  self.new_session
1009
1076
  retry
1010
- else
1011
- Rails.logger.error("Describe session expired. Starting new session.") if log_errors
1012
- raise ex
1013
1077
  end
1078
+
1079
+ Rails.logger.error("Describe session expired. Starting new session.") if log_errors
1080
+ raise ex
1014
1081
  rescue => ex
1015
1082
  raise ex
1016
- else
1017
- return des_hash
1018
1083
  end
1019
1084
 
1020
1085
  def rest_call(
@@ -1027,11 +1092,12 @@ module ZuoraAPI
1027
1092
  z_session: true,
1028
1093
  session_type: :basic,
1029
1094
  timeout_retry: false,
1030
- timeout: 120,
1095
+ timeout: 130,
1031
1096
  timeout_sleep_interval: self.timeout_sleep,
1032
1097
  multipart: false,
1033
1098
  stream_body: false,
1034
1099
  output_exception_messages: true,
1100
+ zuora_track_id: nil,
1035
1101
  **keyword_args,
1036
1102
  &block
1037
1103
  )
@@ -1041,12 +1107,13 @@ module ZuoraAPI
1041
1107
 
1042
1108
  authentication_headers = {}
1043
1109
  if z_session
1044
- authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type) }
1110
+ authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type, zuora_track_id: zuora_track_id) }
1045
1111
  if self.entity_id.present?
1046
1112
  authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
1047
1113
  authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
1048
1114
  end
1049
1115
  end
1116
+ headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
1050
1117
 
1051
1118
  modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
1052
1119
 
@@ -1072,18 +1139,20 @@ module ZuoraAPI
1072
1139
  Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
1073
1140
 
1074
1141
  raise_errors(type: :JSON, body: output_json, response: response)
1075
- rescue
1142
+ rescue => ex
1076
1143
  reset_files(body) if multipart
1077
1144
  raise
1078
1145
  end
1146
+
1147
+ return [output_json, response]
1079
1148
  rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
1080
1149
  if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
1081
1150
  session_type = :bearer
1082
1151
  retry
1083
- else
1084
- Rails.logger.debug("Rest Call - Session Bad Auth type")
1085
- raise ex
1086
1152
  end
1153
+ Rails.logger.debug("Rest Call - Session Bad Auth type")
1154
+ raise ex
1155
+
1087
1156
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1088
1157
  if !tries.zero? && z_session
1089
1158
  tries -= 1
@@ -1096,40 +1165,35 @@ module ZuoraAPI
1096
1165
  end
1097
1166
 
1098
1167
  retry
1099
- else
1100
- if errors.include?(ex.class)
1101
- raise ex
1102
- else
1103
- return [output_json, response]
1104
- end
1105
1168
  end
1169
+
1170
+ raise ex if errors.include?(ex.class)
1171
+ return [output_json, response]
1172
+
1106
1173
  rescue *ZUORA_API_ERRORS => ex
1107
- if errors.include?(ex.class)
1108
- raise ex
1109
- else
1110
- response = ex.response unless response
1111
- return [output_json, response]
1112
- end
1174
+ raise ex if errors.include?(ex.class)
1175
+
1176
+ response = ex.response unless response
1177
+ return [output_json, response]
1178
+
1113
1179
  rescue ZuoraAPI::Exceptions::BadEntityError => ex
1114
1180
  raise ex
1115
1181
  rescue *CONNECTION_EXCEPTIONS => ex
1116
- if tries.zero?
1117
- if output_exception_messages
1118
- if Rails.logger.class.to_s == "Ougai::Logger"
1119
- Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
1120
- else
1121
- Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
1122
- end
1123
- end
1124
- raise ex
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
1125
1187
  end
1126
1188
 
1127
- tries -= 1
1128
- sleep(timeout_sleep_interval)
1129
- retry
1189
+ self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if output_exception_messages
1190
+ raise ex
1191
+
1130
1192
  rescue *CONNECTION_READ_EXCEPTIONS => ex
1193
+
1131
1194
  if !tries.zero?
1132
1195
  tries -= 1
1196
+ self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug)
1133
1197
  if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
1134
1198
  retry
1135
1199
  elsif timeout_retry
@@ -1137,20 +1201,15 @@ module ZuoraAPI
1137
1201
  retry
1138
1202
  end
1139
1203
  end
1140
-
1141
- if output_exception_messages
1142
- if Rails.logger.class.to_s == "Ougai::Logger"
1143
- Rails.logger.error("Rest Call - Timed out will retry after #{timeout_sleep_interval} seconds", ex)
1144
- else
1145
- Rails.logger.error("Rest Call - #{ex.class} Timed out will retry after #{timeout_sleep_interval} seconds")
1146
- end
1147
- end
1148
- raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
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 timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.instance_of?(Net::ReadTimeout)
1149
1207
  raise ex
1208
+
1150
1209
  rescue => ex
1151
1210
  raise ex
1152
- else
1153
- return [output_json, response]
1211
+ ensure
1212
+ self.error_logger(ex) if defined?(ex) && Rails.logger.class.to_s == "Ougai::Logger"
1154
1213
  end
1155
1214
 
1156
1215
  def update_create_tenant
@@ -1172,8 +1231,9 @@ module ZuoraAPI
1172
1231
  while !response["nextPage"].blank?
1173
1232
  url = self.rest_endpoint(response["nextPage"].split('/v1/').last)
1174
1233
  Rails.logger.debug("Fetch Catalog URL #{url}")
1175
- output_json, response = self.rest_call(:debug => false, :url => url, :errors => [ZuoraAPI::Exceptions::ZuoraAPISessionError], :timeout_retry => true )
1176
- if !output_json['success'] =~ (/(true|t|yes|y|1)$/i) || output_json['success'].class != TrueClass
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
1177
1237
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
1178
1238
  end
1179
1239
  output_json["products"].each do |product|
@@ -1199,7 +1259,7 @@ module ZuoraAPI
1199
1259
  return products, catalog_map
1200
1260
  end
1201
1261
 
1202
- def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout: 120, session_type: :basic, **execute_params)
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)
1203
1263
  raise "file_path must be of class Pathname" if file_path.class != Pathname
1204
1264
 
1205
1265
  retry_count ||= timeout_retries
@@ -1304,14 +1364,20 @@ module ZuoraAPI
1304
1364
  return file_handle
1305
1365
  when Net::HTTPUnauthorized
1306
1366
  if z_session
1307
- if !(retry_count -= 1).zero?
1367
+ unless (retry_count -= 1).zero?
1308
1368
  self.new_session
1309
- raise response.class
1310
- else
1311
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
1369
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError, 'Retrying'
1312
1370
  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
+ )
1313
1379
  else
1314
- raise
1380
+ raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
1315
1381
  end
1316
1382
  else
1317
1383
  raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
@@ -1322,133 +1388,81 @@ module ZuoraAPI
1322
1388
  sleep(5)
1323
1389
  if (retry_count -= 1) >= 0
1324
1390
  retry
1325
- else
1326
- Rails.logger.error("File Download Failed")
1327
- raise
1328
1391
  end
1392
+ Rails.logger.error("File Download Failed")
1393
+ raise
1329
1394
  end
1330
1395
 
1331
1396
  def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
1332
- begin
1333
- tries ||= 3
1334
- request = Nokogiri::XML::Builder.new do |xml|
1335
- xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:ns2' => "http://object.api.zuora.com/", 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", 'xmlns:ns1' => "http://api.zuora.com/") do
1336
- xml['SOAP-ENV'].Header do
1337
- xml['ns1'].SessionHeader do
1338
- xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
1339
- end
1340
- end
1341
- xml['SOAP-ENV'].Body do
1342
- xml['ns1'].create do
1343
- xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
1344
- xml['ns2'].Format 'csv'
1345
- xml['ns2'].Zip zip
1346
- xml['ns2'].Name 'googman'
1347
- xml['ns2'].Query query
1348
- xml['ns2'].Encrypted encrypted
1349
- end
1350
- end
1351
- end
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
1352
1407
  end
1353
1408
  end
1354
-
1355
- response_query = HTTParty.post(self.url, body: request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8", "Z-Track-Id" => z_track_id}, :timeout => 120)
1356
-
1357
- output_xml = Nokogiri::XML(response_query.body)
1358
- raise_errors(type: :SOAP, body: output_xml, response: response_query) if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
1359
-
1360
- # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
1361
-
1362
- id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
1363
-
1364
- confirmRequest = Nokogiri::XML::Builder.new do |xml|
1365
- xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:ns2' => "http://object.api.zuora.com/", 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", 'xmlns:ns1' => "http://api.zuora.com/") do
1366
- xml['SOAP-ENV'].Header do
1367
- xml['ns1'].SessionHeader do
1368
- xml['ns1'].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: z_track_id)
1369
- end
1370
- end
1371
- xml['SOAP-ENV'].Body do
1372
- xml['ns1'].query do
1373
- xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'"
1374
- end
1375
- 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}'"
1376
1419
  end
1377
1420
  end
1378
- result = 'Waiting'
1379
-
1380
- while result != "Completed"
1381
- sleep 3
1382
- response_query = HTTParty.post(self.url, body: confirmRequest.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8", "Z-Track-Id" => z_track_id}, :timeout => 120)
1383
-
1384
- output_xml = Nokogiri::XML(response_query.body)
1385
- result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
1386
- status_code = response_query.code if response_query
1387
-
1388
- raise_errors(type: :SOAP, body: output_xml, response: response_query) if result.blank? || result == "Failed"
1389
- # raise "Export Creation Unsuccessful : #{response_query.code}: #{response_query.parsed_response}" if result.blank? || result == "Failed"
1390
- end
1391
-
1392
- file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
1393
- export_file = get_file(:url => self.fileURL(file_id))
1394
- export_file_path = export_file.path
1395
- Rails.logger.debug("=====> Export path #{export_file.path}")
1396
-
1397
- if extract && zip
1398
- require "zip"
1399
- new_path = export_file_path.partition('.zip').first
1400
- zipped = Zip::File.open(export_file_path)
1401
- file_handle = zipped.entries.first
1402
- file_handle.extract(new_path)
1403
- File.delete(export_file_path)
1404
- return new_path
1405
- else
1406
- return export_file_path
1407
- end
1408
- rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
1409
- if !(tries -= 1).zero?
1410
- Rails.logger.info("Export call failed - Trace ID: #{z_track_id}")
1411
- self.new_session
1412
- retry
1413
- else
1414
- raise ex
1415
- end
1416
-
1417
- rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex
1418
- if !(tries -= 1).zero?
1419
- Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds")
1420
- sleep 10
1421
- retry
1422
- else
1423
- raise ex
1424
- end
1425
-
1426
- rescue *ZUORA_API_ERRORS => ex
1427
- raise ex
1428
-
1429
- rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
1430
- if !(tries -= 1).zero?
1431
- Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds")
1432
- sleep 5
1433
- retry
1434
- else
1435
- raise ex
1436
- end
1421
+ result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
1422
+ end
1437
1423
 
1438
- rescue Errno::ECONNRESET => ex
1439
- if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
1440
- retry
1441
- else
1442
- raise ex
1443
- end
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
1444
1446
 
1445
- rescue ZuoraAPI::Exceptions::BadEntityError => ex
1446
- raise ex
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
1447
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
1460
+ end
1461
+ raise ex
1448
1462
  end
1449
1463
 
1450
1464
  def query(query, parse = false)
1451
- output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
1465
+ output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true) do |xml|
1452
1466
  xml['ns1'].query do
1453
1467
  xml['ns1'].queryString query
1454
1468
  end