zuora_api 1.7.03 → 1.7.7
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 +4 -4
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +2 -2
- data/CHANGELOG.md +17 -0
- data/README.md +1 -1
- data/lib/insights_api/login.rb +5 -6
- data/lib/zuora_api/exceptions.rb +129 -22
- data/lib/zuora_api/login.rb +623 -325
- data/lib/zuora_api/logins/basic.rb +15 -6
- data/lib/zuora_api/logins/oauth.rb +56 -34
- data/lib/zuora_api/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1215bc1af56e355b1e454f84b465e380280e1915c978b37003e9bb01bdcd73e4
|
|
4
|
+
data.tar.gz: e702c8c5d31fc49aabf4ea71a27ff409deb6bc304603335602a4fa2e80ad5f82
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bff03abeeb11116c1d75fdef3299182dde6452a5da95113f8a124afcbfa065f3c06ba04496bec6008d1e2b793c4a454fcd3471d2879f8390714178ab2e09ee65
|
|
7
|
+
data.tar.gz: 0fcbaab89256770c7f3fe616839ba402bac33122c474ac6ac16068ae67badb959bace310af9a12171b41ff2a064050f0fa44c7c09262eae3d707151da092abcc
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
CHANGED
|
@@ -48,8 +48,8 @@ rubygems-deploy:
|
|
|
48
48
|
- if [[ "staging" == $CI_BUILD_REF_SLUG ]];then export VERSION=`git describe --match "[0-9]*\.[0-9]*\.[0-9]*[a-z]" --abbrev=0 --tags HEAD`; fi
|
|
49
49
|
- if [[ "master" == $CI_BUILD_REF_SLUG ]];then export VERSION=`git describe --exclude "[0-9]*\.[0-9]*\.[0-9]*[a-z]" --abbrev=0 --tags HEAD`; fi
|
|
50
50
|
- echo $VERSION
|
|
51
|
-
- sed -i "s/0.0.1/$VERSION/"
|
|
52
|
-
- git add
|
|
51
|
+
- sed -i "s/0.0.1/$VERSION/" lib/zuora_api/version.rb
|
|
52
|
+
- git add lib/zuora_api/version.rb
|
|
53
53
|
- git config --global user.email "connect@zuora.com"
|
|
54
54
|
- git config --global user.name "Connect Automation"
|
|
55
55
|
- git commit -m "Automated Version Update $VERSION"
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
|
|
4
|
+
## [1.7.07] - 2018-9-10
|
|
5
|
+
### Changed
|
|
6
|
+
- Cookie name for service endpoint integration
|
|
7
|
+
|
|
8
|
+
## [1.7.06] - 2018-8-25
|
|
9
|
+
### Added
|
|
10
|
+
- Retry for 502/503
|
|
11
|
+
- Standard exception for 504
|
|
12
|
+
|
|
13
|
+
## [1.7.05] - 2018-8-25
|
|
14
|
+
### Added
|
|
15
|
+
- Added support for oauth token forbidden
|
|
16
|
+
|
|
17
|
+
## [1.7.02] - 2018-8-23
|
|
18
|
+
### Added
|
|
19
|
+
- Added mulit part support for rest call
|
|
20
|
+
|
|
4
21
|
## [1.7.01] - 2018-8-06
|
|
5
22
|
### Changed
|
|
6
23
|
- Changed library used to determine host
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Zuora Gem
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/rb/zuora_api) [](https://badge.fury.io/rb/zuora_api) [](https://gitlab.0.ecc.auw2.zuora/extension-products/shared-libraries/zuora-gem/commits/master)
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
Add this line to your application's Gemfile:
|
data/lib/insights_api/login.rb
CHANGED
|
@@ -190,12 +190,11 @@ module InsightsAPI
|
|
|
190
190
|
end
|
|
191
191
|
|
|
192
192
|
rescue => ex
|
|
193
|
-
if
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
end
|
|
193
|
+
raise ex if tries.zero?
|
|
194
|
+
|
|
195
|
+
tries -= 1
|
|
196
|
+
sleep 3
|
|
197
|
+
retry
|
|
199
198
|
else
|
|
200
199
|
return temp_file
|
|
201
200
|
end
|
data/lib/zuora_api/exceptions.rb
CHANGED
|
@@ -1,14 +1,38 @@
|
|
|
1
1
|
module ZuoraAPI
|
|
2
2
|
module Exceptions
|
|
3
|
-
class Error < StandardError;
|
|
3
|
+
class Error < StandardError;
|
|
4
|
+
def parse_message(message)
|
|
5
|
+
case message
|
|
6
|
+
when /^Payment status should be Processed. Invalid payment is P-\d*./
|
|
7
|
+
@message = "Payment status should be Processed."
|
|
8
|
+
when /^Adjustment cannot be created for invoice(.*) with a zero balance./
|
|
9
|
+
@message = "Adjustment cannot be created for invoice with a zero balance."
|
|
10
|
+
when /^The balance of all the invoice items and tax items is 0. No write-off is needed for the invoice .*./
|
|
11
|
+
@message = "The balance of all the invoice items and tax items is 0. No write-off is needed for the invoice."
|
|
12
|
+
when /^Json input does not match schema. Error(s): string ".*" is too long .*/
|
|
13
|
+
@message = "Json input does not match schema. Error(s): String is too long."
|
|
14
|
+
when /^Query failed \(#[\d\w_]*\): line [0-9]+:[0-9]+: (.*)$/
|
|
15
|
+
@message = "Query failed: #{$1}"
|
|
16
|
+
when /^Query failed \(#[\d\w_]*\): (.*)$/
|
|
17
|
+
@message = "Query failed: #{$1}"
|
|
18
|
+
when /^Could not find [\w\d]{32}.$/
|
|
19
|
+
@message = "Could not find object."
|
|
20
|
+
when /^Subscription [\w\d]{32} is in expired status. It is not supported to generate billing documents for expired subscriptions./
|
|
21
|
+
@message = "Subscription is in expired status. It is not supported to generate billing documents for expired subscriptions."
|
|
22
|
+
else
|
|
23
|
+
@message = message
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
class FileDownloadError < StandardError; end
|
|
4
28
|
class AuthorizationNotPerformed < Error; end
|
|
5
29
|
class ZuoraAPISessionError < Error
|
|
6
30
|
attr_reader :code, :response
|
|
7
31
|
attr_writer :default_message
|
|
8
32
|
|
|
9
|
-
def initialize(message = nil,response=nil)
|
|
10
|
-
@code = response.
|
|
11
|
-
@message = message
|
|
33
|
+
def initialize(message = nil,response=nil, errors = [], successes = [])
|
|
34
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
35
|
+
@message = parse_message(message)
|
|
12
36
|
@response = response
|
|
13
37
|
@default_message = "Error with Zuora Session."
|
|
14
38
|
end
|
|
@@ -23,8 +47,8 @@ module ZuoraAPI
|
|
|
23
47
|
attr_writer :default_message
|
|
24
48
|
|
|
25
49
|
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
26
|
-
@code = response.
|
|
27
|
-
@message = message
|
|
50
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
51
|
+
@message = parse_message(message)
|
|
28
52
|
@response = response
|
|
29
53
|
@default_message = "Error with Zuora Entity"
|
|
30
54
|
@errors = errors
|
|
@@ -41,8 +65,8 @@ module ZuoraAPI
|
|
|
41
65
|
attr_writer :default_message
|
|
42
66
|
|
|
43
67
|
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
44
|
-
@code = response.
|
|
45
|
-
@message = message
|
|
68
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
69
|
+
@message = parse_message(message)
|
|
46
70
|
@response = response
|
|
47
71
|
@default_message = "Error communicating with Zuora."
|
|
48
72
|
@errors = errors
|
|
@@ -54,13 +78,31 @@ module ZuoraAPI
|
|
|
54
78
|
end
|
|
55
79
|
end
|
|
56
80
|
|
|
81
|
+
class ZuoraAPIInternalServerError < Error
|
|
82
|
+
attr_reader :code, :response, :errors, :successes
|
|
83
|
+
attr_writer :default_message
|
|
84
|
+
|
|
85
|
+
def initialize(message = nil,response = nil, errors = [], successes = [], *args)
|
|
86
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
87
|
+
@message = parse_message(message)
|
|
88
|
+
@response = response
|
|
89
|
+
@default_message = "Zuora Internal Server Error."
|
|
90
|
+
@errors = errors
|
|
91
|
+
@successes = successes
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def to_s
|
|
95
|
+
@message || @default_message
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
57
99
|
class ZuoraAPIRequestLimit < Error
|
|
58
100
|
attr_reader :code, :response
|
|
59
101
|
attr_writer :default_message
|
|
60
102
|
|
|
61
|
-
def initialize(message = nil,response=nil,
|
|
62
|
-
@code = response.
|
|
63
|
-
@message = message
|
|
103
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
104
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
105
|
+
@message = parse_message(message)
|
|
64
106
|
@response = response
|
|
65
107
|
@default_message = "Your request limit has been exceeded for zuora."
|
|
66
108
|
end
|
|
@@ -70,13 +112,29 @@ module ZuoraAPI
|
|
|
70
112
|
end
|
|
71
113
|
end
|
|
72
114
|
|
|
115
|
+
class ZuoraAPIUnkownError < Error
|
|
116
|
+
attr_reader :code, :response
|
|
117
|
+
attr_writer :default_message
|
|
118
|
+
|
|
119
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
120
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
121
|
+
@message = parse_message(message)
|
|
122
|
+
@response = response
|
|
123
|
+
@default_message = "An unkown error occured. Workflow is not responsible. Please contact Support."
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def to_s
|
|
127
|
+
@message || @default_message
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
73
131
|
class ZuoraAPILockCompetition < Error
|
|
74
132
|
attr_reader :code, :response
|
|
75
133
|
attr_writer :default_message
|
|
76
134
|
|
|
77
|
-
def initialize(message = nil,response=nil,
|
|
78
|
-
@code = response.
|
|
79
|
-
@message = message
|
|
135
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
136
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
137
|
+
@message = parse_message(message)
|
|
80
138
|
@response = response
|
|
81
139
|
@default_message = "Operation failed due to lock competition. Please retry"
|
|
82
140
|
end
|
|
@@ -90,9 +148,9 @@ module ZuoraAPI
|
|
|
90
148
|
attr_reader :code, :response
|
|
91
149
|
attr_writer :default_message
|
|
92
150
|
|
|
93
|
-
def initialize(message = nil,response=nil,
|
|
94
|
-
@code = response.
|
|
95
|
-
@message = message
|
|
151
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
152
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
153
|
+
@message = parse_message(message)
|
|
96
154
|
@response = response
|
|
97
155
|
@default_message = "Operation failed due to lock competition. Please retry"
|
|
98
156
|
end
|
|
@@ -102,13 +160,29 @@ module ZuoraAPI
|
|
|
102
160
|
end
|
|
103
161
|
end
|
|
104
162
|
|
|
163
|
+
class ZuoraUnexpectedError < Error
|
|
164
|
+
attr_reader :code, :response
|
|
165
|
+
attr_writer :default_message
|
|
166
|
+
|
|
167
|
+
def initialize(message = nil, response=nil, errors = [], successes = [], *args)
|
|
168
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
169
|
+
@message = parse_message(message)
|
|
170
|
+
@response = response
|
|
171
|
+
@default_message = "An unexpected error occurred"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def to_s
|
|
175
|
+
@message || @default_message
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
105
179
|
class ZuoraAPITemporaryError < Error
|
|
106
180
|
attr_reader :code, :response
|
|
107
181
|
attr_writer :default_message
|
|
108
182
|
|
|
109
|
-
def initialize(message = nil,response=nil, *args)
|
|
110
|
-
@code = response.
|
|
111
|
-
@message = message
|
|
183
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
184
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
185
|
+
@message = parse_message(message)
|
|
112
186
|
@response = response
|
|
113
187
|
@default_message = "There is a temporary error with zuora system."
|
|
114
188
|
end
|
|
@@ -122,10 +196,43 @@ module ZuoraAPI
|
|
|
122
196
|
attr_reader :code, :response
|
|
123
197
|
attr_writer :default_message
|
|
124
198
|
|
|
125
|
-
def initialize(message = nil,response=nil,
|
|
126
|
-
@code = response.
|
|
199
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
200
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
201
|
+
@message = parse_message(message)
|
|
202
|
+
@response = response
|
|
203
|
+
@default_message = "Authentication type is not supported by this Login"
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def to_s
|
|
207
|
+
@message || @default_message
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
class ZuoraAPIConnectionTimeout < Net::OpenTimeout
|
|
212
|
+
attr_reader :code, :response
|
|
213
|
+
attr_writer :default_message
|
|
214
|
+
|
|
215
|
+
def initialize(message = nil,response=nil, errors = [], successes = [], *args)
|
|
216
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
217
|
+
@message = message
|
|
218
|
+
@response = response
|
|
219
|
+
@default_message = "Authentication type is not supported by this Login"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def to_s
|
|
223
|
+
@message || @default_message
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
class ZuoraAPIReadTimeout < Net::ReadTimeout
|
|
228
|
+
attr_reader :code, :response, :request
|
|
229
|
+
attr_writer :default_message
|
|
230
|
+
|
|
231
|
+
def initialize(message = nil, response = nil, request = nil, errors = [], successes = [], *args)
|
|
232
|
+
@code = response.class.to_s == "HTTParty::Response" ? response.code : nil
|
|
127
233
|
@message = message
|
|
128
234
|
@response = response
|
|
235
|
+
@request = request
|
|
129
236
|
@default_message = "Authentication type is not supported by this Login"
|
|
130
237
|
end
|
|
131
238
|
|
data/lib/zuora_api/login.rb
CHANGED
|
@@ -5,13 +5,44 @@ require 'zuora_api/exceptions'
|
|
|
5
5
|
|
|
6
6
|
module ZuoraAPI
|
|
7
7
|
class Login
|
|
8
|
-
ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown', STAGING = 'Staging' ]
|
|
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
10
|
MIN_Endpoint = '96.0'
|
|
11
11
|
XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
|
|
13
|
+
CONNECTION_EXCEPTIONS = [
|
|
14
|
+
Net::OpenTimeout,
|
|
15
|
+
OpenSSL::SSL::SSLError,
|
|
16
|
+
Errno::ECONNREFUSED,
|
|
17
|
+
SocketError,
|
|
18
|
+
Errno::EHOSTUNREACH,
|
|
19
|
+
Errno::EADDRNOTAVAIL,
|
|
20
|
+
Errno::ETIMEDOUT,
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
CONNECTION_READ_EXCEPTIONS = [
|
|
24
|
+
Net::ReadTimeout,
|
|
25
|
+
Errno::ECONNRESET,
|
|
26
|
+
Errno::EPIPE
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
ZUORA_API_ERRORS = [
|
|
30
|
+
ZuoraAPI::Exceptions::ZuoraAPIError,
|
|
31
|
+
ZuoraAPI::Exceptions::ZuoraAPIRequestLimit,
|
|
32
|
+
ZuoraAPI::Exceptions::ZuoraAPILockCompetition,
|
|
33
|
+
ZuoraAPI::Exceptions::ZuoraAPITemporaryError,
|
|
34
|
+
ZuoraAPI::Exceptions::ZuoraDataIntegrity,
|
|
35
|
+
ZuoraAPI::Exceptions::ZuoraAPIInternalServerError,
|
|
36
|
+
ZuoraAPI::Exceptions::ZuoraUnexpectedError,
|
|
37
|
+
ZuoraAPI::Exceptions::ZuoraAPIUnkownError
|
|
38
|
+
].freeze
|
|
39
|
+
|
|
40
|
+
ZUORA_SERVER_ERRORS = [
|
|
41
|
+
ZuoraAPI::Exceptions::ZuoraAPIInternalServerError,
|
|
42
|
+
ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout,
|
|
43
|
+
ZuoraAPI::Exceptions::ZuoraAPIReadTimeout,
|
|
44
|
+
ZuoraAPI::Exceptions::ZuoraUnexpectedError
|
|
45
|
+
].freeze
|
|
15
46
|
|
|
16
47
|
attr_accessor :region, :url, :wsdl_number, :current_session, :bearer_token, :oauth_session_expires_at, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep, :hostname, :zconnect_provider
|
|
17
48
|
|
|
@@ -19,10 +50,10 @@ module ZuoraAPI
|
|
|
19
50
|
raise "URL is nil or empty, but URL is required" if url.nil? || url.empty?
|
|
20
51
|
# raise "URL is improper. URL must contain zuora.com, zuora.eu, or zuora.na" if /zuora.com|zuora.eu|zuora.na/ === url
|
|
21
52
|
self.hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil?
|
|
22
|
-
if !/apps\/services\/a\/\d
|
|
53
|
+
if !/apps\/services\/a\/\d+\.\d$/.match(url.strip)
|
|
23
54
|
self.url = "https://#{hostname}/apps/services/a/#{MIN_Endpoint}"
|
|
24
|
-
elsif MIN_Endpoint.to_f > url.scan(/(\d
|
|
25
|
-
self.url = url.gsub(/(\d
|
|
55
|
+
elsif MIN_Endpoint.to_f > url.scan(/(\d+\.\d)$/).dig(0,0).to_f
|
|
56
|
+
self.url = url.gsub(/(\d+\.\d)$/, MIN_Endpoint)
|
|
26
57
|
else
|
|
27
58
|
self.url = url
|
|
28
59
|
end
|
|
@@ -41,27 +72,12 @@ module ZuoraAPI
|
|
|
41
72
|
|
|
42
73
|
def get_identity(cookies)
|
|
43
74
|
zsession = cookies["ZSession"]
|
|
44
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
45
75
|
begin
|
|
46
76
|
if !zsession.blank?
|
|
47
77
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
48
78
|
output_json = JSON.parse(response.body)
|
|
49
|
-
elsif zconnect_accesstoken.present?
|
|
50
|
-
begin
|
|
51
|
-
code = zconnect_accesstoken.split("#!").last
|
|
52
|
-
encrypted_token, tenant_id = Base64.decode64(code).split(":")
|
|
53
|
-
body = {'token' => encrypted_token}.to_json
|
|
54
|
-
rescue => ex
|
|
55
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie")
|
|
56
|
-
end
|
|
57
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
|
|
58
|
-
output_json = JSON.parse(response.body)
|
|
59
79
|
else
|
|
60
|
-
|
|
61
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
62
|
-
else
|
|
63
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
64
|
-
end
|
|
80
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
65
81
|
end
|
|
66
82
|
rescue JSON::ParserError => ex
|
|
67
83
|
output_json = {}
|
|
@@ -72,20 +88,12 @@ module ZuoraAPI
|
|
|
72
88
|
|
|
73
89
|
def get_full_nav(cookies)
|
|
74
90
|
zsession = cookies["ZSession"]
|
|
75
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
76
91
|
begin
|
|
77
92
|
if zsession.present?
|
|
78
93
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
79
94
|
output_json = JSON.parse(response.body)
|
|
80
|
-
elsif zconnect_accesstoken.present?
|
|
81
|
-
response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
|
|
82
|
-
output_json = JSON.parse(response.body)
|
|
83
95
|
else
|
|
84
|
-
|
|
85
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
86
|
-
else
|
|
87
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
88
|
-
end
|
|
96
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
89
97
|
end
|
|
90
98
|
rescue JSON::ParserError => ex
|
|
91
99
|
output_json = {}
|
|
@@ -96,20 +104,12 @@ module ZuoraAPI
|
|
|
96
104
|
|
|
97
105
|
def set_nav(state, cookies)
|
|
98
106
|
zsession = cookies["ZSession"]
|
|
99
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
100
107
|
begin
|
|
101
108
|
if !zsession.blank?
|
|
102
109
|
response = HTTParty.put("https://#{self.hostname}/apps/v1/preference/navigation", :body => state.to_json, :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
103
110
|
output_json = JSON.parse(response.body)
|
|
104
|
-
elsif !zconnect_accesstoken.blank?
|
|
105
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/navigationstate", :body => state.to_json, :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
|
106
|
-
output_json = JSON.parse(response.body)
|
|
107
111
|
else
|
|
108
|
-
|
|
109
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
110
|
-
else
|
|
111
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
112
|
-
end
|
|
112
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
113
113
|
end
|
|
114
114
|
rescue JSON::ParserError => ex
|
|
115
115
|
output_json = {}
|
|
@@ -120,20 +120,12 @@ module ZuoraAPI
|
|
|
120
120
|
|
|
121
121
|
def refresh_nav(cookies)
|
|
122
122
|
zsession = cookies["ZSession"]
|
|
123
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
|
124
123
|
begin
|
|
125
124
|
if !zsession.blank?
|
|
126
125
|
response = HTTParty.post("https://#{self.hostname}/apps/v1/navigation/fetch", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
|
127
126
|
output_json = JSON.parse(response.body)
|
|
128
|
-
elsif !zconnect_accesstoken.blank?
|
|
129
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/refresh-navbarcache", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
|
130
|
-
output_json = JSON.parse(response.body)
|
|
131
127
|
else
|
|
132
|
-
|
|
133
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
|
134
|
-
else
|
|
135
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
136
|
-
end
|
|
128
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
|
137
129
|
end
|
|
138
130
|
rescue JSON::ParserError => ex
|
|
139
131
|
output_json = {}
|
|
@@ -142,27 +134,21 @@ module ZuoraAPI
|
|
|
142
134
|
return output_json
|
|
143
135
|
end
|
|
144
136
|
|
|
145
|
-
def get_zconnect_accesstoken(cookies)
|
|
146
|
-
accesstoken = nil
|
|
147
|
-
self.update_zconnect_provider
|
|
148
|
-
if !cookies[self.zconnect_provider].nil? && !cookies[self.zconnect_provider].empty?
|
|
149
|
-
accesstoken = cookies[self.zconnect_provider]
|
|
150
|
-
end
|
|
151
|
-
return accesstoken
|
|
152
|
-
end
|
|
153
|
-
|
|
154
137
|
def reporting_url(path)
|
|
155
138
|
map = {"US" => {"Sandbox" => "https://zconnectsandbox.zuora.com/api/rest/v1/",
|
|
156
139
|
"Production" => "https://zconnect.zuora.com/api/rest/v1/",
|
|
157
|
-
"
|
|
140
|
+
"Test" => "https://reporting-sbx.zan.0001.sbx.auw2.zuora.com/api/rest/v1/",
|
|
141
|
+
"Staging" => "https://reporting-stg11.zan.svc.auw2.zuora.com/api/rest/v1/",
|
|
142
|
+
"Performance" => "https://zconnectpt1.zuora.com/api/rest/v1/",
|
|
143
|
+
"Services" => "https://reporting-svc08.svc.auw2.zuora.com/api/rest/v1/"},
|
|
158
144
|
"EU" => {"Sandbox" => "https://zconnect.sandbox.eu.zuora.com/api/rest/v1/",
|
|
159
145
|
"Production" => "https://zconnect.eu.zuora.com/api/rest/v1/",
|
|
160
|
-
"Services"=> ""},
|
|
146
|
+
"Services"=> "https://reporting-sbx0000.sbx.aec1.zuora.com/api/rest/v1/"},
|
|
161
147
|
"NA" => {"Sandbox" => "https://zconnect.sandbox.na.zuora.com/api/rest/v1/",
|
|
162
148
|
"Production" => "https://zconnect.na.zuora.com/api/rest/v1/",
|
|
163
149
|
"Services"=> ""}
|
|
164
150
|
}
|
|
165
|
-
return map[
|
|
151
|
+
return map[self.region][self.environment].insert(-1, path)
|
|
166
152
|
end
|
|
167
153
|
|
|
168
154
|
# There are two ways to call this method. The first way is best.
|
|
@@ -212,7 +198,7 @@ module ZuoraAPI
|
|
|
212
198
|
end
|
|
213
199
|
|
|
214
200
|
def self.environments
|
|
215
|
-
%w(Sandbox Production Services Performance Staging)
|
|
201
|
+
%w(Sandbox Production Services Performance Staging Test)
|
|
216
202
|
end
|
|
217
203
|
|
|
218
204
|
def self.regions
|
|
@@ -224,11 +210,13 @@ module ZuoraAPI
|
|
|
224
210
|
"Production" => "https://www.zuora.com/apps/services/a/",
|
|
225
211
|
"Performance" => "https://pt1.zuora.com/apps/services/a/",
|
|
226
212
|
"Services" => "https://services347.zuora.com/apps/services/a/",
|
|
227
|
-
"Staging" => "https://staging2.zuora.com/apps/services/a/"
|
|
213
|
+
"Staging" => "https://staging2.zuora.com/apps/services/a/",
|
|
214
|
+
"Test" => "https://test.zuora.com/apps/services/a/"},
|
|
228
215
|
"EU" => {"Sandbox" => "https://sandbox.eu.zuora.com/apps/services/a/",
|
|
229
216
|
"Production" => "https://eu.zuora.com/apps/services/a/",
|
|
230
217
|
"Performance" => "https://pt1.eu.zuora.com/apps/services/a/",
|
|
231
|
-
"Services" => "https://services347.eu.zuora.com/apps/services/a/"
|
|
218
|
+
"Services" => "https://services347.eu.zuora.com/apps/services/a/",
|
|
219
|
+
"Test" => "https://test.eu.zuora.com/apps/services/a/"},
|
|
232
220
|
"NA" => {"Sandbox" => "https://sandbox.na.zuora.com/apps/services/a/",
|
|
233
221
|
"Production" => "https://na.zuora.com/apps/services/a/",
|
|
234
222
|
"Performance" => "https://pt1.na.zuora.com/apps/services/a/",
|
|
@@ -265,15 +253,18 @@ module ZuoraAPI
|
|
|
265
253
|
|
|
266
254
|
def update_environment
|
|
267
255
|
if !self.url.blank?
|
|
268
|
-
|
|
256
|
+
case self.hostname
|
|
257
|
+
when /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/
|
|
269
258
|
self.environment = 'Sandbox'
|
|
270
|
-
|
|
259
|
+
when /(?<=\.|\/|^)(service[\d]*|services[\d]*|ep-edge)(?=\.|\/|$)/
|
|
271
260
|
self.environment = 'Services'
|
|
272
|
-
|
|
261
|
+
when /(?<=\.|\/|-|^)(pt[\d]*)(?=\.|\/|-|$)/
|
|
273
262
|
self.environment = 'Performance'
|
|
274
|
-
|
|
263
|
+
when /(?<=\.|\/|^)(staging1|staging2|stg)(?=\.|\/|$)/
|
|
275
264
|
self.environment = 'Staging'
|
|
276
|
-
|
|
265
|
+
when /(?<=\.|\/|^)(test)(?=\.|\/|$)/
|
|
266
|
+
self.environment = 'Test'
|
|
267
|
+
when /(?<=\.|\/|^)(www|api)(?=\.|\/|$)/, /(^|tls10\.|origin-www\.|zforsf\.|eu\.|na\.)(zuora\.com)/
|
|
277
268
|
self.environment = 'Production'
|
|
278
269
|
else
|
|
279
270
|
self.environment = 'Unknown'
|
|
@@ -283,25 +274,14 @@ module ZuoraAPI
|
|
|
283
274
|
end
|
|
284
275
|
end
|
|
285
276
|
|
|
286
|
-
def is_prod_env
|
|
287
|
-
is_prod = false
|
|
288
|
-
www_or_api = /(?<=\.|\/|^)(www|api)(?=\.|\/|$)/ === self.hostname
|
|
289
|
-
host_prefix_match = /(^|tls10\.|origin-www\.|zforsf\.|eu\.|na\.)(zuora\.com)/ === self.hostname
|
|
290
|
-
if www_or_api || host_prefix_match
|
|
291
|
-
is_prod = true
|
|
292
|
-
end
|
|
293
|
-
return is_prod
|
|
294
|
-
end
|
|
295
|
-
|
|
296
277
|
def update_zconnect_provider
|
|
297
278
|
region = update_region
|
|
298
279
|
environment = update_environment
|
|
299
|
-
mappings = {"US" => {"Sandbox" => "ZConnectSbx",
|
|
300
|
-
"NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "
|
|
301
|
-
"EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "
|
|
280
|
+
mappings = {"US" => {"Sandbox" => "ZConnectSbx", "Services" => "ZConnectSvcUS", "Production" => "ZConnectProd", "Performance" => "ZConnectPT1", "Test" => "ZConnectTest", "Staging" => "ZConnectQA", "KubeSTG" => "ZConnectDev", "KubeDEV" => "ZConnectDev", "KubePROD" => "ZConnectDev"},
|
|
281
|
+
"NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "ZConnectSvcNA", "Production" => "ZConnectProdNA", "Performance" => "ZConnectPT1NA"},
|
|
282
|
+
"EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "ZConnectSvcEU", "Production" => "ZConnectProdEU", "Performance" => "ZConnectPT1EU", "Test" => "ZConnectTest"},
|
|
302
283
|
"Unknown" => {"Unknown" => "Unknown"}}
|
|
303
284
|
self.zconnect_provider = mappings[region][environment]
|
|
304
|
-
# raise "Can't find ZConnect Provider for #{region} region and #{environment} environment" if self.zconnect_provider.nil?
|
|
305
285
|
end
|
|
306
286
|
|
|
307
287
|
def aqua_endpoint(url="")
|
|
@@ -314,45 +294,35 @@ module ZuoraAPI
|
|
|
314
294
|
return "#{url_slash_apps_slash}api/#{url}"
|
|
315
295
|
end
|
|
316
296
|
|
|
317
|
-
def rest_endpoint(url="")
|
|
297
|
+
def rest_endpoint(url="", domain=true, prefix='/v1/')
|
|
318
298
|
update_environment
|
|
319
299
|
endpoint = url
|
|
320
|
-
|
|
300
|
+
url_postfix = {"US" => ".", "EU" => ".eu.", "NA" => ".na."}[self.region]
|
|
301
|
+
|
|
321
302
|
case self.environment
|
|
303
|
+
when 'Test'
|
|
304
|
+
endpoint = "https://rest.test#{url_postfix}zuora.com"
|
|
322
305
|
when 'Sandbox'
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
endpoint = "https://rest.apisandbox.zuora.com/v1/".concat(url)
|
|
326
|
-
when 'EU'
|
|
327
|
-
endpoint = "https://rest.sandbox.eu.zuora.com/v1/".concat(url)
|
|
328
|
-
when 'NA'
|
|
329
|
-
endpoint = "https://rest.sandbox.na.zuora.com/v1/".concat(url)
|
|
330
|
-
end
|
|
306
|
+
endpoint = "https://rest.sandbox#{url_postfix}zuora.com"
|
|
307
|
+
endpoint = "https://rest.apisandbox.zuora.com" if self.region == "US"
|
|
331
308
|
when 'Production'
|
|
332
|
-
|
|
333
|
-
when 'US'
|
|
334
|
-
endpoint = "https://rest.zuora.com/v1/".concat(url)
|
|
335
|
-
when 'EU'
|
|
336
|
-
endpoint = "https://rest.eu.zuora.com/v1/".concat(url)
|
|
337
|
-
when 'NA'
|
|
338
|
-
endpoint = "https://rest.na.zuora.com/v1/".concat(url)
|
|
339
|
-
end
|
|
309
|
+
endpoint = "https://rest#{url_postfix}zuora.com"
|
|
340
310
|
when 'Performance'
|
|
341
|
-
endpoint = "https://rest.pt1.zuora.com
|
|
311
|
+
endpoint = "https://rest.pt1.zuora.com"
|
|
342
312
|
when 'Services'
|
|
343
313
|
https = /https:\/\/|http:\/\//.match(self.url)[0]
|
|
344
314
|
host = self.hostname
|
|
345
|
-
endpoint = "#{https}#{host}
|
|
315
|
+
endpoint = "#{https}rest#{host}"
|
|
346
316
|
when 'Staging'
|
|
347
|
-
endpoint = "https://rest-staging2.zuora.com
|
|
317
|
+
endpoint = "https://rest-staging2.zuora.com"
|
|
348
318
|
when 'Unknown'
|
|
349
319
|
raise "Environment unknown, returning passed in parameter unaltered"
|
|
350
320
|
end
|
|
351
|
-
return endpoint
|
|
321
|
+
return domain ? endpoint.concat(prefix).concat(url) : prefix.concat(url)
|
|
352
322
|
end
|
|
353
323
|
|
|
354
324
|
def rest_domain
|
|
355
|
-
return URI(self.rest_endpoint).host
|
|
325
|
+
return URI(self.rest_endpoint).host
|
|
356
326
|
end
|
|
357
327
|
|
|
358
328
|
def fileURL(url="")
|
|
@@ -363,10 +333,10 @@ module ZuoraAPI
|
|
|
363
333
|
return self.wsdl_number > 68 ? '%Y-%m-%d' : '%Y-%m-%dT%H:%M:%S'
|
|
364
334
|
end
|
|
365
335
|
|
|
366
|
-
def new_session(auth_type: :basic, debug: false)
|
|
336
|
+
def new_session(auth_type: :basic, debug: false, zuora_track_id: nil)
|
|
367
337
|
end
|
|
368
338
|
|
|
369
|
-
def get_session(prefix: false, auth_type: :basic)
|
|
339
|
+
def get_session(prefix: false, auth_type: :basic, zuora_track_id: nil)
|
|
370
340
|
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}") if Rails.env.to_s == 'development'
|
|
371
341
|
case auth_type
|
|
372
342
|
when :basic
|
|
@@ -374,13 +344,13 @@ module ZuoraAPI
|
|
|
374
344
|
case self.class.to_s
|
|
375
345
|
when 'ZuoraAPI::Oauth'
|
|
376
346
|
if self.bearer_token.blank? || self.oauth_expired?
|
|
377
|
-
self.new_session(auth_type: :bearer)
|
|
347
|
+
self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id)
|
|
378
348
|
end
|
|
379
|
-
self.get_z_session if self.status == 'Active'
|
|
349
|
+
self.get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
|
|
380
350
|
when 'ZuoraAPI::Basic'
|
|
381
|
-
self.new_session(auth_type: :basic)
|
|
351
|
+
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
382
352
|
else
|
|
383
|
-
|
|
353
|
+
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
384
354
|
end
|
|
385
355
|
end
|
|
386
356
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
|
@@ -389,17 +359,33 @@ module ZuoraAPI
|
|
|
389
359
|
case self.class.to_s
|
|
390
360
|
when 'ZuoraAPI::Oauth'
|
|
391
361
|
if self.bearer_token.blank? || self.oauth_expired?
|
|
392
|
-
self.new_session(auth_type: :bearer)
|
|
362
|
+
self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id)
|
|
393
363
|
end
|
|
394
364
|
when 'ZuoraAPI::Basic'
|
|
395
365
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}")
|
|
366
|
+
else
|
|
367
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Unknown Login, does not support Authentication of Type: #{auth_type}")
|
|
396
368
|
end
|
|
369
|
+
|
|
397
370
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
|
398
371
|
return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
|
|
399
372
|
end
|
|
400
373
|
end
|
|
401
374
|
|
|
402
|
-
def soap_call(
|
|
375
|
+
def soap_call(
|
|
376
|
+
ns1: 'ns1',
|
|
377
|
+
ns2: 'ns2',
|
|
378
|
+
batch_size: nil,
|
|
379
|
+
single_transaction: false,
|
|
380
|
+
debug: false,
|
|
381
|
+
zuora_track_id: nil,
|
|
382
|
+
errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS),
|
|
383
|
+
z_session: true,
|
|
384
|
+
timeout_retry: false,
|
|
385
|
+
timeout: 120,
|
|
386
|
+
timeout_sleep_interval: self.timeout_sleep,
|
|
387
|
+
output_exception_messages: true,
|
|
388
|
+
**keyword_args)
|
|
403
389
|
tries ||= 2
|
|
404
390
|
xml = Nokogiri::XML::Builder.new do |xml|
|
|
405
391
|
xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/",
|
|
@@ -409,7 +395,7 @@ module ZuoraAPI
|
|
|
409
395
|
"xmlns:#{ns1}" => "http://api.zuora.com/") do
|
|
410
396
|
xml['SOAP-ENV'].Header do
|
|
411
397
|
xml["#{ns1}"].SessionHeader do
|
|
412
|
-
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic)
|
|
398
|
+
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
413
399
|
end
|
|
414
400
|
if single_transaction
|
|
415
401
|
xml["#{ns1}"].CallOptions do
|
|
@@ -432,15 +418,34 @@ module ZuoraAPI
|
|
|
432
418
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
|
433
419
|
Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
434
420
|
|
|
435
|
-
|
|
421
|
+
headers = { 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'}
|
|
422
|
+
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
423
|
+
|
|
424
|
+
request = HTTParty::Request.new(
|
|
425
|
+
Net::HTTP::Post,
|
|
426
|
+
self.url,
|
|
427
|
+
body: xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip,
|
|
428
|
+
headers: headers,
|
|
429
|
+
timeout: timeout,
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
response = request.perform
|
|
433
|
+
|
|
436
434
|
output_xml = Nokogiri::XML(response.body)
|
|
437
435
|
Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
|
438
436
|
|
|
439
437
|
raise_errors(type: :SOAP, body: output_xml, response: response)
|
|
440
438
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
441
|
-
if !
|
|
439
|
+
if !tries.zero? && z_session
|
|
440
|
+
tries -= 1
|
|
442
441
|
Rails.logger.debug("SOAP Call - Session Invalid")
|
|
443
|
-
|
|
442
|
+
|
|
443
|
+
begin
|
|
444
|
+
self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id)
|
|
445
|
+
rescue *ZUORA_API_ERRORS => ex
|
|
446
|
+
return output_xml, input_xml, ex.response
|
|
447
|
+
end
|
|
448
|
+
|
|
444
449
|
retry
|
|
445
450
|
else
|
|
446
451
|
if errors.include?(ex.class)
|
|
@@ -453,30 +458,45 @@ module ZuoraAPI
|
|
|
453
458
|
if errors.include?(ex.class)
|
|
454
459
|
raise ex
|
|
455
460
|
else
|
|
461
|
+
response = ex.response unless response
|
|
456
462
|
return output_xml, input_xml, response
|
|
457
463
|
end
|
|
458
464
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
459
|
-
if
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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
|
|
465
474
|
end
|
|
475
|
+
|
|
476
|
+
tries -= 1
|
|
477
|
+
sleep(timeout_sleep_interval)
|
|
478
|
+
retry
|
|
466
479
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
467
|
-
if !
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
480
|
+
if !tries.zero?
|
|
481
|
+
tries -= 1
|
|
482
|
+
|
|
483
|
+
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
484
|
+
retry
|
|
485
|
+
elsif timeout_retry
|
|
486
|
+
sleep(timeout_sleep_interval)
|
|
487
|
+
retry
|
|
488
|
+
end
|
|
473
489
|
end
|
|
474
|
-
|
|
475
|
-
if
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
490
|
+
|
|
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
|
|
479
497
|
end
|
|
498
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
499
|
+
raise ex
|
|
480
500
|
rescue => ex
|
|
481
501
|
raise ex
|
|
482
502
|
else
|
|
@@ -484,31 +504,60 @@ module ZuoraAPI
|
|
|
484
504
|
end
|
|
485
505
|
|
|
486
506
|
def raise_errors(type: :SOAP, body: nil, response: nil)
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
507
|
+
request_uri, request_path, match_string = "", "", ""
|
|
508
|
+
if response.class.to_s == "HTTP::Message"
|
|
509
|
+
request_uri = response.http_header.request_uri.to_s
|
|
510
|
+
request_path = response.http_header.request_uri.path
|
|
511
|
+
match_string = "#{response.http_header.request_method}::#{response.code}::#{request_uri}"
|
|
512
|
+
else
|
|
513
|
+
request = response.request
|
|
514
|
+
request_uri = response.request.uri
|
|
515
|
+
request_path = request.path.path
|
|
516
|
+
match_string = "#{request.http_method.to_s.split("Net::HTTP::").last.upcase}::#{response.code}::#{request_path}"
|
|
517
|
+
end
|
|
491
518
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
end
|
|
519
|
+
if [502,503].include?(response.code)
|
|
520
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from #{request_uri}", response)
|
|
521
|
+
end
|
|
496
522
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
523
|
+
# Check failure response code
|
|
524
|
+
case response.code
|
|
525
|
+
when 504
|
|
526
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from #{request_uri}", response)
|
|
527
|
+
when 429
|
|
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)
|
|
529
|
+
when 401
|
|
530
|
+
|
|
531
|
+
else
|
|
532
|
+
if body.class == Hash
|
|
533
|
+
case request_path
|
|
534
|
+
when /^\/v1\/connections$/
|
|
535
|
+
response_headers = response.headers.to_h
|
|
536
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing cookies for authentication call", response) if response_headers['set-cookie'].blank?
|
|
537
|
+
z_session_cookie = response_headers.fetch('set-cookie', []).select{|x| x.match(/^ZSession=.*/) }.first
|
|
538
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing ZSession cookie for authentication call", response) if z_session_cookie.blank?
|
|
539
|
+
end
|
|
500
540
|
end
|
|
541
|
+
end
|
|
501
542
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
543
|
+
case type
|
|
544
|
+
when :SOAP
|
|
545
|
+
error, success, message = get_soap_error_and_message(body)
|
|
546
|
+
|
|
547
|
+
if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? &&
|
|
548
|
+
body.xpath(
|
|
549
|
+
'//ns1:records[@xsi:type="ns2:Export"]',
|
|
550
|
+
'ns1' => 'http://api.zuora.com/', 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
|
|
551
|
+
).present?
|
|
552
|
+
result = body.xpath('//ns2:Status', 'ns2' => 'http://object.api.zuora.com/').text
|
|
553
|
+
if result == 'Failed'
|
|
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'
|
|
510
558
|
else
|
|
511
|
-
|
|
559
|
+
error = 'FATAL_ERROR'
|
|
560
|
+
message = 'Export failed due to unknown reason. Consult api logs.'
|
|
512
561
|
end
|
|
513
562
|
end
|
|
514
563
|
end
|
|
@@ -516,44 +565,48 @@ module ZuoraAPI
|
|
|
516
565
|
#By default response if not passed in for SOAP as all SOAP is 200
|
|
517
566
|
if error.present?
|
|
518
567
|
if error.class == String
|
|
519
|
-
|
|
520
|
-
when "INVALID_SESSION"
|
|
521
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{error}::#{message}", response)
|
|
522
|
-
when "REQUEST_EXCEEDED_LIMIT"
|
|
523
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{error}::#{message}", response)
|
|
524
|
-
when "LOCK_COMPETITION"
|
|
525
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
|
|
526
|
-
when "BATCH_FAIL_ERROR"
|
|
527
|
-
if message.include?("optimistic locking failed")
|
|
528
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
|
|
529
|
-
else
|
|
530
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
|
|
531
|
-
end
|
|
532
|
-
when "TEMPORARY_ERROR"
|
|
533
|
-
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{error}::#{message}", response)
|
|
534
|
-
when "INVALID_VALUE"
|
|
535
|
-
if message.include?("data integrity violation")
|
|
536
|
-
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
|
|
537
|
-
else
|
|
538
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
|
|
539
|
-
end
|
|
540
|
-
else
|
|
541
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response) if error.present?
|
|
542
|
-
end
|
|
568
|
+
raise_errors_helper(error: error, message: message, response: response)
|
|
543
569
|
elsif error.class == Array
|
|
544
|
-
if error
|
|
545
|
-
|
|
570
|
+
if error.uniq.size == 1
|
|
571
|
+
err, msg = error[0].split('::')
|
|
572
|
+
raise_errors_helper(error: err, message: msg, response: response, errors: error, success: success)
|
|
546
573
|
else
|
|
547
574
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), response, error, success)
|
|
548
575
|
end
|
|
549
576
|
end
|
|
550
577
|
end
|
|
578
|
+
|
|
579
|
+
self.errors_via_content_type(response: response, type: :xml)
|
|
551
580
|
|
|
552
|
-
|
|
553
|
-
|
|
581
|
+
when :JSON
|
|
582
|
+
case request_path
|
|
583
|
+
when /^\/query\/jobs.*/ #DataQuery Paths
|
|
584
|
+
return if body.class != Hash
|
|
585
|
+
case match_string
|
|
586
|
+
when /^GET::200::\/query\/jobs\/([a-zA-Z0-9\-_]+)$/ #Get DQ job, Capture of the id is present if needed in future error responses.
|
|
587
|
+
if body.dig('data', "errorCode") == "LINK_10000005"
|
|
588
|
+
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body.dig('data', "errorMessage"), response)
|
|
589
|
+
elsif (body.dig('data', "errorMessage").present? || body.dig('data', "queryStatus") == "failed")
|
|
590
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('data', "errorMessage"), response)
|
|
591
|
+
end
|
|
592
|
+
when /^GET::404::\/query\/jobs\/([a-zA-Z0-9\-_]+)$/ #Get DQ job not found, capture of the id is present if needed in future error responses.
|
|
593
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('message'), response) if body.dig('message').present?
|
|
594
|
+
when /^POST::400::\/query\/jobs$/ #Create DQ job
|
|
595
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('message'), response) if body.dig('message').present?
|
|
596
|
+
end
|
|
597
|
+
when /^\/api\/rest\/v1\/reports.*/ #Reporting Paths
|
|
598
|
+
reporting_message = response.parsed_response.dig("ZanResponse", "response", "message") || body.dig("message")
|
|
599
|
+
if reporting_message&.include?("com.zuora.rest.RestUsageException: The user does not have permissions for this API.")
|
|
600
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response)
|
|
601
|
+
elsif reporting_message&.include?("500 Internal Server Error")
|
|
602
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Internal Server Error. The Reporting API is down. Contact Support.", response)
|
|
603
|
+
end
|
|
604
|
+
case match_string
|
|
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.
|
|
606
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(reporting_message, response) if reporting_message.present?
|
|
607
|
+
end
|
|
554
608
|
end
|
|
555
609
|
|
|
556
|
-
when :JSON
|
|
557
610
|
body = body.dig("results").present? ? body["results"] : body if body.class == Hash
|
|
558
611
|
if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
|
|
559
612
|
messages_array = body.fetch("reasons", []).map {|error| error['message']}.compact
|
|
@@ -561,6 +614,14 @@ module ZuoraAPI
|
|
|
561
614
|
codes_array = body.fetch("reasons", []).map {|error| error['code']}.compact
|
|
562
615
|
codes_array = codes_array.push(body.dig("error", 'code')).compact if body.dig('error').class == Hash
|
|
563
616
|
|
|
617
|
+
if body['message'] == 'request exceeded limit'
|
|
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)
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
if (body.dig('message') || '').downcase.include?('unexpected error') && response.code != 500
|
|
622
|
+
raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(body['message'], response)
|
|
623
|
+
end
|
|
624
|
+
|
|
564
625
|
if body['message'] == "No bearer token" && response.code == 400
|
|
565
626
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Authentication type is not supported by this Login", response)
|
|
566
627
|
end
|
|
@@ -574,8 +635,12 @@ module ZuoraAPI
|
|
|
574
635
|
end
|
|
575
636
|
|
|
576
637
|
#Oauth Tokens - User deactivated
|
|
577
|
-
if body['
|
|
578
|
-
|
|
638
|
+
if body['path'] == '/oauth/token'
|
|
639
|
+
if body['status'] == 403 && response.code == 403
|
|
640
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Forbidden", response)
|
|
641
|
+
elsif body['status'] == 400 && response.code == 400 && body['message'].include?("Invalid client id")
|
|
642
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Invalid Oauth Client Id", response)
|
|
643
|
+
end
|
|
579
644
|
end
|
|
580
645
|
|
|
581
646
|
if body['error'] == 'Unauthorized' && body['status'] == 401
|
|
@@ -583,7 +648,12 @@ module ZuoraAPI
|
|
|
583
648
|
end
|
|
584
649
|
#Authentication failed
|
|
585
650
|
if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
|
|
586
|
-
|
|
651
|
+
new_message = messages_array.join(', ')
|
|
652
|
+
if new_message.present?
|
|
653
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(new_message, response)
|
|
654
|
+
else
|
|
655
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(body['message'], response)
|
|
656
|
+
end
|
|
587
657
|
end
|
|
588
658
|
|
|
589
659
|
#Zuora REST Create Amendment error #Authentication failed
|
|
@@ -591,16 +661,30 @@ module ZuoraAPI
|
|
|
591
661
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body['faultstring']}", response)
|
|
592
662
|
end
|
|
593
663
|
|
|
664
|
+
#Locking contention
|
|
665
|
+
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
|
|
666
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
|
|
667
|
+
end
|
|
668
|
+
#Internal Server Error
|
|
669
|
+
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(60)
|
|
670
|
+
if messages_array.uniq.size == 1
|
|
671
|
+
if messages_array.first.match(/^Transaction declined.*|^There is an invoice pending tax.*|^The Zuora GetTax call to Avalara.*|^The tax calculation call to Zuora Connect returned the following error: Status Code: 4.*/)
|
|
672
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(messages_array.first, response)
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("#{messages_array.join(', ')}", response)
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
#Retryiable Service Error
|
|
679
|
+
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(61)
|
|
680
|
+
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{messages_array.join(', ')}", response)
|
|
681
|
+
end
|
|
682
|
+
|
|
594
683
|
#Request exceeded limit
|
|
595
684
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70)
|
|
596
685
|
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", response)
|
|
597
686
|
end
|
|
598
687
|
|
|
599
|
-
#Locking contention
|
|
600
|
-
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
|
|
601
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
|
|
602
|
-
end
|
|
603
|
-
|
|
604
688
|
#All Errors catch
|
|
605
689
|
if codes_array.size > 0
|
|
606
690
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages_array.join(', ')}", response)
|
|
@@ -608,26 +692,20 @@ module ZuoraAPI
|
|
|
608
692
|
|
|
609
693
|
#Zuora REST Query Errors
|
|
610
694
|
if body["faultcode"].present?
|
|
611
|
-
|
|
612
|
-
when "fns:MALFORMED_QUERY"
|
|
613
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
|
614
|
-
when "fns:REQUEST_EXCEEDED_LIMIT"
|
|
615
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
|
616
|
-
when "fns:LOCK_COMPETITION"
|
|
617
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
|
618
|
-
when "INVALID_SESSION"
|
|
619
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
|
620
|
-
else
|
|
621
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
|
622
|
-
end
|
|
695
|
+
raise_errors_helper(error: body["faultcode"], message: body["faultstring"], response: response)
|
|
623
696
|
end
|
|
624
697
|
|
|
625
698
|
if body["Errors"].present? || body["errors"].present?
|
|
626
|
-
|
|
627
|
-
(
|
|
628
|
-
(
|
|
629
|
-
|
|
630
|
-
|
|
699
|
+
codes, messages = [[],[]]
|
|
700
|
+
body.fetch("Errors", []).each { |obj| messages.push(obj["Message"]); messages.push(obj["title"]); codes.push(obj["Code"]); codes.push(obj["code"]) }
|
|
701
|
+
body.fetch("errors", []).each { |obj| messages.push(obj["Message"]); messages.push(obj["title"]); codes.push(obj["Code"]); codes.push(obj["code"]) }
|
|
702
|
+
codes, messages = [codes.uniq.compact, messages.uniq.compact]
|
|
703
|
+
if codes.size > 0
|
|
704
|
+
if codes.size == 1
|
|
705
|
+
raise_errors_helper(error: codes.first, message: messages.first, response: response, errors: messages)
|
|
706
|
+
else
|
|
707
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages.join(", ")}", response, messages)
|
|
708
|
+
end
|
|
631
709
|
end
|
|
632
710
|
end
|
|
633
711
|
end
|
|
@@ -645,7 +723,7 @@ module ZuoraAPI
|
|
|
645
723
|
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", response)
|
|
646
724
|
elsif error_messages.first.include?("data integrity violation")
|
|
647
725
|
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
|
|
648
|
-
end
|
|
726
|
+
end
|
|
649
727
|
end
|
|
650
728
|
end
|
|
651
729
|
|
|
@@ -654,15 +732,128 @@ module ZuoraAPI
|
|
|
654
732
|
end
|
|
655
733
|
end
|
|
656
734
|
|
|
735
|
+
if body.class == Hash && body['message'].present?
|
|
736
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(body['message'], response) if response.code == 500
|
|
737
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['message'], response) if ![200,201].include?(response.code)
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
self.errors_via_content_type(response: response, type: :json)
|
|
741
|
+
|
|
657
742
|
#All other errors
|
|
658
|
-
if ![200,201].include?(response.code)
|
|
659
|
-
|
|
660
|
-
|
|
743
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(response.body, response) if ![200,201].include?(response.code)
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
def errors_via_content_type(response: nil, type: :xml)
|
|
748
|
+
response_content_types = response.headers.transform_keys(&:downcase).fetch('content-type', []).first || ""
|
|
749
|
+
|
|
750
|
+
if response_content_types.include?('application/json') && type != :json
|
|
751
|
+
output_json = JSON.parse(response.body)
|
|
752
|
+
self.raise_errors(type: :JSON, body: output_json, response: response)
|
|
753
|
+
|
|
754
|
+
elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml')) and type != :xml
|
|
755
|
+
output_xml = Nokogiri::XML(response.body)
|
|
756
|
+
self.raise_errors(type: :SOAP, body: output_xml, response: response)
|
|
757
|
+
|
|
758
|
+
elsif response_content_types.include?('text/html')
|
|
759
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Akamai Error", response) if response.headers.fetch('server', '') == 'AkamaiGHost'
|
|
760
|
+
|
|
761
|
+
parse_body = Nokogiri::HTML(response.body)
|
|
762
|
+
error_title = parse_body.xpath('//h2').text
|
|
763
|
+
error_title = parse_body.xpath('//h1').text if error_title.blank?
|
|
764
|
+
error_message = parse_body.xpath('//p').text
|
|
765
|
+
|
|
766
|
+
error_message = error_title if error_message.blank?
|
|
767
|
+
|
|
768
|
+
if error_title.present?
|
|
769
|
+
case error_title
|
|
770
|
+
when /Service Unavailable/
|
|
771
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(error_message, response)
|
|
772
|
+
when /Client sent a bad request./, /Bad Request/, /403 Forbidden/
|
|
773
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
774
|
+
else
|
|
775
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(error_message, response)
|
|
776
|
+
end
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Http response body is missing", response) if response.body.blank?
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(response.body, response) if response.code == 500
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
def get_soap_error_and_message(body)
|
|
787
|
+
error = body.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text
|
|
788
|
+
message = body.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
|
789
|
+
|
|
790
|
+
if error.blank? || message.blank?
|
|
791
|
+
error = body.xpath('//faultcode').text
|
|
792
|
+
message = body.xpath('//faultstring').text
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
if error.blank? || message.blank?
|
|
796
|
+
error = body.xpath('//ns1:Code', 'ns1' =>'http://api.zuora.com/').text
|
|
797
|
+
message = body.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
#Update/Create/Delete Calls with multiple requests and responses
|
|
801
|
+
if body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').size > 0 && body.xpath('//ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
|
|
802
|
+
error = []
|
|
803
|
+
success = []
|
|
804
|
+
body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').each_with_index do |call, object_index|
|
|
805
|
+
if call.xpath('./ns1:Success', 'ns1' =>'http://api.zuora.com/').text == 'false' && call.xpath('./ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0
|
|
806
|
+
message = "#{call.xpath('./*/ns1:Code', 'ns1' =>'http://api.zuora.com/').text}::#{call.xpath('./*/ns1:Message', 'ns1' =>'http://api.zuora.com/').text}"
|
|
807
|
+
error.push(message)
|
|
661
808
|
else
|
|
662
|
-
|
|
809
|
+
success.push(call.xpath('./ns1:Id', 'ns1' =>'http://api.zuora.com/').text)
|
|
663
810
|
end
|
|
664
811
|
end
|
|
665
812
|
end
|
|
813
|
+
return error, success, message
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
def raise_errors_helper(error: nil, message: nil, response: nil, errors: [], success: [])
|
|
817
|
+
case error
|
|
818
|
+
when /.*INVALID_SESSION/
|
|
819
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response, errors, success)
|
|
820
|
+
when /.*REQUEST_EXCEEDED_LIMIT/
|
|
821
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new(message, response, errors, success)
|
|
822
|
+
when /.*LOCK_COMPETITION/
|
|
823
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(message, response, errors, success)
|
|
824
|
+
when /.*BATCH_FAIL_ERROR/
|
|
825
|
+
if message.include?("optimistic locking failed") || message.include?("Operation failed due to a lock competition, please retry later.")
|
|
826
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(message, response, errors, success)
|
|
827
|
+
elsif message.include?("org.hibernate.exception.ConstraintViolationException")
|
|
828
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
|
|
829
|
+
end
|
|
830
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
831
|
+
when /.*TEMPORARY_ERROR/, /.*TRANSACTION_TIMEOUT/
|
|
832
|
+
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(message, response, errors, success)
|
|
833
|
+
when /.*INVALID_VALUE/
|
|
834
|
+
if message.include?("data integrity violation")
|
|
835
|
+
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response, errors), success
|
|
836
|
+
end
|
|
837
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
838
|
+
when /.*UNKNOWN_ERROR/
|
|
839
|
+
if /payment\/refund|Credit Balance Adjustment|Payment Gateway|ARSettlement permission/.match(message).nil?
|
|
840
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
|
|
841
|
+
end
|
|
842
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
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/
|
|
844
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
845
|
+
when /.*UNEXPECTED_ERROR/
|
|
846
|
+
raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(message, response, errors, success)
|
|
847
|
+
when /.*soapenv:Server.*/
|
|
848
|
+
if /^Invalid value.*for type.*|^Id is invalid|^date string can not be less than 19 charactors$/.match(message).present?
|
|
849
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(message, response, errors, success)
|
|
850
|
+
elsif /^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match(message).present?
|
|
851
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(message, response, errors, success)
|
|
852
|
+
end
|
|
853
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(message, response, errors, success)
|
|
854
|
+
else
|
|
855
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Z:#{error}::#{message}", response, errors, success)
|
|
856
|
+
end
|
|
666
857
|
end
|
|
667
858
|
|
|
668
859
|
def aqua_query(queryName: '', query: '', version: '1.2', jobName: 'Aqua',partner: '', project: '')
|
|
@@ -742,16 +933,24 @@ module ZuoraAPI
|
|
|
742
933
|
end
|
|
743
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
|
|
744
935
|
end
|
|
745
|
-
rescue *(CONNECTION_EXCEPTIONS
|
|
746
|
-
if
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
936
|
+
rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
|
|
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
|
|
752
946
|
end
|
|
947
|
+
|
|
948
|
+
tries -= 1
|
|
949
|
+
sleep(self.timeout_sleep)
|
|
950
|
+
retry
|
|
753
951
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
754
|
-
if !
|
|
952
|
+
if !tries.zero? && self.status == 'Active'
|
|
953
|
+
tries -= 1
|
|
755
954
|
Rails.logger.debug("Describe session expired. Starting new session.")
|
|
756
955
|
self.new_session
|
|
757
956
|
retry
|
|
@@ -776,50 +975,73 @@ module ZuoraAPI
|
|
|
776
975
|
session_type: :basic,
|
|
777
976
|
timeout_retry: false,
|
|
778
977
|
timeout: 120,
|
|
978
|
+
timeout_sleep_interval: self.timeout_sleep,
|
|
779
979
|
multipart: false,
|
|
780
|
-
|
|
980
|
+
stream_body: false,
|
|
981
|
+
output_exception_messages: true,
|
|
982
|
+
**keyword_args,
|
|
983
|
+
&block
|
|
781
984
|
)
|
|
782
985
|
tries ||= 2
|
|
783
986
|
|
|
784
|
-
if self.entity_id.present?
|
|
785
|
-
headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
|
786
|
-
headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
|
787
|
-
end
|
|
788
|
-
|
|
789
987
|
raise "Method not supported, supported methods include: :get, :post, :put, :delete, :patch, :head, :options" if ![:get, :post, :put, :delete, :patch, :head, :options].include?(method)
|
|
790
988
|
|
|
791
|
-
authentication_headers =
|
|
792
|
-
|
|
989
|
+
authentication_headers = {}
|
|
990
|
+
if z_session
|
|
991
|
+
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type) }
|
|
992
|
+
if self.entity_id.present?
|
|
993
|
+
authentication_headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
|
994
|
+
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
|
995
|
+
end
|
|
996
|
+
end
|
|
793
997
|
|
|
794
|
-
|
|
795
|
-
"Net::HTTP::#{method.to_s.capitalize}".constantize,
|
|
796
|
-
url,
|
|
797
|
-
body: body,
|
|
798
|
-
headers: modified_headers,
|
|
799
|
-
timeout: timeout,
|
|
800
|
-
multipart: multipart,
|
|
801
|
-
).perform
|
|
998
|
+
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
|
802
999
|
|
|
803
|
-
Rails.logger.debug("Response Code: #{response.code}") if debug
|
|
804
1000
|
begin
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
1001
|
+
request = HTTParty::Request.new(
|
|
1002
|
+
"Net::HTTP::#{method.to_s.capitalize}".constantize,
|
|
1003
|
+
url,
|
|
1004
|
+
body: body,
|
|
1005
|
+
headers: modified_headers,
|
|
1006
|
+
timeout: timeout,
|
|
1007
|
+
multipart: multipart,
|
|
1008
|
+
stream_body: stream_body
|
|
1009
|
+
)
|
|
1010
|
+
|
|
1011
|
+
response = request.perform(&block)
|
|
1012
|
+
|
|
1013
|
+
Rails.logger.debug("Response Code: #{response.code}") if debug
|
|
1014
|
+
begin
|
|
1015
|
+
output_json = JSON.parse(response.body)
|
|
1016
|
+
rescue JSON::ParserError => ex
|
|
1017
|
+
output_json = {}
|
|
1018
|
+
end
|
|
1019
|
+
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
|
810
1020
|
|
|
811
|
-
|
|
1021
|
+
raise_errors(type: :JSON, body: output_json, response: response)
|
|
1022
|
+
rescue
|
|
1023
|
+
reset_files(body) if multipart
|
|
1024
|
+
raise
|
|
1025
|
+
end
|
|
812
1026
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
|
813
1027
|
if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
|
|
814
|
-
|
|
1028
|
+
session_type = :bearer
|
|
1029
|
+
retry
|
|
815
1030
|
else
|
|
816
1031
|
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
|
817
1032
|
raise ex
|
|
818
1033
|
end
|
|
819
1034
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
|
820
|
-
if !
|
|
1035
|
+
if !tries.zero? && z_session
|
|
1036
|
+
tries -= 1
|
|
821
1037
|
Rails.logger.debug("Rest Call - Session Invalid #{session_type}")
|
|
822
|
-
|
|
1038
|
+
|
|
1039
|
+
begin
|
|
1040
|
+
self.new_session(auth_type: session_type)
|
|
1041
|
+
rescue *ZUORA_API_ERRORS => ex
|
|
1042
|
+
return [output_json, ex.response]
|
|
1043
|
+
end
|
|
1044
|
+
|
|
823
1045
|
retry
|
|
824
1046
|
else
|
|
825
1047
|
if errors.include?(ex.class)
|
|
@@ -832,32 +1054,46 @@ module ZuoraAPI
|
|
|
832
1054
|
if errors.include?(ex.class)
|
|
833
1055
|
raise ex
|
|
834
1056
|
else
|
|
1057
|
+
response = ex.response unless response
|
|
835
1058
|
return [output_json, response]
|
|
836
1059
|
end
|
|
837
1060
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
|
838
1061
|
raise ex
|
|
839
1062
|
rescue *CONNECTION_EXCEPTIONS => ex
|
|
840
|
-
if
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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
|
|
846
1072
|
end
|
|
1073
|
+
|
|
1074
|
+
tries -= 1
|
|
1075
|
+
sleep(timeout_sleep_interval)
|
|
1076
|
+
retry
|
|
847
1077
|
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
|
848
|
-
if !
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
1078
|
+
if !tries.zero?
|
|
1079
|
+
tries -= 1
|
|
1080
|
+
if ex.is_a?(Errno::ECONNRESET) && ex.message.include?('SSL_connect')
|
|
1081
|
+
retry
|
|
1082
|
+
elsif timeout_retry
|
|
1083
|
+
sleep(timeout_sleep_interval)
|
|
1084
|
+
retry
|
|
1085
|
+
end
|
|
854
1086
|
end
|
|
855
|
-
|
|
856
|
-
if
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
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
|
|
860
1094
|
end
|
|
1095
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read timeout from #{url}", nil, request) if ex.instance_of?(Net::ReadTimeout)
|
|
1096
|
+
raise ex
|
|
861
1097
|
rescue => ex
|
|
862
1098
|
raise ex
|
|
863
1099
|
else
|
|
@@ -910,9 +1146,11 @@ module ZuoraAPI
|
|
|
910
1146
|
return products, catalog_map
|
|
911
1147
|
end
|
|
912
1148
|
|
|
913
|
-
def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: 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)
|
|
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)
|
|
914
1150
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
|
915
1151
|
|
|
1152
|
+
retry_count ||= timeout_retries
|
|
1153
|
+
|
|
916
1154
|
#Make sure directory exists
|
|
917
1155
|
require 'fileutils'
|
|
918
1156
|
FileUtils.mkdir_p(file_path) unless File.exists?(file_path)
|
|
@@ -927,8 +1165,9 @@ module ZuoraAPI
|
|
|
927
1165
|
headers = headers.merge({"Zuora-Entity-Ids" => self.entity_id}) if !self.entity_id.blank?
|
|
928
1166
|
end
|
|
929
1167
|
|
|
1168
|
+
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
|
1169
|
+
|
|
930
1170
|
response_save = nil
|
|
931
|
-
retry_count ||= timeout_retries
|
|
932
1171
|
http.request_get(uri.request_uri, headers) do |response|
|
|
933
1172
|
response_save = response
|
|
934
1173
|
status_code = response.code if response
|
|
@@ -1022,11 +1261,11 @@ module ZuoraAPI
|
|
|
1022
1261
|
raise
|
|
1023
1262
|
end
|
|
1024
1263
|
else
|
|
1025
|
-
raise
|
|
1264
|
+
raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}")
|
|
1026
1265
|
end
|
|
1027
1266
|
end
|
|
1028
|
-
|
|
1029
|
-
rescue => ex
|
|
1267
|
+
|
|
1268
|
+
rescue => ex
|
|
1030
1269
|
sleep(5)
|
|
1031
1270
|
if (retry_count -= 1) >= 0
|
|
1032
1271
|
retry
|
|
@@ -1036,75 +1275,122 @@ module ZuoraAPI
|
|
|
1036
1275
|
end
|
|
1037
1276
|
end
|
|
1038
1277
|
|
|
1039
|
-
def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1278
|
+
def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
|
|
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
|
|
1045
1287
|
end
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
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
|
|
1055
1297
|
end
|
|
1056
1298
|
end
|
|
1057
1299
|
end
|
|
1058
1300
|
end
|
|
1059
|
-
end
|
|
1060
1301
|
|
|
1061
|
-
|
|
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)
|
|
1062
1303
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
|
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"
|
|
1066
1306
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
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
|
|
1072
1317
|
end
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
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
|
|
1077
1322
|
end
|
|
1078
1323
|
end
|
|
1079
1324
|
end
|
|
1080
|
-
|
|
1081
|
-
result = 'Waiting'
|
|
1325
|
+
result = 'Waiting'
|
|
1082
1326
|
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
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)
|
|
1086
1330
|
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
raise "Export Creation Unsuccessful : #{output_xml.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text}" if result.blank? || result == "Failed"
|
|
1091
|
-
end
|
|
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
|
|
1092
1334
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
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
|
|
1108
1394
|
end
|
|
1109
1395
|
end
|
|
1110
1396
|
|
|
@@ -1171,5 +1457,17 @@ module ZuoraAPI
|
|
|
1171
1457
|
end
|
|
1172
1458
|
return "failure"
|
|
1173
1459
|
end
|
|
1460
|
+
|
|
1461
|
+
def reset_files(body)
|
|
1462
|
+
return unless body.is_a? Hash
|
|
1463
|
+
|
|
1464
|
+
body.transform_values! do |v|
|
|
1465
|
+
if v.is_a?(File)
|
|
1466
|
+
v.reopen(v.path)
|
|
1467
|
+
else
|
|
1468
|
+
v
|
|
1469
|
+
end
|
|
1470
|
+
end
|
|
1471
|
+
end
|
|
1174
1472
|
end
|
|
1175
1473
|
end
|