zuora_api 1.6.54 → 1.6.251
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitlab-ci.yml +3 -16
- data/CHANGELOG.md +8 -13
- data/lib/zuora_api/exceptions.rb +14 -30
- data/lib/zuora_api/login.rb +190 -230
- data/lib/zuora_api/logins/basic.rb +17 -26
- data/lib/zuora_api/logins/oauth.rb +10 -8
- data/lib/zuora_api/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1bfd029f416736077243b7e0d6c8b3fd5e218167
|
4
|
+
data.tar.gz: 5344e6087fc2d37c50972ab97cd6705d4696bb23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4fd0150091455e2999b35081be1a078ca2a529e2ff264227048f3c1f7788b7a193510acb030270f051058f635edf2b51f557f1f2ecac2280ec1a9d33a58e772
|
7
|
+
data.tar.gz: 6700d2cceaf338fbb1f151841e65cf7980cc2e0a13370416cbd2530e8893716d7ec9aa286f6f203800c0e27845210ed4a20e567ea97335e8ef0d88a6294882b5
|
data/.gitlab-ci.yml
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
image: ruby:2.3.1
|
2
3
|
stages:
|
3
4
|
- setup
|
4
5
|
- test
|
@@ -40,24 +41,10 @@ rubygems-deploy:
|
|
40
41
|
stage: deploy
|
41
42
|
allow_failure: false
|
42
43
|
script:
|
43
|
-
- echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" >> /etc/apt/sources.list
|
44
|
-
- apt-get update
|
45
|
-
- apt-get install -y git
|
46
|
-
- apt-get clean all
|
47
|
-
- gem install dpl
|
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
|
-
- 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
|
-
- echo $VERSION
|
51
|
-
- sed -i "s/0.0.1/$VERSION/" /Connect/zuora-gem/lib/zuora_api/version.rb
|
52
|
-
- git add /Connect/zuora-gem/lib/zuora_api/version.rb
|
53
|
-
- git config --global user.email "connect@zuora.com"
|
54
|
-
- git config --global user.name "Connect Automation"
|
55
|
-
- git commit -m "Automated Version Update $VERSION"
|
56
44
|
- bundle install
|
57
45
|
- gem install rake
|
58
46
|
- version=$(rake install | grep -o 'pkg/zuora_api-.*gem')
|
59
47
|
- curl -u $USERNAME:$PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
|
60
48
|
- gem push $version
|
61
49
|
only:
|
62
|
-
|
63
|
-
- staging
|
50
|
+
- master
|
data/CHANGELOG.md
CHANGED
@@ -1,23 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [1.6.
|
5
|
-
### Changed
|
6
|
-
- Don't log fatal errors, allow application to decide for file download
|
7
|
-
- Don't change api url if the user set a high api url
|
8
|
-
|
9
|
-
###Removed
|
10
|
-
- Force encoding
|
11
|
-
|
12
|
-
## [1.6.28] - 2018-3-12
|
4
|
+
## [1.6.16] - 2018-12-09
|
13
5
|
### Added
|
14
|
-
-
|
6
|
+
- Example
|
15
7
|
|
16
|
-
|
17
|
-
|
18
|
-
|
8
|
+
### Changed
|
9
|
+
- Example
|
10
|
+
|
11
|
+
### Removed
|
12
|
+
- Example
|
19
13
|
|
20
14
|
## [1.6.22] - 2019-01-03
|
15
|
+
|
21
16
|
### Changed
|
22
17
|
- get_identity method - supports ZSession auth now
|
23
18
|
- updated rspecs accordingly
|
data/lib/zuora_api/exceptions.rb
CHANGED
@@ -6,8 +6,8 @@ module ZuoraAPI
|
|
6
6
|
attr_reader :code, :response
|
7
7
|
attr_writer :default_message
|
8
8
|
|
9
|
-
def initialize(message = nil,response=nil)
|
10
|
-
@code =
|
9
|
+
def initialize(message = nil,response=nil, code =nil)
|
10
|
+
@code = code
|
11
11
|
@message = message
|
12
12
|
@response = response
|
13
13
|
@default_message = "Error with Zuora Session."
|
@@ -22,8 +22,8 @@ module ZuoraAPI
|
|
22
22
|
attr_reader :code, :response, :errors, :successes
|
23
23
|
attr_writer :default_message
|
24
24
|
|
25
|
-
def initialize(message = nil,response=nil, errors = [], successes = []
|
26
|
-
@code =
|
25
|
+
def initialize(message = nil,response=nil, code =nil, errors = [], successes = [])
|
26
|
+
@code = code
|
27
27
|
@message = message
|
28
28
|
@response = response
|
29
29
|
@default_message = "Error with Zuora Entity"
|
@@ -40,8 +40,8 @@ module ZuoraAPI
|
|
40
40
|
attr_reader :code, :response, :errors, :successes
|
41
41
|
attr_writer :default_message
|
42
42
|
|
43
|
-
def initialize(message = nil,response=nil, errors = [], successes = []
|
44
|
-
@code =
|
43
|
+
def initialize(message = nil,response=nil, code =nil, errors = [], successes = [])
|
44
|
+
@code = code
|
45
45
|
@message = message
|
46
46
|
@response = response
|
47
47
|
@default_message = "Error communicating with Zuora."
|
@@ -58,8 +58,8 @@ module ZuoraAPI
|
|
58
58
|
attr_reader :code, :response
|
59
59
|
attr_writer :default_message
|
60
60
|
|
61
|
-
def initialize(message = nil,response=nil,
|
62
|
-
@code =
|
61
|
+
def initialize(message = nil,response=nil, code =nil)
|
62
|
+
@code = code
|
63
63
|
@message = message
|
64
64
|
@response = response
|
65
65
|
@default_message = "Your request limit has been exceeded for zuora."
|
@@ -74,24 +74,8 @@ module ZuoraAPI
|
|
74
74
|
attr_reader :code, :response
|
75
75
|
attr_writer :default_message
|
76
76
|
|
77
|
-
def initialize(message = nil,response=nil,
|
78
|
-
@code =
|
79
|
-
@message = message
|
80
|
-
@response = response
|
81
|
-
@default_message = "Operation failed due to lock competition. Please retry"
|
82
|
-
end
|
83
|
-
|
84
|
-
def to_s
|
85
|
-
@message || @default_message
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
class ZuoraDataIntegrity < Error
|
90
|
-
attr_reader :code, :response
|
91
|
-
attr_writer :default_message
|
92
|
-
|
93
|
-
def initialize(message = nil,response=nil, *args)
|
94
|
-
@code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
|
77
|
+
def initialize(message = nil,response=nil, code =nil)
|
78
|
+
@code = code
|
95
79
|
@message = message
|
96
80
|
@response = response
|
97
81
|
@default_message = "Operation failed due to lock competition. Please retry"
|
@@ -106,8 +90,8 @@ module ZuoraAPI
|
|
106
90
|
attr_reader :code, :response
|
107
91
|
attr_writer :default_message
|
108
92
|
|
109
|
-
def initialize(message = nil,response=nil,
|
110
|
-
@code =
|
93
|
+
def initialize(message = nil,response=nil, code =nil)
|
94
|
+
@code = code
|
111
95
|
@message = message
|
112
96
|
@response = response
|
113
97
|
@default_message = "There is a temporary error with zuora system."
|
@@ -122,8 +106,8 @@ module ZuoraAPI
|
|
122
106
|
attr_reader :code, :response
|
123
107
|
attr_writer :default_message
|
124
108
|
|
125
|
-
def initialize(message = nil,response=nil,
|
126
|
-
@code =
|
109
|
+
def initialize(message = nil,response=nil, code =nil)
|
110
|
+
@code = code
|
127
111
|
@message = message
|
128
112
|
@response = response
|
129
113
|
@default_message = "Authentication type is not supported by this Login"
|
data/lib/zuora_api/login.rb
CHANGED
@@ -1,38 +1,28 @@
|
|
1
1
|
require "httparty"
|
2
2
|
require "nokogiri"
|
3
3
|
require "uri"
|
4
|
-
require 'zuora_api/exceptions'
|
5
4
|
|
6
5
|
module ZuoraAPI
|
7
6
|
class Login
|
8
7
|
ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown', STAGING = 'Staging' ]
|
9
8
|
REGIONS = [EU = 'EU', US = 'US', NA = 'NA' ]
|
10
|
-
MIN_Endpoint = '
|
9
|
+
MIN_Endpoint = '91.0'
|
11
10
|
XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
12
|
-
CONNECTION_EXCEPTIONS = [Net::OpenTimeout, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError
|
11
|
+
CONNECTION_EXCEPTIONS = [Net::OpenTimeout, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError]
|
13
12
|
CONNECTION_READ_EXCEPTIONS = [Net::ReadTimeout, Errno::ECONNRESET, Errno::EPIPE]
|
14
|
-
ZUORA_API_ERRORS = [ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition, ZuoraAPI::Exceptions::ZuoraAPITemporaryError, ZuoraAPI::Exceptions::ZuoraDataIntegrity]
|
15
|
-
|
16
|
-
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
13
|
|
18
|
-
|
19
|
-
|
14
|
+
attr_accessor :region, :url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep, :hostname, :zconnect_provider
|
15
|
+
|
16
|
+
def initialize(url: nil, entity_id: nil, session: nil, status: nil, **keyword_args)
|
17
|
+
raise "URL is nil or empty, but URL is required" if url.nil? | url.empty?
|
20
18
|
# raise "URL is improper. URL must contain zuora.com, zuora.eu, or zuora.na" if /zuora.com|zuora.eu|zuora.na/ === url
|
21
|
-
|
22
|
-
if !/
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
self.entity_id = get_entity_id(entity_id: entity_id)
|
30
|
-
self.errors = Hash.new
|
31
|
-
self.current_session = session
|
32
|
-
self.bearer_token = bearer_token
|
33
|
-
self.oauth_session_expires_at = oauth_session_expires_at
|
34
|
-
self.status = status.blank? ? "Active" : status
|
35
|
-
self.user_info = Hash.new
|
19
|
+
@url = url.gsub(/(\d{2}\.\d)$/, MIN_Endpoint)
|
20
|
+
@hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil?
|
21
|
+
@entity_id = get_entity_id(entity_id: entity_id)
|
22
|
+
@errors = Hash.new
|
23
|
+
@current_session = session
|
24
|
+
@status = status.blank? ? "Active" : status
|
25
|
+
@user_info = Hash.new
|
36
26
|
self.update_region
|
37
27
|
self.update_environment
|
38
28
|
self.update_zconnect_provider
|
@@ -46,21 +36,21 @@ module ZuoraAPI
|
|
46
36
|
if !zsession.blank?
|
47
37
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
48
38
|
output_json = JSON.parse(response.body)
|
49
|
-
elsif zconnect_accesstoken.
|
39
|
+
elsif !zconnect_accesstoken.blank?
|
40
|
+
code = zconnect_accesstoken.split("#!").last
|
41
|
+
encrypted_token, tenant_id = Base64.decode64(code).split(":")
|
50
42
|
begin
|
51
|
-
code = zconnect_accesstoken.split("#!").last
|
52
|
-
encrypted_token, tenant_id = Base64.decode64(code).split(":")
|
53
43
|
body = {'token' => encrypted_token}.to_json
|
54
44
|
rescue => ex
|
55
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie")
|
45
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie", {}, 400)
|
56
46
|
end
|
57
47
|
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
|
58
48
|
output_json = JSON.parse(response.body)
|
59
49
|
else
|
60
50
|
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
61
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
51
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
62
52
|
else
|
63
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
53
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
64
54
|
end
|
65
55
|
end
|
66
56
|
rescue JSON::ParserError => ex
|
@@ -74,17 +64,17 @@ module ZuoraAPI
|
|
74
64
|
zsession = cookies["ZSession"]
|
75
65
|
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
76
66
|
begin
|
77
|
-
if zsession.
|
67
|
+
if !zsession.blank?
|
78
68
|
response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
79
69
|
output_json = JSON.parse(response.body)
|
80
|
-
elsif zconnect_accesstoken.
|
70
|
+
elsif !zconnect_accesstoken.blank?
|
81
71
|
response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
|
82
72
|
output_json = JSON.parse(response.body)
|
83
73
|
else
|
84
74
|
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
85
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
75
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
86
76
|
else
|
87
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
77
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
88
78
|
end
|
89
79
|
end
|
90
80
|
rescue JSON::ParserError => ex
|
@@ -106,9 +96,9 @@ module ZuoraAPI
|
|
106
96
|
output_json = JSON.parse(response.body)
|
107
97
|
else
|
108
98
|
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
109
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
99
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
110
100
|
else
|
111
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
101
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
112
102
|
end
|
113
103
|
end
|
114
104
|
rescue JSON::ParserError => ex
|
@@ -130,9 +120,9 @@ module ZuoraAPI
|
|
130
120
|
output_json = JSON.parse(response.body)
|
131
121
|
else
|
132
122
|
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
133
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
|
123
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
134
124
|
else
|
135
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
|
125
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
136
126
|
end
|
137
127
|
end
|
138
128
|
rescue JSON::ParserError => ex
|
@@ -180,12 +170,12 @@ module ZuoraAPI
|
|
180
170
|
if entity_ids.blank? && cookies["ZuoraCurrentEntity"].present?
|
181
171
|
entity_ids = Array(cookies["ZuoraCurrentEntity"].unpack("a8a4a4a4a12").join('-'))
|
182
172
|
else
|
183
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora Entity ID not provided")
|
173
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora Entity ID not provided", {}, 400)
|
184
174
|
end
|
185
175
|
if user_id.blank? && cookies["Zuora-User-Id"].present?
|
186
176
|
user_id = cookies["Zuora-User-Id"]
|
187
177
|
else
|
188
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided")
|
178
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided", {}, 400)
|
189
179
|
end
|
190
180
|
elsif !client_id.nil? && !client_secret.nil?
|
191
181
|
bearer_response = HTTParty.post("https://#{self.hostname}/oauth/token", :headers => {'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => 'application/json'}, :body => {'client_id' => client_id, 'client_secret' => URI::encode(client_secret), 'grant_type' => 'client_credentials'})
|
@@ -202,12 +192,12 @@ module ZuoraAPI
|
|
202
192
|
output_json["clientSecret"] = new_client_secret
|
203
193
|
return output_json
|
204
194
|
elsif oauth_response.code == 401 && !oauth_response.message.blank?
|
205
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], oauth_response)
|
195
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], {}, oauth_response.code)
|
206
196
|
else
|
207
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["error"], oauth_response)
|
197
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["error"], {}, oauth_response.code)
|
208
198
|
end
|
209
199
|
else
|
210
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Insufficient credentials provided")
|
200
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Insufficient credentials provided", {}, 400)
|
211
201
|
end
|
212
202
|
end
|
213
203
|
|
@@ -267,7 +257,7 @@ module ZuoraAPI
|
|
267
257
|
if !self.url.blank?
|
268
258
|
if /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/ === self.hostname
|
269
259
|
self.environment = 'Sandbox'
|
270
|
-
elsif /(?<=\.|\/|^)(service
|
260
|
+
elsif /(?<=\.|\/|^)(service|services[\d]*|ep-edge)(?=\.|\/|$)/ === self.hostname
|
271
261
|
self.environment = 'Services'
|
272
262
|
elsif /(?<=\.|\/|-|^)(pt[\d]*)(?=\.|\/|-|$)/ === self.hostname
|
273
263
|
self.environment = 'Performance'
|
@@ -342,22 +332,17 @@ module ZuoraAPI
|
|
342
332
|
when 'Services'
|
343
333
|
https = /https:\/\/|http:\/\//.match(self.url)[0]
|
344
334
|
host = self.hostname
|
345
|
-
endpoint = "#{https}
|
335
|
+
endpoint = "#{https}#{host}/apps/v1/#{url}"
|
346
336
|
when 'Staging'
|
347
|
-
endpoint = "https://rest-staging2.zuora.com/
|
337
|
+
endpoint = "https://rest-staging2.zuora.com/".concat(url)
|
348
338
|
when 'Unknown'
|
349
339
|
raise "Environment unknown, returning passed in parameter unaltered"
|
350
340
|
end
|
351
341
|
return endpoint
|
352
342
|
end
|
353
343
|
|
354
|
-
def rest_domain
|
355
|
-
require 'addressable/uri'
|
356
|
-
return ::Addressable::URI.parse(self.rest_endpoint).host
|
357
|
-
end
|
358
|
-
|
359
344
|
def fileURL(url="")
|
360
|
-
return self.
|
345
|
+
return self.url.split(".com").first.concat(".com/apps/api/file/").concat(url)
|
361
346
|
end
|
362
347
|
|
363
348
|
def dateFormat
|
@@ -368,16 +353,17 @@ module ZuoraAPI
|
|
368
353
|
end
|
369
354
|
|
370
355
|
def get_session(prefix: false, auth_type: :basic)
|
371
|
-
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}")
|
356
|
+
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}")
|
372
357
|
case auth_type
|
373
358
|
when :basic
|
374
359
|
if self.current_session.blank?
|
360
|
+
Rails.logger.debug("Create new session")
|
375
361
|
case self.class.to_s
|
376
362
|
when 'ZuoraAPI::Oauth'
|
377
363
|
if self.bearer_token.blank? || self.oauth_expired?
|
378
364
|
self.new_session(auth_type: :bearer)
|
379
365
|
end
|
380
|
-
self.get_z_session
|
366
|
+
self.get_z_session
|
381
367
|
when 'ZuoraAPI::Basic'
|
382
368
|
self.new_session(auth_type: :basic)
|
383
369
|
else
|
@@ -400,7 +386,7 @@ module ZuoraAPI
|
|
400
386
|
end
|
401
387
|
end
|
402
388
|
|
403
|
-
def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError]
|
389
|
+
def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError, ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition], z_session: true, timeout_retry: false, timeout: 120,**keyword_args)
|
404
390
|
tries ||= 2
|
405
391
|
xml = Nokogiri::XML::Builder.new do |xml|
|
406
392
|
xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/",
|
@@ -450,7 +436,7 @@ module ZuoraAPI
|
|
450
436
|
return output_xml, input_xml, response
|
451
437
|
end
|
452
438
|
end
|
453
|
-
rescue
|
439
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
454
440
|
if errors.include?(ex.class)
|
455
441
|
raise ex
|
456
442
|
else
|
@@ -472,12 +458,6 @@ module ZuoraAPI
|
|
472
458
|
else
|
473
459
|
raise ex
|
474
460
|
end
|
475
|
-
rescue Errno::ECONNRESET => ex
|
476
|
-
if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
|
477
|
-
retry
|
478
|
-
else
|
479
|
-
raise ex
|
480
|
-
end
|
481
461
|
rescue => ex
|
482
462
|
raise ex
|
483
463
|
else
|
@@ -519,102 +499,93 @@ module ZuoraAPI
|
|
519
499
|
if error.class == String
|
520
500
|
case error
|
521
501
|
when "INVALID_SESSION"
|
522
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{error}::#{message}", response)
|
502
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{error}::#{message}", body, response.code )
|
523
503
|
when "REQUEST_EXCEEDED_LIMIT"
|
524
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{error}::#{message}", response)
|
504
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{error}::#{message}", body, response.code)
|
525
505
|
when "LOCK_COMPETITION"
|
526
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
|
506
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", body, response.code)
|
527
507
|
when "BATCH_FAIL_ERROR"
|
528
508
|
if message.include?("optimistic locking failed")
|
529
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
|
509
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", body, response.code)
|
530
510
|
else
|
531
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
|
511
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code)
|
532
512
|
end
|
533
513
|
when "TEMPORARY_ERROR"
|
534
|
-
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{error}::#{message}", response)
|
535
|
-
when "INVALID_VALUE"
|
536
|
-
if message.include?("data integrity violation")
|
537
|
-
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
|
538
|
-
else
|
539
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
|
540
|
-
end
|
514
|
+
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{error}::#{message}", body, response.code)
|
541
515
|
else
|
542
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response) if error.present?
|
516
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code) if error.present?
|
543
517
|
end
|
544
518
|
elsif error.class == Array
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
519
|
+
if error[0].include?("LOCK_COMPETITION") && error.count == 1
|
520
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), body, response.code)
|
521
|
+
else
|
522
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), body, response.code, error, success)
|
523
|
+
end
|
550
524
|
end
|
551
525
|
end
|
552
|
-
|
526
|
+
|
553
527
|
if response.code == 429
|
554
|
-
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)
|
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.", body, response.code)
|
555
529
|
end
|
556
530
|
|
557
531
|
when :JSON
|
558
|
-
body = body.dig("results").present? ? body["results"] : body if body.class == Hash
|
559
532
|
if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
|
560
|
-
messages_array = body
|
561
|
-
|
562
|
-
codes_array = body.fetch("reasons", []).map {|error| error['code']}.compact
|
563
|
-
codes_array = codes_array.push(body.dig("error", 'code')).compact if body.dig('error').class == Hash
|
533
|
+
messages_array = (body["reasons"] || []).map {|error| error['message']}.compact
|
534
|
+
codes_array = (body["reasons"] || []).map {|error| error['code']}.compact
|
564
535
|
|
565
536
|
if body['message'] == "No bearer token" && response.code == 400
|
566
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new(
|
537
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new()
|
567
538
|
end
|
568
539
|
|
569
540
|
if body['errorMessage']
|
570
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errorMessage'],
|
541
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errorMessage'],body,response.code)
|
571
542
|
end
|
572
543
|
|
573
544
|
if body.dig("reasons").nil? ? false : body.dig("reasons")[0].dig("code") == 90000020
|
574
|
-
raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", response)
|
545
|
+
raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", body, response.code)
|
575
546
|
end
|
576
547
|
|
577
548
|
if body['error'] == 'Unauthorized' && body['status'] = 401
|
578
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
|
549
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
|
579
550
|
end
|
580
551
|
#Authentication failed
|
581
|
-
if
|
582
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
|
552
|
+
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401
|
553
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
|
583
554
|
end
|
584
555
|
|
585
556
|
#Zuora REST Create Amendment error #Authentication failed
|
586
557
|
if body["faultcode"].present? && body["faultcode"] == "fns:INVALID_SESSION"
|
587
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body['faultstring']}", response)
|
558
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body['faultstring']}", body, response.code)
|
588
559
|
end
|
589
560
|
|
590
561
|
#Request exceeded limit
|
591
562
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70)
|
592
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", response)
|
563
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", body, response.code)
|
593
564
|
end
|
594
565
|
|
595
566
|
#Locking contention
|
596
567
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
|
597
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
|
598
|
-
end
|
568
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", body, response.code)
|
569
|
+
end
|
599
570
|
|
600
571
|
#All Errors catch
|
601
572
|
if codes_array.size > 0
|
602
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages_array.join(', ')}", response)
|
573
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages_array.join(', ')}", body, response.code)
|
603
574
|
end
|
604
575
|
|
605
576
|
#Zuora REST Query Errors
|
606
577
|
if body["faultcode"].present?
|
607
578
|
case body["faultcode"]
|
608
579
|
when "fns:MALFORMED_QUERY"
|
609
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
580
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
|
610
581
|
when "fns:REQUEST_EXCEEDED_LIMIT"
|
611
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
582
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
|
612
583
|
when "fns:LOCK_COMPETITION"
|
613
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
584
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
|
614
585
|
when "INVALID_SESSION"
|
615
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
586
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
|
616
587
|
else
|
617
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
|
588
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
|
618
589
|
end
|
619
590
|
end
|
620
591
|
|
@@ -623,39 +594,34 @@ module ZuoraAPI
|
|
623
594
|
(body["Errors"] || []).select { |obj| errors.push(obj["Message"]) }.compact
|
624
595
|
(body["errors"] || []).select { |obj| errors.push(obj["Message"]) }.compact
|
625
596
|
if errors.size > 0
|
626
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{errors.join(", ")}", response, errors)
|
597
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{errors.join(", ")}", body, response.code, errors)
|
627
598
|
end
|
628
599
|
end
|
629
600
|
end
|
630
601
|
|
631
|
-
#Zuora REST Actions error (Create, Update, Delete
|
602
|
+
#Zuora REST Actions error (Create, Update, Delete)
|
632
603
|
if body.class == Array
|
633
604
|
all_errors = body.select {|obj| !obj['Success'] || !obj['success'] }.map {|obj| obj['Errors'] || obj['errors'] }.compact
|
634
605
|
all_success = body.select {|obj| obj['Success'] || obj['success']}.compact
|
635
606
|
|
636
607
|
if all_success.blank? && all_errors.present?
|
637
608
|
error_codes = all_errors.flatten.group_by {|error| error['Code']}.keys.uniq
|
638
|
-
|
639
|
-
|
640
|
-
if error_codes.first == "LOCK_COMPETITION"
|
641
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", response)
|
642
|
-
elsif error_messages.first.include?("data integrity violation")
|
643
|
-
raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
|
644
|
-
end
|
609
|
+
if error_codes.size == 1 && error_codes[0] == "LOCK_COMPETITION"
|
610
|
+
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", body, response.code)
|
645
611
|
end
|
646
612
|
end
|
647
613
|
|
648
614
|
if all_errors.size > 0
|
649
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{all_errors.flatten.group_by {|error| error['Message']}.keys.uniq.join(' ')}", response, all_errors, all_success)
|
615
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{all_errors.flatten.group_by {|error| error['Message']}.keys.uniq.join(' ')}", body, response.code, all_errors, all_success )
|
650
616
|
end
|
651
617
|
end
|
652
618
|
|
653
619
|
#All other errors
|
654
|
-
if
|
620
|
+
if response.code != 200
|
655
621
|
if response.code == 429
|
656
|
-
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)
|
622
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("The total number of concurrent requests has exceeded the limit allowed by the system. Please resubmit your request later.", body, response.code)
|
657
623
|
else
|
658
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{response.message}", response)
|
624
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{response.message}", body, response.code)
|
659
625
|
end
|
660
626
|
end
|
661
627
|
end
|
@@ -678,7 +644,7 @@ module ZuoraAPI
|
|
678
644
|
}
|
679
645
|
response = self.rest_call(method: :post, body: params.to_json, url: self.aqua_endpoint("batch-query/"))
|
680
646
|
if(response[0]["id"].nil?)
|
681
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error in AQuA Process.
|
647
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error in AQuA Process. #{response}")
|
682
648
|
end
|
683
649
|
return getFileById(id: response[0]["id"])
|
684
650
|
end
|
@@ -691,7 +657,7 @@ module ZuoraAPI
|
|
691
657
|
response, fullResponse = self.rest_call(method: :get, body: {}, url: self.aqua_endpoint("batch-query/jobs/#{id}"))
|
692
658
|
result = response["batches"][0]["status"]
|
693
659
|
if result == "error"
|
694
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Aqua Error
|
660
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Aqua Error: #{response}")
|
695
661
|
break
|
696
662
|
end
|
697
663
|
end
|
@@ -707,7 +673,7 @@ module ZuoraAPI
|
|
707
673
|
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"}
|
708
674
|
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
|
709
675
|
|
710
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401'
|
676
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401' ) if response.code == 401
|
711
677
|
|
712
678
|
output_xml = Nokogiri::XML(response.body)
|
713
679
|
des_hash = Hash.new
|
@@ -747,12 +713,11 @@ module ZuoraAPI
|
|
747
713
|
raise ex
|
748
714
|
end
|
749
715
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
750
|
-
if !(tries -= 1).zero?
|
751
|
-
Rails.logger.
|
716
|
+
if !(tries -= 1).zero?
|
717
|
+
Rails.logger.info("Session expired. Starting new session.")
|
752
718
|
self.new_session
|
753
719
|
retry
|
754
720
|
else
|
755
|
-
Rails.logger.error("Session expired. Starting new session.")
|
756
721
|
raise ex
|
757
722
|
end
|
758
723
|
rescue => ex
|
@@ -761,7 +726,7 @@ module ZuoraAPI
|
|
761
726
|
return des_hash
|
762
727
|
end
|
763
728
|
|
764
|
-
def rest_call(method: :get, body: nil, headers: {}, url: rest_endpoint("catalog/products?pageSize=4"), debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError]
|
729
|
+
def rest_call(method: :get, body: nil, headers: {}, url: rest_endpoint("catalog/products?pageSize=4"), debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError, ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition], z_session: true, session_type: :basic, timeout_retry: false, timeout: 120, **keyword_args)
|
765
730
|
tries ||= 2
|
766
731
|
|
767
732
|
if self.entity_id.present?
|
@@ -772,9 +737,9 @@ module ZuoraAPI
|
|
772
737
|
raise "Method not supported, supported methods include: :get, :post, :put, :delete, :patch, :head, :options" if ![:get, :post, :put, :delete, :patch, :head, :options].include?(method)
|
773
738
|
|
774
739
|
authentication_headers = z_session ? {"Authorization" => self.get_session(prefix: true, auth_type: session_type) } : {}
|
775
|
-
|
740
|
+
headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(headers).merge(authentication_headers)
|
776
741
|
|
777
|
-
response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers:
|
742
|
+
response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: headers, timeout: timeout).perform
|
778
743
|
Rails.logger.debug("Response Code: #{response.code}") if debug
|
779
744
|
begin
|
780
745
|
output_json = JSON.parse(response.body)
|
@@ -785,8 +750,8 @@ module ZuoraAPI
|
|
785
750
|
|
786
751
|
raise_errors(type: :JSON, body: output_json, response: response)
|
787
752
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
788
|
-
if self.class.to_s == 'ZuoraAPI::Oauth'
|
789
|
-
self.rest_call(method: method.to_sym, url: url,
|
753
|
+
if self.class.to_s == 'ZuoraAPI::Oauth'
|
754
|
+
self.rest_call(method: method.to_sym, url: url, debug: debug, errors: errors, z_session: z_session, session_type: :bearer, timeout_retry: timeout_retry, timeout: timeout)
|
790
755
|
else
|
791
756
|
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
792
757
|
raise ex
|
@@ -803,7 +768,7 @@ module ZuoraAPI
|
|
803
768
|
return [output_json, response]
|
804
769
|
end
|
805
770
|
end
|
806
|
-
rescue
|
771
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
807
772
|
if errors.include?(ex.class)
|
808
773
|
raise ex
|
809
774
|
else
|
@@ -827,12 +792,6 @@ module ZuoraAPI
|
|
827
792
|
else
|
828
793
|
raise ex
|
829
794
|
end
|
830
|
-
rescue Errno::ECONNRESET => ex
|
831
|
-
if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
|
832
|
-
retry
|
833
|
-
else
|
834
|
-
raise ex
|
835
|
-
end
|
836
795
|
rescue => ex
|
837
796
|
raise ex
|
838
797
|
else
|
@@ -860,7 +819,7 @@ module ZuoraAPI
|
|
860
819
|
Rails.logger.debug("Fetch Catalog URL #{url}")
|
861
820
|
output_json, response = self.rest_call(:debug => false, :url => url, :errors => [ZuoraAPI::Exceptions::ZuoraAPISessionError], :timeout_retry => true )
|
862
821
|
if !output_json['success'] =~ (/(true|t|yes|y|1)$/i) || output_json['success'].class != TrueClass
|
863
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}"
|
822
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}")
|
864
823
|
end
|
865
824
|
output_json["products"].each do |product|
|
866
825
|
catalog_map[product["id"]] = {"productId" => product["id"]}
|
@@ -897,130 +856,129 @@ module ZuoraAPI
|
|
897
856
|
uri = URI.parse(url)
|
898
857
|
http = Net::HTTP.new(uri.host, uri.port)
|
899
858
|
http.read_timeout = timeout #Seconds
|
900
|
-
http.use_ssl = true if
|
859
|
+
http.use_ssl = true if uri.scheme.downcase == 'https'
|
901
860
|
if z_session
|
902
861
|
headers = headers.merge({"Authorization" => self.get_session(prefix: true)})
|
903
862
|
headers = headers.merge({"Zuora-Entity-Ids" => self.entity_id}) if !self.entity_id.blank?
|
904
863
|
end
|
905
864
|
|
906
865
|
response_save = nil
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
status_code = response.code if response
|
911
|
-
|
912
|
-
case response
|
913
|
-
when Net::HTTPNotFound
|
914
|
-
raise
|
915
|
-
|
916
|
-
when Net::HTTPUnauthorized
|
917
|
-
if count <= 0
|
918
|
-
if z_session
|
919
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
920
|
-
else
|
921
|
-
raise
|
922
|
-
end
|
923
|
-
end
|
924
|
-
self.new_session if z_session
|
925
|
-
return get_file(:url => url, :headers => headers, :count => count - 1, :z_session => z_session, :tempfile => tempfile, :file_path => file_path, :timeout_retries => timeout_retries, :timeout => timeout)
|
866
|
+
http.request_get(uri.request_uri, headers) do |response|
|
867
|
+
response_save = response
|
868
|
+
status_code = response.code if response
|
926
869
|
|
927
|
-
|
928
|
-
|
870
|
+
case response
|
871
|
+
when Net::HTTPNotFound
|
872
|
+
Rails.logger.fatal("404 - Not Found")
|
873
|
+
raise
|
929
874
|
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
if output_file_name.present?
|
937
|
-
file_ending ||= output_file_name.end_with?(".csv.zip") ? ".csv.zip" : File.extname(output_file_name)
|
938
|
-
filename ||= File.basename(output_file_name, file_ending)
|
875
|
+
when Net::HTTPUnauthorized
|
876
|
+
if count <= 0
|
877
|
+
if z_session
|
878
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
|
879
|
+
else
|
880
|
+
raise
|
939
881
|
end
|
882
|
+
end
|
883
|
+
Rails.logger.fatal("Unauthorized: Retry")
|
884
|
+
self.new_session if z_session
|
885
|
+
return get_file(:url => url, :headers => headers, :count => count - 1, :z_session => z_session, :tempfile => tempfile, :file_path => file_path, :timeout_retries => timeout_retries, :timeout => timeout)
|
940
886
|
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
case response.header["Content-Disposition"]
|
945
|
-
when /.*; filename\*=.*/
|
946
|
-
full_filename ||= /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[2].strip
|
947
|
-
encoding = /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[1].strip
|
948
|
-
when /.*; filename=/
|
949
|
-
full_filename ||= /.*; filename=(.*)/.match(response.header["Content-Disposition"])[1].strip
|
950
|
-
else
|
951
|
-
raise "Can't parse Content-Disposition header: #{response.header["Content-Disposition"]}"
|
952
|
-
end
|
953
|
-
file_ending ||= full_filename.end_with?(".csv.zip") ? ".csv.zip" : File.extname(full_filename)
|
954
|
-
filename ||= File.basename(full_filename, file_ending)
|
955
|
-
end
|
887
|
+
when *(CONNECTION_EXCEPTIONS).concat(CONNECTION_READ_EXCEPTIONS)
|
888
|
+
Rails.logger.fatal("#{response.class} timeout - retry")
|
889
|
+
return get_file(:url => url, :headers => headers, :count => count, :z_session => z_session, :tempfile => tempfile, :file_path => file_path, :timeout_retries => timeout_retries - 1, :timeout => timeout)
|
956
890
|
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
else
|
967
|
-
type = response.header["Content-Type"]
|
968
|
-
encoding ||= 'UTF-8'
|
969
|
-
end
|
970
|
-
end
|
891
|
+
when Net::HTTPClientError
|
892
|
+
raise
|
893
|
+
|
894
|
+
when Net::HTTPOK
|
895
|
+
headers = {}
|
896
|
+
response.each_header do |k,v|
|
897
|
+
headers[k] = v
|
898
|
+
end
|
899
|
+
Rails.logger.debug("Headers: #{headers.to_s}")
|
971
900
|
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
901
|
+
if output_file_name.present?
|
902
|
+
file_ending ||= output_file_name.end_with?(".csv.zip") ? ".csv.zip" : File.extname(output_file_name)
|
903
|
+
filename ||= File.basename(output_file_name, file_ending)
|
904
|
+
end
|
905
|
+
|
906
|
+
size, export_progress = [0, 0]
|
907
|
+
encoding, type, full_filename = [nil, nil, nil]
|
908
|
+
if response.header["Content-Disposition"].present?
|
909
|
+
case response.header["Content-Disposition"]
|
910
|
+
when /.*; filename\*=.*/
|
911
|
+
full_filename ||= /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[2].strip
|
912
|
+
encoding = /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[1].strip
|
913
|
+
when /.*; filename=/
|
914
|
+
full_filename ||= /.*; filename=(.*)/.match(response.header["Content-Disposition"])[1].strip
|
915
|
+
else
|
916
|
+
raise "Can't parse Content-Disposition header: #{response.header["Content-Disposition"]}"
|
976
917
|
end
|
918
|
+
file_ending ||= full_filename.end_with?(".csv.zip") ? ".csv.zip" : File.extname(full_filename)
|
919
|
+
filename ||= File.basename(full_filename, file_ending)
|
920
|
+
end
|
977
921
|
|
978
|
-
|
922
|
+
#If user supplied a filename use it, else default to content header filename, else default to uri pattern
|
923
|
+
file_ending ||= uri.path.end_with?(".csv.zip") ? ".csv.zip" : File.extname(uri.path)
|
924
|
+
filename ||= File.basename(uri.path, file_ending)
|
979
925
|
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
926
|
+
if response.header["Content-Type"].present?
|
927
|
+
case response.header["Content-Type"]
|
928
|
+
when /.*;charset=.*/
|
929
|
+
type = /(.*);charset=(.*)/.match(response.header["Content-Type"])[1]
|
930
|
+
encoding = /(.*);charset=(.*)/.match(response.header["Content-Type"])[2]
|
984
931
|
else
|
985
|
-
|
932
|
+
type = response.header["Content-Type"]
|
933
|
+
encoding ||= 'UTF-8'
|
986
934
|
end
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
935
|
+
end
|
936
|
+
Rails.logger.info("File: #{filename}#{file_ending} #{encoding} #{type}")
|
937
|
+
|
938
|
+
if response.header["Content-Length"].present?
|
939
|
+
export_size = response.header["Content-Length"].to_i
|
940
|
+
elsif response.header["ContentLength"].present?
|
941
|
+
export_size = response.header["ContentLength"].to_i
|
942
|
+
end
|
943
|
+
|
944
|
+
file_prefix = add_timestamp ? "#{filename}_#{Time.now.to_i}" : filename
|
945
|
+
if tempfile
|
946
|
+
require 'tempfile'
|
947
|
+
file_handle = ::Tempfile.new([file_prefix, "#{file_ending}"], file_path)
|
948
|
+
else
|
949
|
+
file_handle = File.new(file_path.join("#{file_prefix}#{file_ending}"), "w+")
|
950
|
+
end
|
951
|
+
file_handle.binmode
|
952
|
+
|
953
|
+
response.read_body do |chunk|
|
954
|
+
file_handle << chunk.force_encoding(encoding)
|
955
|
+
|
956
|
+
if defined?(export_size) && export_size != 0 && export_size.class == Integer
|
957
|
+
size += chunk.size
|
958
|
+
new_progress = (size * 100) / export_size
|
959
|
+
unless new_progress == export_progress
|
960
|
+
Rails.logger.debug("Login: Export Downloading %s (%3d%%)" % [filename, new_progress])
|
999
961
|
end
|
962
|
+
export_progress = new_progress
|
1000
963
|
end
|
964
|
+
end
|
1001
965
|
|
1002
|
-
|
1003
|
-
|
966
|
+
file_handle.close
|
967
|
+
Rails.logger.debug("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb")
|
1004
968
|
|
1005
|
-
|
1006
|
-
end
|
1007
|
-
end
|
1008
|
-
rescue *(CONNECTION_EXCEPTIONS).concat(CONNECTION_READ_EXCEPTIONS).concat([Net::HTTPBadResponse]) => e
|
1009
|
-
sleep(5)
|
1010
|
-
if (timeout_retries -= 1) >= 0
|
1011
|
-
Rails.logger.warn("Download Failed: #{e.class} : #{e.message}")
|
1012
|
-
retry
|
1013
|
-
else
|
1014
|
-
raise
|
969
|
+
return file_handle
|
1015
970
|
end
|
1016
971
|
end
|
1017
|
-
rescue =>
|
1018
|
-
Rails.logger.fatal(
|
972
|
+
rescue Exception => e
|
973
|
+
Rails.logger.fatal("Download Failed: #{response_save} - #{e.class} : #{e.message}")
|
974
|
+
Rails.logger.fatal("Download Failed: #{e.backtrace.join("\n")}")
|
1019
975
|
raise
|
1020
976
|
end
|
1021
977
|
end
|
1022
978
|
|
1023
979
|
def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
|
980
|
+
Rails.logger.debug("Build export")
|
981
|
+
Rails.logger.debug("#{query}")
|
1024
982
|
request = Nokogiri::XML::Builder.new do |xml|
|
1025
983
|
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
|
1026
984
|
xml['SOAP-ENV'].Header do
|
@@ -1075,6 +1033,7 @@ module ZuoraAPI
|
|
1075
1033
|
end
|
1076
1034
|
|
1077
1035
|
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
1036
|
+
Rails.logger.debug('=====> Export finished')
|
1078
1037
|
export_file = get_file(:url => self.fileURL(file_id))
|
1079
1038
|
export_file_path = export_file.path
|
1080
1039
|
Rails.logger.debug("=====> Export path #{export_file.path}")
|
@@ -1093,6 +1052,7 @@ module ZuoraAPI
|
|
1093
1052
|
end
|
1094
1053
|
|
1095
1054
|
def query(query, parse = false)
|
1055
|
+
Rails.logger.debug("Querying Zuora for #{query}")
|
1096
1056
|
output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
|
1097
1057
|
xml['ns1'].query do
|
1098
1058
|
xml['ns1'].queryString query
|
@@ -1,17 +1,15 @@
|
|
1
1
|
module ZuoraAPI
|
2
2
|
class Basic < Login
|
3
|
-
attr_accessor :username, :password
|
4
|
-
def initialize(username: nil, password: nil,
|
5
|
-
|
6
|
-
|
7
|
-
self.current_session = session
|
8
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Basic Login but either 'Username' or 'Password' were not passed.") if self.current_session.blank? && (self.password.blank? && self.username.blank?)
|
3
|
+
attr_accessor :username, :password
|
4
|
+
def initialize(username: nil, password: nil, **keyword_args)
|
5
|
+
@username = username
|
6
|
+
@password = password
|
9
7
|
super
|
10
8
|
end
|
11
9
|
|
12
|
-
def new_session(auth_type: :basic, debug: false)
|
10
|
+
def new_session( auth_type: :basic, debug: false)
|
13
11
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
|
14
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("
|
12
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login requires username and password to be set.") if auth_type == :basic && (self.password.blank? && self.username.blank?)
|
15
13
|
|
16
14
|
tries ||= 2
|
17
15
|
request = Nokogiri::XML::Builder.new do |xml|
|
@@ -29,16 +27,16 @@ module ZuoraAPI
|
|
29
27
|
|
30
28
|
input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
31
29
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
32
|
-
Rails.logger.debug('Connect') {"SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
30
|
+
Rails.logger.debug('Connect') {"Request Code: #{@response_query.code} SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
33
31
|
|
34
|
-
response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => 10)
|
35
|
-
output_xml = Nokogiri::XML(response_query.body)
|
36
|
-
Rails.logger.debug('Connect') {"Response Code: #{response_query.code} SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
32
|
+
@response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => 10)
|
33
|
+
@output_xml = Nokogiri::XML(@response_query.body)
|
34
|
+
Rails.logger.debug('Connect') {"Response Code: #{@response_query.code} SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
37
35
|
|
38
|
-
if
|
36
|
+
if !@response_query.success?
|
39
37
|
self.current_session = nil
|
40
|
-
if output_xml.namespaces.size > 0 && output_xml.xpath('//soapenv:Fault').size > 0
|
41
|
-
self.current_error = output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
38
|
+
if @output_xml.namespaces.size > 0 && @output_xml.xpath('//soapenv:Fault').size > 0
|
39
|
+
self.current_error = @output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
42
40
|
if self.current_error.include?('deactivated')
|
43
41
|
self.status = 'Deactivated'
|
44
42
|
self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
|
@@ -77,20 +75,19 @@ module ZuoraAPI
|
|
77
75
|
self.errors[:base] = self.current_error
|
78
76
|
else
|
79
77
|
self.status = 'Unknown'
|
80
|
-
self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
|
78
|
+
self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
|
81
79
|
self.errors[:base] = self.current_error
|
82
80
|
end
|
83
81
|
|
84
82
|
else
|
85
83
|
self.status = 'Unknown'
|
86
|
-
self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
|
84
|
+
self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
|
87
85
|
self.errors[:base] = self.current_error
|
88
86
|
end
|
89
87
|
else
|
90
88
|
#Username & password combo
|
91
|
-
retrieved_session = output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
|
92
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call."
|
93
|
-
self.status = 'Active'
|
89
|
+
retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
|
90
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
|
94
91
|
self.current_session = retrieved_session
|
95
92
|
end
|
96
93
|
return self.status
|
@@ -104,12 +101,6 @@ module ZuoraAPI
|
|
104
101
|
self.status = 'Timeout'
|
105
102
|
return self.status
|
106
103
|
end
|
107
|
-
rescue EOFError
|
108
|
-
if self.url.match?(/.*services\d{1,}.zuora.com*/)
|
109
|
-
self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available."
|
110
|
-
self.status = 'Not Available'
|
111
|
-
return self.status
|
112
|
-
end
|
113
104
|
end
|
114
105
|
end
|
115
106
|
end
|
@@ -5,9 +5,9 @@ module ZuoraAPI
|
|
5
5
|
def initialize(oauth_client_id: nil, oauth_secret: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args)
|
6
6
|
self.oauth_client_id = oauth_client_id
|
7
7
|
self.oauth_secret = oauth_secret
|
8
|
-
self.bearer_token = bearer_token
|
9
|
-
self.oauth_session_expires_at = oauth_session_expires_at
|
10
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if
|
8
|
+
self.bearer_token = bearer_token if !bearer_token.blank?
|
9
|
+
self.oauth_session_expires_at = oauth_session_expires_at if !oauth_session_expires_at.blank?
|
10
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if @oauth_client_id.blank? || @oauth_secret.blank?
|
11
11
|
super
|
12
12
|
end
|
13
13
|
|
@@ -16,10 +16,10 @@ module ZuoraAPI
|
|
16
16
|
get_bearer_token()
|
17
17
|
elsif auth_type == :basic
|
18
18
|
get_bearer_token() if self.oauth_expired?
|
19
|
-
get_z_session()
|
19
|
+
get_z_session()
|
20
20
|
else
|
21
21
|
get_bearer_token()
|
22
|
-
get_z_session()
|
22
|
+
get_z_session()
|
23
23
|
end
|
24
24
|
return self.status
|
25
25
|
end
|
@@ -66,8 +66,6 @@ module ZuoraAPI
|
|
66
66
|
|
67
67
|
def get_bearer_token
|
68
68
|
tries ||= 2
|
69
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if self.oauth_client_id.blank? || self.oauth_secret.blank?
|
70
|
-
|
71
69
|
output_json, response = self.rest_call(:method => :post,
|
72
70
|
:url => self.rest_endpoint.chomp('v1/').concat("oauth/token"),
|
73
71
|
:z_session => false,
|
@@ -89,7 +87,11 @@ module ZuoraAPI
|
|
89
87
|
self.status = 'Invalid Login'
|
90
88
|
return self.status
|
91
89
|
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
92
|
-
|
90
|
+
if errors.include?(ex.class)
|
91
|
+
raise ex
|
92
|
+
else
|
93
|
+
return [output_json, response]
|
94
|
+
end
|
93
95
|
rescue *(CONNECTION_EXCEPTIONS).concat(CONNECTION_READ_EXCEPTIONS) => ex
|
94
96
|
if !(tries -= 1).zero?
|
95
97
|
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
data/lib/zuora_api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zuora_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.251
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zuora Strategic Solutions Group
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -186,7 +186,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
186
|
- !ruby/object:Gem::Version
|
187
187
|
version: '0'
|
188
188
|
requirements: []
|
189
|
-
|
189
|
+
rubyforge_project:
|
190
|
+
rubygems_version: 2.6.8
|
190
191
|
signing_key:
|
191
192
|
specification_version: 4
|
192
193
|
summary: Gem that provides easy integration to Zuora
|