zuora_api 1.5.2 → 1.6.0
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/.gitlab-ci.yml +1 -14
- data/lib/zuora_api.rb +2 -1
- data/lib/zuora_api/exceptions.rb +35 -1
- data/lib/zuora_api/login.rb +115 -310
- data/lib/zuora_api/logins/basic.rb +103 -0
- data/lib/zuora_api/logins/oauth.rb +106 -0
- data/lib/zuora_api/version.rb +1 -1
- data/zuora_api.gemspec +1 -1
- metadata +6 -5
- data/lib/zuora_api/metrics_helper.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65fac01cabaf327d7cf9b15fbce13cfb784ecc28
|
4
|
+
data.tar.gz: 3d02d5242b1800403685ef3408891337de774f98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb9dc6f29b775a6174470fd1c122da7951ba05a5b43a700cd23001e2b584654d337e2b5489b900f158d9a1ddab7d4eb3efc7ac02139df7925e410e81647159f8
|
7
|
+
data.tar.gz: e9f520c636e4c6f7b2a51088af86bd916fd6191102e4f555f16c2bc9af97f70a379af42cc067d5fd2a7a02a09efdc42a7ede6408560e66df11795ae168bb0bb3
|
data/.gitlab-ci.yml
CHANGED
@@ -47,17 +47,4 @@ rubygems-deploy:
|
|
47
47
|
- curl -u $USERNAME:$PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
|
48
48
|
- gem push $version
|
49
49
|
only:
|
50
|
-
- master
|
51
|
-
|
52
|
-
rubygems-deploy:
|
53
|
-
stage: deploy
|
54
|
-
allow_failure: false
|
55
|
-
when: manual
|
56
|
-
script:
|
57
|
-
- bundle install
|
58
|
-
- gem install rake
|
59
|
-
- version=$(rake install | grep -o 'pkg/zuora_api-.*gem')
|
60
|
-
- curl -u $USERNAME:$PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
|
61
|
-
- gem push $version
|
62
|
-
only:
|
63
|
-
- staging
|
50
|
+
- master
|
data/lib/zuora_api.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'rails'
|
2
2
|
require "zuora_api/login"
|
3
|
+
require "zuora_api/logins/basic"
|
4
|
+
require "zuora_api/logins/oauth"
|
3
5
|
require 'zuora_api/exceptions'
|
4
6
|
require "insights_api/login"
|
5
|
-
require "zuora_api/metrics_helper"
|
6
7
|
module ZuoraAPI
|
7
8
|
# Your code goes here...
|
8
9
|
end
|
data/lib/zuora_api/exceptions.rb
CHANGED
@@ -2,7 +2,6 @@ module ZuoraAPI
|
|
2
2
|
module Exceptions
|
3
3
|
class Error < StandardError; end
|
4
4
|
class AuthorizationNotPerformed < Error; end
|
5
|
-
|
6
5
|
class ZuoraAPISessionError < Error
|
7
6
|
attr_reader :code, :response
|
8
7
|
attr_writer :default_message
|
@@ -19,6 +18,24 @@ module ZuoraAPI
|
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
21
|
+
class BadEntityError < Error
|
22
|
+
attr_reader :code, :response, :errors, :successes
|
23
|
+
attr_writer :default_message
|
24
|
+
|
25
|
+
def initialize(message = nil,response=nil, code =nil, errors = [], successes = [])
|
26
|
+
@code = code
|
27
|
+
@message = message
|
28
|
+
@response = response
|
29
|
+
@default_message = "Error with Zuora Entity"
|
30
|
+
@errors = errors
|
31
|
+
@successes = successes
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
@message || @default_message
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
22
39
|
class ZuoraAPIError < Error
|
23
40
|
attr_reader :code, :response, :errors, :successes
|
24
41
|
attr_writer :default_message
|
@@ -68,5 +85,22 @@ module ZuoraAPI
|
|
68
85
|
@message || @default_message
|
69
86
|
end
|
70
87
|
end
|
88
|
+
|
89
|
+
|
90
|
+
class ZuoraAPIAuthenticationTypeError < Error
|
91
|
+
attr_reader :code, :response
|
92
|
+
attr_writer :default_message
|
93
|
+
|
94
|
+
def initialize(message = nil,response=nil, code =nil)
|
95
|
+
@code = code
|
96
|
+
@message = message
|
97
|
+
@response = response
|
98
|
+
@default_message = "Authentication type is not supported by this Login"
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_s
|
102
|
+
@message || @default_message
|
103
|
+
end
|
104
|
+
end
|
71
105
|
end
|
72
106
|
end
|
data/lib/zuora_api/login.rb
CHANGED
@@ -6,29 +6,26 @@ module ZuoraAPI
|
|
6
6
|
class Login
|
7
7
|
ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown' ]
|
8
8
|
REGIONS = [EU = 'EU', US = 'US' ]
|
9
|
-
XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
10
|
-
attr_accessor :
|
9
|
+
XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
10
|
+
attr_accessor :region, :url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep
|
11
11
|
|
12
|
-
def initialize(
|
13
|
-
@username = username
|
14
|
-
@password = password
|
12
|
+
def initialize(url: nil, entity_id: nil, session: nil, status: nil, **keyword_args)
|
15
13
|
@url = url
|
16
14
|
@entity_id = entity_id
|
17
|
-
@current_session = session
|
18
15
|
@errors = Hash.new
|
16
|
+
@current_session = session
|
19
17
|
@status = status.blank? ? "Active" : status
|
20
18
|
@user_info = Hash.new
|
21
19
|
self.update_environment
|
22
20
|
@timeout_sleep = 5
|
23
21
|
end
|
24
22
|
|
25
|
-
|
26
23
|
def self.environments
|
27
|
-
%w(Sandbox Production Services Performance)
|
24
|
+
%w(Sandbox Production Services Performance Staging)
|
28
25
|
end
|
29
26
|
|
30
27
|
def self.regions
|
31
|
-
%w(US EU)
|
28
|
+
%w(US EU NA)
|
32
29
|
end
|
33
30
|
|
34
31
|
def self.endpoints
|
@@ -39,23 +36,28 @@ module ZuoraAPI
|
|
39
36
|
"EU" => {"Sandbox" => "https://sandbox.eu.zuora.com/apps/services/a/",
|
40
37
|
"Production" => "https://eu.zuora.com/apps/services/a/",
|
41
38
|
"Performance" => "https://pt1.eu.zuora.com/apps/services/a/",
|
42
|
-
"Services" => "https://services347.eu.zuora.com/apps/services/a/"}
|
39
|
+
"Services" => "https://services347.eu.zuora.com/apps/services/a/"},
|
40
|
+
"NA" => {"Sandbox" => "https://sandbox.na.zuora.com/apps/services/a/",
|
41
|
+
"Production" => "https://na.zuora.com/apps/services/a/",
|
42
|
+
"Performance" => "https://pt1.na.zuora.com/apps/services/a/",
|
43
|
+
"Services" => "https://services347.na.zuora.com/apps/services/a/"}
|
43
44
|
}
|
44
45
|
end
|
45
46
|
|
46
47
|
def update_environment
|
47
48
|
if !self.url.blank?
|
48
49
|
env_path = self.url.split('https://').last.split('.zuora.com').first
|
49
|
-
self.region = self.url.include?("eu.") ? "EU" : "US"
|
50
|
+
self.region = self.url.include?("eu.") ? "EU" : self.url.include?("na.") ? "NA" : "US"
|
50
51
|
if env_path == 'apisandbox' || self.url.include?('sandbox')
|
51
52
|
self.environment = 'Sandbox'
|
52
|
-
elsif env_path == 'www' || env_path == 'api' || self.url.include?('tls10.zuora.com') || self.url.include?('origin-www.zuora.com') || self.url.include?('zforsf.zuora.com') || self.url.include?('https://zuora.com') || self.url.include?('eu.zuora.com')
|
53
|
+
elsif env_path == 'www' || env_path == 'api' || self.url.include?('tls10.zuora.com') || self.url.include?('origin-www.zuora.com') || self.url.include?('zforsf.zuora.com') || self.url.include?('https://zuora.com') || self.url.include?('eu.zuora.com') || self.url.include?('https://na.zuora.com')
|
53
54
|
self.environment = 'Production'
|
54
55
|
elsif env_path.include?('service') || env_path.include?('ep-edge')
|
55
56
|
self.environment = 'Services'
|
56
57
|
elsif env_path.include?('pt')
|
57
58
|
self.environment = 'Performance'
|
58
|
-
elsif env_path.include?('
|
59
|
+
elsif env_path.include?('staging2') || env_path.include?('staging1')
|
60
|
+
self.region = 'US'
|
59
61
|
self.environment = 'Staging'
|
60
62
|
else
|
61
63
|
self.environment = 'Unknown'
|
@@ -69,9 +71,9 @@ module ZuoraAPI
|
|
69
71
|
|
70
72
|
def rest_endpoint(url="")
|
71
73
|
if self.environment == 'Sandbox'
|
72
|
-
return self.region == "US" ? "https://rest.apisandbox.zuora.com/v1/".concat(url) : "https://rest.sandbox.eu.zuora.com/v1/".concat(url)
|
74
|
+
return self.region == "US" ? "https://rest.apisandbox.zuora.com/v1/".concat(url) : self.region == "EU" ? "https://rest.sandbox.eu.zuora.com/v1/".concat(url) : "https://rest.sandbox.na.zuora.com/v1/".concat(url)
|
73
75
|
elsif self.environment == 'Production'
|
74
|
-
return self.region == "US" ? "https://rest.zuora.com/v1/".concat(url) : "https://rest.eu.zuora.com/v1/".concat(url)
|
76
|
+
return self.region == "US" ? "https://rest.zuora.com/v1/".concat(url) : self.region == "EU" ? "https://rest.eu.zuora.com/v1/".concat(url) : "https://rest.na.zuora.com/v1/".concat(url)
|
75
77
|
elsif self.environment == 'Services'
|
76
78
|
return self.url.split('/')[0..2].join('/').concat('/apps/v1/').concat(url)
|
77
79
|
elsif self.environment == 'Performance'
|
@@ -89,130 +91,45 @@ module ZuoraAPI
|
|
89
91
|
return self.wsdl_number > 68 ? '%Y-%m-%d' : '%Y-%m-%dT%H:%M:%S'
|
90
92
|
end
|
91
93
|
|
92
|
-
def new_session(debug: false)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
94
|
+
def new_session(auth_type: :basic, debug: false)
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_session(prefix: false, auth_type: :basic)
|
98
|
+
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}")
|
99
|
+
case auth_type
|
100
|
+
when :basic
|
101
|
+
if self.current_session.blank?
|
102
|
+
Rails.logger.debug("Create new session")
|
103
|
+
case self.class.to_s
|
104
|
+
when 'ZuoraAPI::Oauth'
|
105
|
+
if self.bearer_token.blank? || self.oauth_expired?
|
106
|
+
self.new_session(auth_type: :bearer)
|
105
107
|
end
|
108
|
+
self.get_z_session
|
109
|
+
when 'ZuoraAPI::Basic'
|
110
|
+
self.new_session(auth_type: :basic)
|
106
111
|
else
|
107
|
-
|
108
|
-
xml['SOAP-ENV'].Body do
|
109
|
-
xml['api'].login do
|
110
|
-
xml['api'].username self.username
|
111
|
-
xml['api'].password self.password
|
112
|
-
xml['api'].entityId self.entity_id if !self.entity_id.blank?
|
113
|
-
end
|
114
|
-
end
|
112
|
+
raise "No Zuora Login Specified"
|
115
113
|
end
|
116
114
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
@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)
|
125
|
-
@output_xml = Nokogiri::XML(@response_query.body)
|
126
|
-
Rails.logger.debug('Connect') {"Response SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
127
|
-
|
128
|
-
|
129
|
-
if !@response_query.success?
|
130
|
-
self.current_session = nil
|
131
|
-
if @output_xml.namespaces.size > 0 && @output_xml.xpath('//soapenv:Fault').size > 0
|
132
|
-
self.current_error = @output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
133
|
-
if self.current_error.include?('deactivated')
|
134
|
-
self.status = 'Deactivated'
|
135
|
-
self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
|
136
|
-
self.errors[:username] = self.current_error
|
137
|
-
elsif self.current_error.include?('inactive')
|
138
|
-
self.status = 'Inactive'
|
139
|
-
self.current_error = 'Inactive user login, please check with Zuora tenant administrator'
|
140
|
-
self.errors[:username] = self.current_error
|
141
|
-
elsif self.current_error.include?("invalid username or password") || self.current_error.include?("Invalid login. User name and password do not match.")
|
142
|
-
self.status = 'Invalid Login'
|
143
|
-
self.current_error = 'Invalid login, please check username and password or URL endpoint'
|
144
|
-
self.errors[:username] = self.current_error
|
145
|
-
self.errors[:password] = self.current_error
|
146
|
-
elsif self.current_error.include?('unsupported version')
|
147
|
-
self.status = 'Unsupported API Version'
|
148
|
-
self.current_error = 'Unsupported API version, please verify URL endpoint'
|
149
|
-
self.errors[:url] = self.current_error
|
150
|
-
elsif self.current_error.include?('invalid api version')
|
151
|
-
self.status = 'Invalid API Version'
|
152
|
-
self.current_error = 'Invalid API version, please verify URL endpoint'
|
153
|
-
self.errors[:url] = self.current_error
|
154
|
-
elsif self.current_error.include?('invalid session')
|
155
|
-
self.status = 'Invalid Session'
|
156
|
-
self.current_error = 'Session invalid, please update session and verify URL endpoint'
|
157
|
-
self.errors[:session] = self.current_error
|
158
|
-
elsif self.current_error.include?('Your IP address')
|
159
|
-
self.status = 'Restricted IP'
|
160
|
-
self.current_error = 'IP restricted, contact Zuora tenant administrator and remove IP restriction'
|
161
|
-
self.errors[:base] = self.current_error
|
162
|
-
elsif self.current_error.include?('This account has been locked')
|
163
|
-
self.status = 'Locked'
|
164
|
-
self.current_error = 'Locked user login, please wait or navigate to Zuora to unlock user'
|
165
|
-
self.errors[:username] = self.current_error
|
166
|
-
else
|
167
|
-
self.status = 'Unknown'
|
168
|
-
self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
|
169
|
-
self.errors[:base] = self.current_error
|
115
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
116
|
+
return prefix ? "ZSession #{self.current_session}" : self.current_session.to_s
|
117
|
+
when :bearer
|
118
|
+
case self.class.to_s
|
119
|
+
when 'ZuoraAPI::Oauth'
|
120
|
+
if self.bearer_token.blank? || self.oauth_expired?
|
121
|
+
self.new_session(auth_type: :bearer)
|
170
122
|
end
|
171
|
-
|
172
|
-
|
173
|
-
self.status = 'No Service'
|
123
|
+
when 'ZuoraAPI::Basic'
|
124
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}")
|
174
125
|
end
|
175
|
-
|
176
|
-
|
177
|
-
if (self.password.blank? && self.current_session.present?)
|
178
|
-
self.current_session = self.current_session
|
179
|
-
self.username = @output_xml.xpath('//ns1:Username', 'ns1' =>'http://api.zuora.com/').text if self.username.blank?
|
180
|
-
|
181
|
-
#Username & password combo
|
182
|
-
elsif (self.password.present? && self.username.present?)
|
183
|
-
retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
|
184
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
|
185
|
-
self.current_session = retrieved_session
|
186
|
-
end
|
187
|
-
|
188
|
-
self.current_error = nil
|
189
|
-
self.status = 'Active'
|
126
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
127
|
+
return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s
|
190
128
|
end
|
191
|
-
return self.status
|
192
|
-
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
|
193
|
-
if !(tries -= 1).zero?
|
194
|
-
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
195
|
-
sleep(self.timeout_sleep)
|
196
|
-
retry
|
197
|
-
else
|
198
|
-
self.current_error = "Request timed out. Try again"
|
199
|
-
self.status = 'Timeout'
|
200
|
-
return self.status
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def get_session
|
205
|
-
Rails.logger.debug("Create new session") if self.current_session.blank?
|
206
|
-
self.new_session if self.current_session.blank?
|
207
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if self.status != 'Active'
|
208
|
-
return self.current_session
|
209
129
|
end
|
210
130
|
|
211
|
-
def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug:
|
131
|
+
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)
|
212
132
|
tries ||= 2
|
213
|
-
error_type = ""
|
214
|
-
start_time = Time.now
|
215
|
-
|
216
133
|
xml = Nokogiri::XML::Builder.new do |xml|
|
217
134
|
xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/",
|
218
135
|
"xmlns:#{ns2}" => "http://object.api.zuora.com/",
|
@@ -221,7 +138,7 @@ module ZuoraAPI
|
|
221
138
|
"xmlns:#{ns1}" => "http://api.zuora.com/") do
|
222
139
|
xml['SOAP-ENV'].Header do
|
223
140
|
xml["#{ns1}"].SessionHeader do
|
224
|
-
xml["#{ns1}"].session self.get_session
|
141
|
+
xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic)
|
225
142
|
end
|
226
143
|
if single_transaction
|
227
144
|
xml["#{ns1}"].CallOptions do
|
@@ -242,19 +159,17 @@ module ZuoraAPI
|
|
242
159
|
|
243
160
|
input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
244
161
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
245
|
-
Rails.logger.debug(
|
162
|
+
Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
246
163
|
|
247
164
|
response = HTTParty.post(self.url,:body => xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => timeout)
|
248
165
|
output_xml = Nokogiri::XML(response.body)
|
249
|
-
Rails.logger.debug(
|
166
|
+
Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug
|
250
167
|
|
251
168
|
raise_errors(type: :SOAP, body: output_xml, response: response)
|
252
|
-
|
253
169
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
254
|
-
error_type = "#{ex.class}"
|
255
170
|
if !(tries -= 1).zero? && z_session
|
256
|
-
Rails.logger.debug
|
257
|
-
self.new_session
|
171
|
+
Rails.logger.debug("SOAP Call - Session Invalid")
|
172
|
+
self.new_session(auth_type: :basic)
|
258
173
|
retry
|
259
174
|
else
|
260
175
|
if errors.include?(ex.class)
|
@@ -264,37 +179,23 @@ module ZuoraAPI
|
|
264
179
|
end
|
265
180
|
end
|
266
181
|
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
267
|
-
error_type = "#{ex.class}"
|
268
182
|
if errors.include?(ex.class)
|
269
183
|
raise ex
|
270
184
|
else
|
271
185
|
return output_xml, input_xml, response
|
272
186
|
end
|
273
187
|
rescue Net::OpenTimeout, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
|
274
|
-
error_type = "#{ex.class}"
|
275
188
|
if !(tries -= 1).zero? && timeout_retry
|
276
|
-
Rails.logger.info
|
189
|
+
Rails.logger.info("SOAP Call - #{ex.class} Timed out will retry after 5 seconds")
|
277
190
|
sleep(self.timeout_sleep)
|
278
191
|
retry
|
279
192
|
else
|
280
193
|
raise ex
|
281
194
|
end
|
282
195
|
rescue => ex
|
283
|
-
error_type = "#{ex.class}"
|
284
196
|
raise ex
|
285
197
|
else
|
286
198
|
return output_xml, input_xml, response
|
287
|
-
ensure
|
288
|
-
# Writing to telegraf
|
289
|
-
begin
|
290
|
-
end_time = Time.now
|
291
|
-
response_time = end_time - start_time
|
292
|
-
status_code = response.code if response
|
293
|
-
endpoint_name = url.present? ? URI(url).host : url
|
294
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
|
295
|
-
rescue => ex
|
296
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
297
|
-
end
|
298
199
|
end
|
299
200
|
|
300
201
|
def raise_errors(type: :SOAP, body: nil, response: nil)
|
@@ -344,7 +245,11 @@ module ZuoraAPI
|
|
344
245
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code)
|
345
246
|
end
|
346
247
|
elsif error.class == Array
|
347
|
-
|
248
|
+
if error[0].include?("LOCK_COMPETITION") && error.count == 1
|
249
|
+
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)
|
250
|
+
else
|
251
|
+
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)
|
252
|
+
end
|
348
253
|
end
|
349
254
|
end
|
350
255
|
|
@@ -357,6 +262,17 @@ module ZuoraAPI
|
|
357
262
|
messages_array = (body["reasons"] || []).map {|error| error['message']}.compact
|
358
263
|
codes_array = (body["reasons"] || []).map {|error| error['code']}.compact
|
359
264
|
|
265
|
+
if body['message'] == "No bearer token" && response.code == 400
|
266
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new()
|
267
|
+
end
|
268
|
+
|
269
|
+
if body.dig("reasons").nil? ? false : body.dig("reasons")[0].dig("code") == 90000020
|
270
|
+
raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", body, response.code)
|
271
|
+
end
|
272
|
+
|
273
|
+
if body['error'] == 'Unauthorized' && body['status'] = 401
|
274
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
|
275
|
+
end
|
360
276
|
#Authentication failed
|
361
277
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401
|
362
278
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
|
@@ -470,14 +386,10 @@ module ZuoraAPI
|
|
470
386
|
def describe_call(object = nil)
|
471
387
|
tries ||= 2
|
472
388
|
|
473
|
-
error_type = ""
|
474
|
-
start_time = Time.now
|
475
|
-
|
476
|
-
self.get_session
|
477
389
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
478
390
|
url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
|
479
391
|
headers = !self.entity_id.blank? ? {"entityId" => self.entity_id, 'Content-Type' => "text/xml; charset=utf-8"} : {'Content-Type' => "text/xml; charset=utf-8"}
|
480
|
-
response = HTTParty.get(url,
|
392
|
+
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
|
481
393
|
|
482
394
|
output_xml = Nokogiri::XML(response.body)
|
483
395
|
des_hash = Hash.new
|
@@ -509,55 +421,48 @@ module ZuoraAPI
|
|
509
421
|
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
|
510
422
|
end
|
511
423
|
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
|
512
|
-
error_type = "#{ex.class}"
|
513
424
|
if !(tries -= 1).zero?
|
514
|
-
Rails.logger.info
|
425
|
+
Rails.logger.info("Describe - #{ex.class} Timed out will retry after 5 seconds")
|
515
426
|
sleep(self.timeout_sleep)
|
516
427
|
retry
|
517
428
|
else
|
518
429
|
raise ex
|
519
430
|
end
|
520
431
|
rescue => ex
|
521
|
-
error_type = "#{ex.class}"
|
522
432
|
raise ex
|
523
433
|
else
|
524
434
|
return des_hash
|
525
|
-
ensure
|
526
|
-
# Writing to telegraf
|
527
|
-
begin
|
528
|
-
end_time = Time.now
|
529
|
-
response_time = end_time - start_time
|
530
|
-
status_code = response.code if response
|
531
|
-
endpoint_name = url.present? ? URI(url).host : url
|
532
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET")
|
533
|
-
rescue => ex
|
534
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
535
|
-
end
|
536
435
|
end
|
537
436
|
|
538
|
-
def rest_call(method: :get, body:
|
437
|
+
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)
|
539
438
|
tries ||= 2
|
540
439
|
headers["entityId"] = self.entity_id if !self.entity_id.blank?
|
541
440
|
raise "Method not supported, supported methods include: :get, :post, :put, :delete, :patch, :head, :options" if ![:get, :post, :put, :delete, :patch, :head, :options].include?(method)
|
441
|
+
|
442
|
+
authentication_headers = z_session ? {"Authorization" => self.get_session(prefix: true, auth_type: session_type) } : {}
|
443
|
+
headers = {'Content_Type' => "application/json; charset=utf-8"}.merge(headers).merge(authentication_headers)
|
542
444
|
|
543
|
-
|
544
|
-
|
545
|
-
response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: {'Content-Type' => "application/json; charset=utf-8"}.merge(z_session ? {"Authorization" => "ZSession #{self.get_session}"} : {}).merge(headers), timeout: timeout).perform
|
546
|
-
|
445
|
+
response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: headers, timeout: timeout).perform
|
446
|
+
Rails.logger.debug("Response Code: #{response.code}") if debug
|
547
447
|
begin
|
548
448
|
output_json = JSON.parse(response.body)
|
549
449
|
rescue JSON::ParserError => ex
|
550
450
|
output_json = {}
|
551
451
|
end
|
552
|
-
Rails.logger.debug(
|
452
|
+
Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present?
|
553
453
|
|
554
454
|
raise_errors(type: :JSON, body: output_json, response: response)
|
555
|
-
|
455
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
456
|
+
if self.class.to_s == 'ZuoraAPI::Oauth'
|
457
|
+
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)
|
458
|
+
else
|
459
|
+
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
460
|
+
raise ex
|
461
|
+
end
|
556
462
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
557
|
-
error_type = "#{ex.class}"
|
558
463
|
if !(tries -= 1).zero? && z_session
|
559
|
-
Rails.logger.debug
|
560
|
-
self.new_session
|
464
|
+
Rails.logger.debug("Rest Call - Session Invalid")
|
465
|
+
self.new_session(auth_type: session_type)
|
561
466
|
retry
|
562
467
|
else
|
563
468
|
if errors.include?(ex.class)
|
@@ -567,37 +472,25 @@ module ZuoraAPI
|
|
567
472
|
end
|
568
473
|
end
|
569
474
|
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
570
|
-
error_type = "#{ex.class}"
|
571
475
|
if errors.include?(ex.class)
|
572
476
|
raise ex
|
573
477
|
else
|
574
478
|
return [output_json, response]
|
575
479
|
end
|
480
|
+
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
481
|
+
raise ex
|
576
482
|
rescue Net::OpenTimeout, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
|
577
|
-
error_type = "#{ex.class}"
|
578
483
|
if !(tries -= 1).zero? && timeout_retry
|
579
|
-
Rails.logger.info
|
484
|
+
Rails.logger.info("Rest Call - #{ex.class} Timed out will retry after 5 seconds")
|
580
485
|
sleep(self.timeout_sleep)
|
581
486
|
retry
|
582
487
|
else
|
583
488
|
raise ex
|
584
489
|
end
|
585
490
|
rescue => ex
|
586
|
-
error_type = "#{ex.class}"
|
587
491
|
raise ex
|
588
492
|
else
|
589
493
|
return [output_json, response]
|
590
|
-
ensure
|
591
|
-
# Writing to telegraf
|
592
|
-
begin
|
593
|
-
end_time = Time.now
|
594
|
-
response_time = end_time - start_time
|
595
|
-
status_code = response.code if response
|
596
|
-
endpoint_name = url.present? ? URI(url).host : url
|
597
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "#{method.upcase}")
|
598
|
-
rescue => ex
|
599
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
600
|
-
end
|
601
494
|
end
|
602
495
|
|
603
496
|
def update_create_tenant
|
@@ -653,16 +546,13 @@ module ZuoraAPI
|
|
653
546
|
require 'fileutils'
|
654
547
|
FileUtils.mkdir_p(file_path) unless File.exists?(file_path)
|
655
548
|
|
656
|
-
error_type = ""
|
657
|
-
start_time = Time.now
|
658
|
-
|
659
549
|
begin
|
660
550
|
status_code = nil
|
661
551
|
uri = URI.parse(url)
|
662
552
|
http = Net::HTTP.new(uri.host, uri.port)
|
663
553
|
http.read_timeout = timeout #Seconds
|
664
554
|
http.use_ssl = true if uri.scheme.downcase == 'https'
|
665
|
-
headers = headers.merge({"Authorization" =>
|
555
|
+
headers = headers.merge({"Authorization" => self.get_session(prefix: true)}) if z_session
|
666
556
|
|
667
557
|
response_save = nil
|
668
558
|
http.request_get(uri.path, headers) do |response|
|
@@ -753,40 +643,26 @@ module ZuoraAPI
|
|
753
643
|
end
|
754
644
|
|
755
645
|
file_handle.close
|
756
|
-
Rails.logger.
|
646
|
+
Rails.logger.debug("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb")
|
757
647
|
|
758
648
|
return file_handle
|
759
649
|
end
|
760
650
|
end
|
761
651
|
rescue Exception => e
|
762
|
-
|
763
|
-
Rails.logger.fatal(
|
764
|
-
Rails.logger.fatal('GetFile') {"Download Failed: #{e.backtrace.join("\n")}"}
|
652
|
+
Rails.logger.fatal("Download Failed: #{response_save} - #{e.class} : #{e.message}")
|
653
|
+
Rails.logger.fatal("Download Failed: #{e.backtrace.join("\n")}")
|
765
654
|
raise
|
766
|
-
ensure
|
767
|
-
# Writing to telegraf
|
768
|
-
begin
|
769
|
-
end_time = Time.now
|
770
|
-
response_time = end_time - start_time
|
771
|
-
status_code = response.code if response
|
772
|
-
endpoint_name = url.present? ? URI(url).host : url
|
773
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET")
|
774
|
-
rescue => ex
|
775
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
776
|
-
end
|
777
655
|
end
|
778
656
|
end
|
779
657
|
|
780
658
|
def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
|
781
|
-
|
782
|
-
|
783
|
-
Rails.logger.info('Export') {"Build export"}
|
784
|
-
Rails.logger.debug('Export query') {"#{query}"}
|
659
|
+
Rails.logger.debug("Build export")
|
660
|
+
Rails.logger.debug("#{query}")
|
785
661
|
request = Nokogiri::XML::Builder.new do |xml|
|
786
662
|
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
|
787
663
|
xml['SOAP-ENV'].Header do
|
788
664
|
xml['ns1'].SessionHeader do
|
789
|
-
xml['ns1'].session self.
|
665
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
|
790
666
|
end
|
791
667
|
end
|
792
668
|
xml['SOAP-ENV'].Body do
|
@@ -803,24 +679,9 @@ module ZuoraAPI
|
|
803
679
|
end
|
804
680
|
end
|
805
681
|
|
806
|
-
|
807
|
-
|
808
|
-
rescue => e
|
809
|
-
error_type = "#{e.class}"
|
810
|
-
ensure
|
811
|
-
begin
|
812
|
-
end_time = Time.now
|
813
|
-
response_time = end_time - start_time
|
814
|
-
status_code = response.code if response
|
815
|
-
endpoint_name = url.present? ? URI(url).host : url
|
816
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
|
817
|
-
rescue => ex
|
818
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
819
|
-
end
|
820
|
-
end
|
821
|
-
|
682
|
+
response_query = HTTParty.post(self.url, body: request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8"}, :timeout => 120)
|
683
|
+
|
822
684
|
output_xml = Nokogiri::XML(response_query.body)
|
823
|
-
|
824
685
|
raise 'Export Creation Unsuccessful : ' + output_xml.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text if output_xml.xpath('//ns1:Success', 'ns1' =>'http://api.zuora.com/').text != "true"
|
825
686
|
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
826
687
|
|
@@ -828,7 +689,7 @@ module ZuoraAPI
|
|
828
689
|
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
|
829
690
|
xml['SOAP-ENV'].Header do
|
830
691
|
xml['ns1'].SessionHeader do
|
831
|
-
xml['ns1'].session self.
|
692
|
+
xml['ns1'].session self.get_session(prefix: false, auth_type: :basic)
|
832
693
|
end
|
833
694
|
end
|
834
695
|
xml['SOAP-ENV'].Body do
|
@@ -840,39 +701,21 @@ module ZuoraAPI
|
|
840
701
|
end
|
841
702
|
result = 'Waiting'
|
842
703
|
|
843
|
-
start_time = Time.now
|
844
|
-
error_type = ""
|
845
|
-
|
846
704
|
while result != "Completed"
|
847
705
|
sleep 3
|
848
|
-
|
849
|
-
|
850
|
-
rescue => e
|
851
|
-
error_type = "#{e.class}"
|
852
|
-
end
|
706
|
+
response_query = HTTParty.post(self.url, body: confirmRequest.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: {'Content-Type' => "application/json; charset=utf-8"}, :timeout => 120)
|
707
|
+
|
853
708
|
output_xml = Nokogiri::XML(response_query.body)
|
854
709
|
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
855
710
|
status_code = response_query.code if response_query
|
856
711
|
raise "Export Creation Unsuccessful : #{output_xml.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text}" if result.blank? || result == "Failed"
|
857
712
|
end
|
858
713
|
|
859
|
-
begin
|
860
|
-
end_time = Time.now
|
861
|
-
response_time = end_time - start_time
|
862
|
-
status_code = response.code if response
|
863
|
-
endpoint_name = url.present? ? URI(url).host : url
|
864
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
|
865
|
-
rescue => ex
|
866
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
867
|
-
end
|
868
|
-
|
869
|
-
|
870
|
-
|
871
714
|
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
872
|
-
Rails.logger.
|
715
|
+
Rails.logger.debug('=====> Export finished')
|
873
716
|
export_file = get_file(:url => self.fileURL(file_id))
|
874
717
|
export_file_path = export_file.path
|
875
|
-
Rails.logger.
|
718
|
+
Rails.logger.debug("=====> Export path #{export_file.path}")
|
876
719
|
|
877
720
|
if extract && zip
|
878
721
|
require "zip"
|
@@ -888,7 +731,7 @@ module ZuoraAPI
|
|
888
731
|
end
|
889
732
|
|
890
733
|
def query(query, parse = false)
|
891
|
-
Rails.logger.debug(
|
734
|
+
Rails.logger.debug("Querying Zuora for #{query}")
|
892
735
|
output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
|
893
736
|
xml['ns1'].query do
|
894
737
|
xml['ns1'].queryString query
|
@@ -904,35 +747,17 @@ module ZuoraAPI
|
|
904
747
|
end
|
905
748
|
|
906
749
|
def createJournalRun(call)
|
907
|
-
error_type = ""
|
908
|
-
start_time = Time.now
|
909
|
-
|
910
750
|
url = rest_endpoint("/journal-runs")
|
911
751
|
uri = URI(url)
|
912
752
|
req = Net::HTTP::Post.new(uri,initheader = {'Content-Type' =>'application/json'})
|
913
|
-
req
|
753
|
+
req["Authorization"] = self.get_session(prefix: true)
|
914
754
|
req.body = call
|
915
755
|
|
916
|
-
|
917
|
-
|
918
|
-
http.request req
|
919
|
-
end
|
920
|
-
rescue => e
|
921
|
-
error_type = "#{e.class}"
|
922
|
-
ensure
|
923
|
-
begin
|
924
|
-
end_time = Time.now
|
925
|
-
response_time = end_time - start_time
|
926
|
-
status_code = response.code if response
|
927
|
-
endpoint_name = url.present? ? URI(url).host : url
|
928
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST")
|
929
|
-
rescue => ex
|
930
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
931
|
-
end
|
756
|
+
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
757
|
+
http.request req
|
932
758
|
end
|
933
|
-
|
934
|
-
Rails.logger.debug(
|
935
|
-
#{response.body}"}
|
759
|
+
|
760
|
+
Rails.logger.debug("Response #{response.code} #{response.message}: #{response.body}")
|
936
761
|
|
937
762
|
result = JSON.parse(response.body)
|
938
763
|
if result["success"]
|
@@ -940,44 +765,24 @@ module ZuoraAPI
|
|
940
765
|
return jrNumber
|
941
766
|
else
|
942
767
|
message = result["reasons"][0]["message"]
|
943
|
-
Rails.logger.
|
768
|
+
Rails.logger.error("Journal Run failed with message #{message}")
|
944
769
|
return result
|
945
770
|
end
|
946
771
|
|
947
772
|
end
|
948
773
|
|
949
774
|
def checkJRStatus(jrNumber)
|
950
|
-
|
951
|
-
|
952
|
-
Rails.logger.info('Journal Run') {"Check for completion"}
|
953
|
-
|
954
|
-
start_time = Time.now
|
955
|
-
|
775
|
+
Rails.logger.info("Check for completion")
|
956
776
|
url = rest_endpoint("/journal-runs/#{jrNumber}")
|
957
777
|
uri = URI(url)
|
958
778
|
req = Net::HTTP::Get.new(uri,initheader = {'Content-Type' =>'application/json'})
|
959
|
-
req
|
779
|
+
req["Authorization"] = self.get_session(prefix: true)
|
960
780
|
|
961
|
-
|
962
|
-
|
963
|
-
http.request req
|
964
|
-
end
|
965
|
-
rescue => e
|
966
|
-
error_type = "#{e.class}"
|
967
|
-
ensure
|
968
|
-
begin
|
969
|
-
end_time = Time.now
|
970
|
-
response_time = end_time - start_time
|
971
|
-
status_code = response.code if response
|
972
|
-
endpoint_name = url.present? ? URI(url).host : url
|
973
|
-
::MetricsHelpers::MetricsHelpers.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET")
|
974
|
-
rescue => ex
|
975
|
-
Rails.logger.warn("Metric Failure: #{ex.class} - #{ex.message}")
|
976
|
-
end
|
781
|
+
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
782
|
+
http.request req
|
977
783
|
end
|
978
784
|
|
979
785
|
result = JSON.parse(response.body)
|
980
|
-
|
981
786
|
if result["success"]
|
982
787
|
if !(result["status"].eql? "Completed")
|
983
788
|
sleep(20.seconds)
|
@@ -985,7 +790,7 @@ module ZuoraAPI
|
|
985
790
|
return result["status"]
|
986
791
|
else
|
987
792
|
message = result["reasons"][0]["message"]
|
988
|
-
Rails.logger.info(
|
793
|
+
Rails.logger.info("Checking status of journal run failed with message #{message}")
|
989
794
|
end
|
990
795
|
return "failure"
|
991
796
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module ZuoraAPI
|
2
|
+
class Basic < Login
|
3
|
+
attr_accessor :username, :password
|
4
|
+
def initialize(username: nil, password: nil, **keyword_args)
|
5
|
+
@username = username
|
6
|
+
@password = password
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def new_session(auth_type: :basic, debug: false)
|
11
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
|
12
|
+
tries ||= 2
|
13
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
14
|
+
xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' =>"http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:api' => "http://api.zuora.com/" ) do
|
15
|
+
xml['SOAP-ENV'].Header
|
16
|
+
xml['SOAP-ENV'].Body do
|
17
|
+
xml['api'].login do
|
18
|
+
xml['api'].username self.username
|
19
|
+
xml['api'].password self.password
|
20
|
+
xml['api'].entityId self.entity_id if !self.entity_id.blank?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
27
|
+
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
28
|
+
Rails.logger.debug('Connect') {"Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
29
|
+
|
30
|
+
@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)
|
31
|
+
@output_xml = Nokogiri::XML(@response_query.body)
|
32
|
+
Rails.logger.debug('Connect') {"Response SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
33
|
+
|
34
|
+
if !@response_query.success?
|
35
|
+
self.current_session = nil
|
36
|
+
if @output_xml.namespaces.size > 0 && @output_xml.xpath('//soapenv:Fault').size > 0
|
37
|
+
self.current_error = @output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
|
38
|
+
if self.current_error.include?('deactivated')
|
39
|
+
self.status = 'Deactivated'
|
40
|
+
self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
|
41
|
+
self.errors[:username] = self.current_error
|
42
|
+
elsif self.current_error.include?('inactive')
|
43
|
+
self.status = 'Inactive'
|
44
|
+
self.current_error = 'Inactive user login, please check with Zuora tenant administrator'
|
45
|
+
self.errors[:username] = self.current_error
|
46
|
+
elsif self.current_error.include?("invalid username or password") || self.current_error.include?("Invalid login. User name and password do not match.")
|
47
|
+
self.status = 'Invalid Login'
|
48
|
+
self.current_error = 'Invalid login, please check username and password or URL endpoint'
|
49
|
+
self.errors[:username] = self.current_error
|
50
|
+
self.errors[:password] = self.current_error
|
51
|
+
elsif self.current_error.include?('unsupported version')
|
52
|
+
self.status = 'Unsupported API Version'
|
53
|
+
self.current_error = 'Unsupported API version, please verify URL endpoint'
|
54
|
+
self.errors[:url] = self.current_error
|
55
|
+
elsif self.current_error.include?('invalid api version')
|
56
|
+
self.status = 'Invalid API Version'
|
57
|
+
self.current_error = 'Invalid API version, please verify URL endpoint'
|
58
|
+
self.errors[:url] = self.current_error
|
59
|
+
elsif self.current_error.include?('invalid session')
|
60
|
+
self.status = 'Invalid Session'
|
61
|
+
self.current_error = 'Session invalid, please update session and verify URL endpoint'
|
62
|
+
self.errors[:session] = self.current_error
|
63
|
+
elsif self.current_error.include?('Your IP address')
|
64
|
+
self.status = 'Restricted IP'
|
65
|
+
self.current_error = 'IP restricted, contact Zuora tenant administrator and remove IP restriction'
|
66
|
+
self.errors[:base] = self.current_error
|
67
|
+
elsif self.current_error.include?('This account has been locked')
|
68
|
+
self.status = 'Locked'
|
69
|
+
self.current_error = 'Locked user login, please wait or navigate to Zuora to unlock user'
|
70
|
+
self.errors[:username] = self.current_error
|
71
|
+
else
|
72
|
+
self.status = 'Unknown'
|
73
|
+
self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
|
74
|
+
self.errors[:base] = self.current_error
|
75
|
+
end
|
76
|
+
|
77
|
+
else
|
78
|
+
self.status = 'Unknown'
|
79
|
+
self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
|
80
|
+
self.errors[:base] = self.current_error
|
81
|
+
end
|
82
|
+
else
|
83
|
+
#Username & password combo
|
84
|
+
if (self.password.present? && self.username.present?)
|
85
|
+
retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
|
86
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
|
87
|
+
self.current_session = retrieved_session
|
88
|
+
end
|
89
|
+
end
|
90
|
+
return self.status
|
91
|
+
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
|
92
|
+
if !(tries -= 1).zero?
|
93
|
+
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
94
|
+
sleep(self.timeout_sleep)
|
95
|
+
retry
|
96
|
+
else
|
97
|
+
self.current_error = "Request timed out. Try again"
|
98
|
+
self.status = 'Timeout'
|
99
|
+
return self.status
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module ZuoraAPI
|
2
|
+
class Oauth < Login
|
3
|
+
attr_accessor :oauth_client_id, :oauth_secret, :bearer_token, :oauth_session_expires_at
|
4
|
+
|
5
|
+
def initialize(oauth_client_id: nil, oauth_secret: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args)
|
6
|
+
self.oauth_client_id = oauth_client_id
|
7
|
+
self.oauth_secret = oauth_secret
|
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
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def new_session(auth_type: nil)
|
15
|
+
if auth_type == :bearer
|
16
|
+
get_bearer_token()
|
17
|
+
elsif auth_type == :basic
|
18
|
+
get_bearer_token() if self.oauth_expired?
|
19
|
+
get_z_session()
|
20
|
+
else
|
21
|
+
get_bearer_token()
|
22
|
+
get_z_session()
|
23
|
+
end
|
24
|
+
return self.status
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_z_session(debug: false)
|
28
|
+
tries ||= 2
|
29
|
+
headers = self.entity_id.present? ? {:entityId => self.entity_id } : {}
|
30
|
+
output_json, response = self.rest_call(:url => self.rest_endpoint("connections"), :session_type => :bearer, :headers => headers)
|
31
|
+
self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=')
|
32
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
33
|
+
if !(tries -= 1).zero?
|
34
|
+
Rails.logger.debug {"Session Invalid"}
|
35
|
+
self.new_session(auth_type: :bearer)
|
36
|
+
retry
|
37
|
+
else
|
38
|
+
if errors.include?(ex.class)
|
39
|
+
raise ex
|
40
|
+
else
|
41
|
+
return [output_json, response]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
45
|
+
if errors.include?(ex.class)
|
46
|
+
raise ex
|
47
|
+
else
|
48
|
+
return [output_json, response]
|
49
|
+
end
|
50
|
+
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
|
51
|
+
if !(tries -= 1).zero?
|
52
|
+
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
53
|
+
sleep(self.timeout_sleep)
|
54
|
+
retry
|
55
|
+
else
|
56
|
+
self.current_error = "Request timed out. Try again"
|
57
|
+
self.status = 'Timeout'
|
58
|
+
return self.status
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_bearer_token
|
63
|
+
tries ||= 2
|
64
|
+
output_json, response = self.rest_call(:method => :post,
|
65
|
+
:url => self.rest_endpoint.chomp('v1/').concat("oauth/token"),
|
66
|
+
:z_session => false,
|
67
|
+
:session_type => :bearer,
|
68
|
+
:headers => {"content_type" => "application/x-www-form-urlencoded"},
|
69
|
+
:body => {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"}
|
70
|
+
)
|
71
|
+
|
72
|
+
self.bearer_token = output_json["access_token"]
|
73
|
+
self.oauth_session_expires_at = Time.now.to_i + output_json["expires_in"].to_i
|
74
|
+
self.current_error = nil
|
75
|
+
self.status = 'Active'
|
76
|
+
|
77
|
+
return self.status
|
78
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
79
|
+
self.bearer_token = nil
|
80
|
+
self.oauth_session_expires_at = nil
|
81
|
+
self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
|
82
|
+
self.status = 'Invalid Login'
|
83
|
+
return self.status
|
84
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
|
85
|
+
if errors.include?(ex.class)
|
86
|
+
raise ex
|
87
|
+
else
|
88
|
+
return [output_json, response]
|
89
|
+
end
|
90
|
+
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
|
91
|
+
if !(tries -= 1).zero?
|
92
|
+
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
93
|
+
sleep(self.timeout_sleep)
|
94
|
+
retry
|
95
|
+
else
|
96
|
+
self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
|
97
|
+
self.status = 'Timeout'
|
98
|
+
return self.status
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def oauth_expired?
|
103
|
+
return (self.oauth_session_expires_at.blank? || self.bearer_token.blank?) ? true : (self.oauth_session_expires_at.to_i < Time.now.to_i)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/zuora_api/version.rb
CHANGED
data/zuora_api.gemspec
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.
|
4
|
+
version: 1.6.0
|
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: 2018-08-
|
11
|
+
date: 2018-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -131,7 +131,7 @@ dependencies:
|
|
131
131
|
version: 4.1.0
|
132
132
|
- - "<"
|
133
133
|
- !ruby/object:Gem::Version
|
134
|
-
version: '5.
|
134
|
+
version: '5.2'
|
135
135
|
type: :runtime
|
136
136
|
prerelease: false
|
137
137
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -141,7 +141,7 @@ dependencies:
|
|
141
141
|
version: 4.1.0
|
142
142
|
- - "<"
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '5.
|
144
|
+
version: '5.2'
|
145
145
|
description: Gem that provides easy integration to Zuora
|
146
146
|
email:
|
147
147
|
- connect@zuora.com
|
@@ -163,7 +163,8 @@ files:
|
|
163
163
|
- lib/zuora_api.rb
|
164
164
|
- lib/zuora_api/exceptions.rb
|
165
165
|
- lib/zuora_api/login.rb
|
166
|
-
- lib/zuora_api/
|
166
|
+
- lib/zuora_api/logins/basic.rb
|
167
|
+
- lib/zuora_api/logins/oauth.rb
|
167
168
|
- lib/zuora_api/version.rb
|
168
169
|
- zuora_api.gemspec
|
169
170
|
homepage: https://connect.zuora.com
|
@@ -1,12 +0,0 @@
|
|
1
|
-
module MetricsHelpers
|
2
|
-
|
3
|
-
class MetricsHelpers
|
4
|
-
def self.write_to_telegraf(response_time: nil, status_code: nil, endpoint_name: nil, direction: nil, error_type: nil, function_name: nil, method_name: nil)
|
5
|
-
if Gem.loaded_specs.has_key?('zuora_connect') && defined?(::ZuoraConnect::AppInstance.write_to_telegraf)
|
6
|
-
Thread.current[:appinstance].present? ? app_instance = Thread.current[:appinstance].id : app_instance = 0
|
7
|
-
ZuoraConnect::AppInstanceBase.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "app_instance": app_instance, "function_name": function_name, "method_name": method_name)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|