zuora_api 1.6.3b → 1.6.03
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 +5 -5
- data/.gitlab-ci.yml +3 -16
- data/lib/insights_api/login.rb +1 -1
- data/lib/zuora_api/exceptions.rb +0 -15
- data/lib/zuora_api/login.rb +139 -466
- data/lib/zuora_api/logins/basic.rb +3 -13
- data/lib/zuora_api/logins/oauth.rb +3 -8
- data/lib/zuora_api/version.rb +1 -1
- metadata +6 -6
- data/CHANGELOG.md +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b6080a42e4f36dd631e4f6891dcdeda528462a0b
|
4
|
+
data.tar.gz: d347833d58451c496186bd0dd089a8919a271e0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 927346daacd2e830f8e8460d18de45e9315d21cd6cb7a0f214edef3225925b5ce73a7d4d3423e6d78ebb21220c072ad3b0375d27256a7a02e6514a310ada8e11
|
7
|
+
data.tar.gz: 596e78be771998f9f8ef852d410ea407c1c9e65c8fadd8388d53bd18f97b30c1fc777f00d050f879dc91a0f343726d45073e5058cc2e626b9b953f7863b02525
|
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/lib/insights_api/login.rb
CHANGED
data/lib/zuora_api/exceptions.rb
CHANGED
@@ -86,21 +86,6 @@ module ZuoraAPI
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
class ZuoraAPITemporaryError < Error
|
90
|
-
attr_reader :code, :response
|
91
|
-
attr_writer :default_message
|
92
|
-
|
93
|
-
def initialize(message = nil,response=nil, code =nil)
|
94
|
-
@code = code
|
95
|
-
@message = message
|
96
|
-
@response = response
|
97
|
-
@default_message = "There is a temporary error with zuora system."
|
98
|
-
end
|
99
|
-
|
100
|
-
def to_s
|
101
|
-
@message || @default_message
|
102
|
-
end
|
103
|
-
end
|
104
89
|
|
105
90
|
class ZuoraAPIAuthenticationTypeError < Error
|
106
91
|
attr_reader :code, :response
|
data/lib/zuora_api/login.rb
CHANGED
@@ -4,203 +4,22 @@ require "uri"
|
|
4
4
|
|
5
5
|
module ZuoraAPI
|
6
6
|
class Login
|
7
|
-
ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown'
|
8
|
-
REGIONS = [EU = 'EU', US = 'US'
|
9
|
-
|
10
|
-
|
11
|
-
CONNECTION_EXCEPTIONS = [Net::OpenTimeout, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError]
|
12
|
-
CONNECTION_READ_EXCEPTIONS = [Net::ReadTimeout, Errno::ECONNRESET, Errno::EPIPE]
|
13
|
-
|
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
|
7
|
+
ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown' ]
|
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 :region, :url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep
|
15
11
|
|
16
12
|
def initialize(url: nil, entity_id: nil, session: nil, status: nil, **keyword_args)
|
17
|
-
|
18
|
-
|
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)
|
13
|
+
@url = url
|
14
|
+
@entity_id = entity_id
|
22
15
|
@errors = Hash.new
|
23
16
|
@current_session = session
|
24
17
|
@status = status.blank? ? "Active" : status
|
25
18
|
@user_info = Hash.new
|
26
|
-
self.update_region
|
27
19
|
self.update_environment
|
28
|
-
self.update_zconnect_provider
|
29
20
|
@timeout_sleep = 5
|
30
21
|
end
|
31
22
|
|
32
|
-
def get_identity(cookies)
|
33
|
-
zsession = cookies["ZSession"]
|
34
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
35
|
-
begin
|
36
|
-
if !zsession.blank?
|
37
|
-
response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
38
|
-
output_json = JSON.parse(response.body)
|
39
|
-
elsif !zconnect_accesstoken.blank?
|
40
|
-
code = zconnect_accesstoken.split("#!").last
|
41
|
-
encrypted_token, tenant_id = Base64.decode64(code).split(":")
|
42
|
-
begin
|
43
|
-
body = {'token' => encrypted_token}.to_json
|
44
|
-
rescue => ex
|
45
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie", {}, 400)
|
46
|
-
end
|
47
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
|
48
|
-
output_json = JSON.parse(response.body)
|
49
|
-
else
|
50
|
-
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
51
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
52
|
-
else
|
53
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
rescue JSON::ParserError => ex
|
57
|
-
output_json = {}
|
58
|
-
end
|
59
|
-
raise_errors(type: :JSON, body: output_json, response: response)
|
60
|
-
return output_json
|
61
|
-
end
|
62
|
-
|
63
|
-
def get_full_nav(cookies)
|
64
|
-
zsession = cookies["ZSession"]
|
65
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
66
|
-
begin
|
67
|
-
if !zsession.blank?
|
68
|
-
response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
69
|
-
output_json = JSON.parse(response.body)
|
70
|
-
elsif !zconnect_accesstoken.blank?
|
71
|
-
response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
|
72
|
-
output_json = JSON.parse(response.body)
|
73
|
-
else
|
74
|
-
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
75
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
76
|
-
else
|
77
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
rescue JSON::ParserError => ex
|
81
|
-
output_json = {}
|
82
|
-
end
|
83
|
-
raise_errors(type: :JSON, body: output_json, response: response)
|
84
|
-
return output_json
|
85
|
-
end
|
86
|
-
|
87
|
-
def set_nav(state, cookies)
|
88
|
-
zsession = cookies["ZSession"]
|
89
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
90
|
-
begin
|
91
|
-
if !zsession.blank?
|
92
|
-
response = HTTParty.put("https://#{self.hostname}/apps/v1/preference/navigation", :body => state.to_json, :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
93
|
-
output_json = JSON.parse(response.body)
|
94
|
-
elsif !zconnect_accesstoken.blank?
|
95
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/navigationstate", :body => state.to_json, :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
96
|
-
output_json = JSON.parse(response.body)
|
97
|
-
else
|
98
|
-
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
99
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
100
|
-
else
|
101
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
rescue JSON::ParserError => ex
|
105
|
-
output_json = {}
|
106
|
-
end
|
107
|
-
raise_errors(type: :JSON, body: output_json, response: response)
|
108
|
-
return output_json
|
109
|
-
end
|
110
|
-
|
111
|
-
def refresh_nav(cookies)
|
112
|
-
zsession = cookies["ZSession"]
|
113
|
-
zconnect_accesstoken = get_zconnect_accesstoken(cookies)
|
114
|
-
begin
|
115
|
-
if !zsession.blank?
|
116
|
-
response = HTTParty.post("https://#{self.hostname}/apps/v1/navigation/fetch", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
|
117
|
-
output_json = JSON.parse(response.body)
|
118
|
-
elsif !zconnect_accesstoken.blank?
|
119
|
-
response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/refresh-navbarcache", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
|
120
|
-
output_json = JSON.parse(response.body)
|
121
|
-
else
|
122
|
-
if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
|
123
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
|
124
|
-
else
|
125
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
rescue JSON::ParserError => ex
|
129
|
-
output_json = {}
|
130
|
-
end
|
131
|
-
raise_errors(type: :JSON, body: output_json, response: response)
|
132
|
-
return output_json
|
133
|
-
end
|
134
|
-
|
135
|
-
def get_zconnect_accesstoken(cookies)
|
136
|
-
accesstoken = nil
|
137
|
-
self.update_zconnect_provider
|
138
|
-
if !cookies[self.zconnect_provider].nil? && !cookies[self.zconnect_provider].empty?
|
139
|
-
accesstoken = cookies[self.zconnect_provider]
|
140
|
-
end
|
141
|
-
return accesstoken
|
142
|
-
end
|
143
|
-
|
144
|
-
def reporting_url(path)
|
145
|
-
map = {"US" => {"Sandbox" => "https://zconnectsandbox.zuora.com/api/rest/v1/",
|
146
|
-
"Production" => "https://zconnect.zuora.com/api/rest/v1/",
|
147
|
-
"Services"=> ""},
|
148
|
-
"EU" => {"Sandbox" => "https://zconnect.sandbox.eu.zuora.com/api/rest/v1/",
|
149
|
-
"Production" => "https://zconnect.eu.zuora.com/api/rest/v1/",
|
150
|
-
"Services"=> ""},
|
151
|
-
"NA" => {"Sandbox" => "https://zconnect.sandbox.na.zuora.com/api/rest/v1/",
|
152
|
-
"Production" => "https://zconnect.na.zuora.com/api/rest/v1/",
|
153
|
-
"Services"=> ""}
|
154
|
-
}
|
155
|
-
return map[zuora_client.region][zuora_client.environment].insert(-1, path)
|
156
|
-
end
|
157
|
-
|
158
|
-
# There are two ways to call this method. The first way is best.
|
159
|
-
# 1. Pass in cookies and optionally custom_authorities, name, and description
|
160
|
-
# 2. Pass in user_id, entity_ids, client_id, client_secret, and optionally custom_authorities, name, and description
|
161
|
-
# https://intranet.zuora.com/confluence/display/Sunburst/Create+an+OAuth+Client+through+API+Gateway#CreateanOAuthClientthroughAPIGateway-ZSession
|
162
|
-
def get_oauth_client (custom_authorities = [], info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, new_client_id: nil, new_client_secret: nil, cookies: nil)
|
163
|
-
authorization = ""
|
164
|
-
new_client_id = SecureRandom.uuid if new_client_id.blank?
|
165
|
-
new_client_secret = SecureRandom.hex(10) if new_client_secret.blank?
|
166
|
-
|
167
|
-
if !cookies.nil?
|
168
|
-
authorization = cookies["ZSession"]
|
169
|
-
authorization = "ZSession-a3N2w #{authorization}"
|
170
|
-
if entity_ids.blank? && cookies["ZuoraCurrentEntity"].present?
|
171
|
-
entity_ids = Array(cookies["ZuoraCurrentEntity"].unpack("a8a4a4a4a12").join('-'))
|
172
|
-
else
|
173
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora Entity ID not provided", {}, 400)
|
174
|
-
end
|
175
|
-
if user_id.blank? && cookies["Zuora-User-Id"].present?
|
176
|
-
user_id = cookies["Zuora-User-Id"]
|
177
|
-
else
|
178
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided", {}, 400)
|
179
|
-
end
|
180
|
-
elsif !client_id.nil? && !client_secret.nil?
|
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'})
|
182
|
-
bearer_hash = JSON.parse(bearer_response.body)
|
183
|
-
bearer_token = bearer_hash["access_token"]
|
184
|
-
authorization = "Bearer #{bearer_token}"
|
185
|
-
end
|
186
|
-
|
187
|
-
if !authorization.blank? && !user_id.blank? && !entity_ids.blank?
|
188
|
-
endpoint = self.rest_endpoint("genesis/clients")
|
189
|
-
oauth_response = HTTParty.post(endpoint, :headers => {'authorization' => authorization, 'Content-Type' => 'application/json'}, :body => {'clientId' => new_client_id, 'clientSecret' => new_client_secret, 'userId' => user_id, 'entityIds' => entity_ids, 'customAuthorities' => custom_authorities, 'additionalInformation' => {'description' => info_desc, 'name' => info_name}}.to_json)
|
190
|
-
output_json = JSON.parse(oauth_response.body)
|
191
|
-
if oauth_response.code == 201
|
192
|
-
output_json["clientSecret"] = new_client_secret
|
193
|
-
return output_json
|
194
|
-
elsif oauth_response.code == 401 && !oauth_response.message.blank?
|
195
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], {}, oauth_response.code)
|
196
|
-
else
|
197
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["error"], {}, oauth_response.code)
|
198
|
-
end
|
199
|
-
else
|
200
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Insufficient credentials provided", {}, 400)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
23
|
def self.environments
|
205
24
|
%w(Sandbox Production Services Performance Staging)
|
206
25
|
end
|
@@ -213,8 +32,7 @@ module ZuoraAPI
|
|
213
32
|
return {"US" => {"Sandbox" => "https://apisandbox.zuora.com/apps/services/a/",
|
214
33
|
"Production" => "https://www.zuora.com/apps/services/a/",
|
215
34
|
"Performance" => "https://pt1.zuora.com/apps/services/a/",
|
216
|
-
"Services" => "https://services347.zuora.com/apps/services/a/",
|
217
|
-
"Staging" => "https://staging2.zuora.com/apps/services/a/"},
|
35
|
+
"Services" => "https://services347.zuora.com/apps/services/a/"},
|
218
36
|
"EU" => {"Sandbox" => "https://sandbox.eu.zuora.com/apps/services/a/",
|
219
37
|
"Production" => "https://eu.zuora.com/apps/services/a/",
|
220
38
|
"Performance" => "https://pt1.eu.zuora.com/apps/services/a/",
|
@@ -226,119 +44,43 @@ module ZuoraAPI
|
|
226
44
|
}
|
227
45
|
end
|
228
46
|
|
229
|
-
def get_entity_id(entity_id: nil)
|
230
|
-
if entity_id.present?
|
231
|
-
entity_match = /[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}$/.match(entity_id)
|
232
|
-
if entity_match.blank?
|
233
|
-
raise "Entity length is wrong." if entity_id.length != 32
|
234
|
-
part_one, part_two, part_three, part_four, part_five = [entity_id[0..7], entity_id[8..11], entity_id[12..15], entity_id[16..19], entity_id[20..31]]
|
235
|
-
entity_id = "#{part_one}-#{part_two}-#{part_three}-#{part_four}-#{part_five}"
|
236
|
-
end
|
237
|
-
end
|
238
|
-
return entity_id
|
239
|
-
end
|
240
|
-
|
241
|
-
def update_region
|
242
|
-
if !self.hostname.blank?
|
243
|
-
if /(?<=\.|\/|^)(eu)(?=\.|\/|$)/ === self.hostname
|
244
|
-
self.region = "EU"
|
245
|
-
elsif /(?<=\.|\/|^)(na)(?=\.|\/|$)/ === self.hostname
|
246
|
-
self.region = "NA"
|
247
|
-
else
|
248
|
-
self.region = "US"
|
249
|
-
end
|
250
|
-
else # This will never happen
|
251
|
-
# raise "Can't update region because URL is blank"
|
252
|
-
self.region = "Unknown"
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
47
|
def update_environment
|
257
48
|
if !self.url.blank?
|
258
|
-
|
49
|
+
env_path = self.url.split('https://').last.split('.zuora.com').first
|
50
|
+
self.region = self.url.include?("eu.") ? "EU" : self.url.include?("na.") ? "NA" : "US"
|
51
|
+
if env_path == 'apisandbox' || self.url.include?('sandbox')
|
259
52
|
self.environment = 'Sandbox'
|
260
|
-
elsif
|
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')
|
54
|
+
self.environment = 'Production'
|
55
|
+
elsif env_path.include?('service') || env_path.include?('ep-edge')
|
261
56
|
self.environment = 'Services'
|
262
|
-
elsif
|
57
|
+
elsif env_path.include?('pt')
|
263
58
|
self.environment = 'Performance'
|
264
|
-
elsif
|
59
|
+
elsif env_path.include?('staging2') || env_path.include?('staging1')
|
60
|
+
self.region = 'US'
|
265
61
|
self.environment = 'Staging'
|
266
|
-
elsif is_prod_env
|
267
|
-
self.environment = 'Production'
|
268
62
|
else
|
269
63
|
self.environment = 'Unknown'
|
270
64
|
end
|
271
|
-
else # this will never happen
|
272
|
-
raise "Can't determine environment from blank URL"
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
def is_prod_env
|
277
|
-
is_prod = false
|
278
|
-
www_or_api = /(?<=\.|\/|^)(www|api)(?=\.|\/|$)/ === self.hostname
|
279
|
-
host_prefix_match = /(^|tls10\.|origin-www\.|zforsf\.|eu\.|na\.)(zuora\.com)/ === self.hostname
|
280
|
-
if www_or_api || host_prefix_match
|
281
|
-
is_prod = true
|
282
65
|
end
|
283
|
-
return is_prod
|
284
|
-
end
|
285
|
-
|
286
|
-
def update_zconnect_provider
|
287
|
-
region = update_region
|
288
|
-
environment = update_environment
|
289
|
-
mappings = {"US" => {"Sandbox" => "ZConnectSbx", "KubeSTG" => "ZConnectDev", "KubeDEV" => "ZConnectDev", "KubePROD" => "ZConnectDev", "Services" => "ZConnectQA", "Production" => "ZConnectProd", "Performance" => "ZConnectPT1", "Staging" => "ZConnectQA"},
|
290
|
-
"NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "ZConnectQANA", "Production" => "ZConnectProdNA", "Performance" => "ZConnectPT1NA"},
|
291
|
-
"EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "ZConnectQAEU", "Production" => "ZConnectProdEU", "Performance" => "ZConnectPT1EU"},
|
292
|
-
"Unknown" => {"Unknown" => "Unknown"}}
|
293
|
-
self.zconnect_provider = mappings[region][environment]
|
294
|
-
# raise "Can't find ZConnect Provider for #{region} region and #{environment} environment" if self.zconnect_provider.nil?
|
295
66
|
end
|
296
67
|
|
297
68
|
def aqua_endpoint(url="")
|
298
|
-
|
299
|
-
if !match.nil?
|
300
|
-
url_slash_apps_slash = match[0]
|
301
|
-
else
|
302
|
-
raise "self.url has no /apps in it"
|
303
|
-
end
|
304
|
-
return "#{url_slash_apps_slash}api/#{url}"
|
69
|
+
return "#{self.url.split("/apps").first}/apps/api/".concat(url)
|
305
70
|
end
|
306
71
|
|
307
72
|
def rest_endpoint(url="")
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
when 'NA'
|
319
|
-
endpoint = "https://rest.sandbox.na.zuora.com/v1/".concat(url)
|
320
|
-
end
|
321
|
-
when 'Production'
|
322
|
-
case self.region
|
323
|
-
when 'US'
|
324
|
-
endpoint = "https://rest.zuora.com/v1/".concat(url)
|
325
|
-
when 'EU'
|
326
|
-
endpoint = "https://rest.eu.zuora.com/v1/".concat(url)
|
327
|
-
when 'NA'
|
328
|
-
endpoint = "https://rest.na.zuora.com/v1/".concat(url)
|
329
|
-
end
|
330
|
-
when 'Performance'
|
331
|
-
endpoint = "https://rest.pt1.zuora.com/v1/".concat(url)
|
332
|
-
when 'Services'
|
333
|
-
https = /https:\/\/|http:\/\//.match(self.url)[0]
|
334
|
-
host = self.hostname
|
335
|
-
endpoint = "#{https}#{host}/apps/v1/#{url}"
|
336
|
-
when 'Staging'
|
337
|
-
endpoint = "https://rest-staging2.zuora.com/".concat(url)
|
338
|
-
when 'Unknown'
|
339
|
-
raise "Environment unknown, returning passed in parameter unaltered"
|
73
|
+
if self.environment == 'Sandbox'
|
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)
|
75
|
+
elsif self.environment == 'Production'
|
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)
|
77
|
+
elsif self.environment == 'Services'
|
78
|
+
return self.url.split('/')[0..2].join('/').concat('/apps/v1/').concat(url)
|
79
|
+
elsif self.environment == 'Performance'
|
80
|
+
return self.url.split('/')[0..2].join('/').concat('/apps/v1/').concat(url)
|
81
|
+
else self.environment == 'Unknown'
|
82
|
+
return url
|
340
83
|
end
|
341
|
-
return endpoint
|
342
84
|
end
|
343
85
|
|
344
86
|
def fileURL(url="")
|
@@ -349,14 +91,15 @@ module ZuoraAPI
|
|
349
91
|
return self.wsdl_number > 68 ? '%Y-%m-%d' : '%Y-%m-%dT%H:%M:%S'
|
350
92
|
end
|
351
93
|
|
352
|
-
def new_session(auth_type: :basic, debug: false)
|
94
|
+
def new_session(auth_type: :basic, debug: false)
|
353
95
|
end
|
354
96
|
|
355
97
|
def get_session(prefix: false, auth_type: :basic)
|
356
|
-
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}")
|
98
|
+
Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}")
|
357
99
|
case auth_type
|
358
100
|
when :basic
|
359
101
|
if self.current_session.blank?
|
102
|
+
Rails.logger.debug("Create new session")
|
360
103
|
case self.class.to_s
|
361
104
|
when 'ZuoraAPI::Oauth'
|
362
105
|
if self.bearer_token.blank? || self.oauth_expired?
|
@@ -441,15 +184,7 @@ module ZuoraAPI
|
|
441
184
|
else
|
442
185
|
return output_xml, input_xml, response
|
443
186
|
end
|
444
|
-
rescue
|
445
|
-
if !(tries -= 1).zero?
|
446
|
-
Rails.logger.info("SOAP Call - #{ex.class} Timed out will retry after 5 seconds")
|
447
|
-
sleep(self.timeout_sleep)
|
448
|
-
retry
|
449
|
-
else
|
450
|
-
raise ex
|
451
|
-
end
|
452
|
-
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
187
|
+
rescue Net::OpenTimeout, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
|
453
188
|
if !(tries -= 1).zero? && timeout_retry
|
454
189
|
Rails.logger.info("SOAP Call - #{ex.class} Timed out will retry after 5 seconds")
|
455
190
|
sleep(self.timeout_sleep)
|
@@ -484,7 +219,8 @@ module ZuoraAPI
|
|
484
219
|
error = []
|
485
220
|
success = []
|
486
221
|
body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').each_with_index do |call, object_index|
|
487
|
-
|
222
|
+
|
223
|
+
if call.xpath('./ns1:Success', 'ns1' =>'http://api.zuora.com/').text == 'false'
|
488
224
|
message = "#{call.xpath('./*/ns1:Code', 'ns1' =>'http://api.zuora.com/').text}::#{call.xpath('./*/ns1:Message', 'ns1' =>'http://api.zuora.com/').text}"
|
489
225
|
error.push(message)
|
490
226
|
else
|
@@ -496,28 +232,22 @@ module ZuoraAPI
|
|
496
232
|
#By default response if not passed in for SOAP as all SOAP is 200
|
497
233
|
if error.present?
|
498
234
|
if error.class == String
|
499
|
-
|
500
|
-
when "INVALID_SESSION"
|
235
|
+
if error == "INVALID_SESSION"
|
501
236
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{error}::#{message}", body, response.code )
|
502
|
-
|
237
|
+
end
|
238
|
+
if error == "REQUEST_EXCEEDED_LIMIT"
|
503
239
|
raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{error}::#{message}", body, response.code)
|
504
|
-
|
240
|
+
end
|
241
|
+
if error == "LOCK_COMPETITION"
|
505
242
|
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", body, response.code)
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
else
|
510
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code)
|
511
|
-
end
|
512
|
-
when "TEMPORARY_ERROR"
|
513
|
-
raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{error}::#{message}", body, response.code)
|
514
|
-
else
|
515
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code) if error.present?
|
243
|
+
end
|
244
|
+
if error.present?
|
245
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code)
|
516
246
|
end
|
517
247
|
elsif error.class == Array
|
518
248
|
if error[0].include?("LOCK_COMPETITION") && error.count == 1
|
519
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)
|
520
|
-
else
|
250
|
+
else
|
521
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)
|
522
252
|
end
|
523
253
|
end
|
@@ -528,7 +258,6 @@ module ZuoraAPI
|
|
528
258
|
end
|
529
259
|
|
530
260
|
when :JSON
|
531
|
-
body = body.dig("results").present? ? body["results"] : body if body.class == Hash
|
532
261
|
if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
|
533
262
|
messages_array = (body["reasons"] || []).map {|error| error['message']}.compact
|
534
263
|
codes_array = (body["reasons"] || []).map {|error| error['code']}.compact
|
@@ -537,10 +266,6 @@ module ZuoraAPI
|
|
537
266
|
raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new()
|
538
267
|
end
|
539
268
|
|
540
|
-
if body['errorMessage']
|
541
|
-
raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errorMessage'],body,response.code)
|
542
|
-
end
|
543
|
-
|
544
269
|
if body.dig("reasons").nil? ? false : body.dig("reasons")[0].dig("code") == 90000020
|
545
270
|
raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", body, response.code)
|
546
271
|
end
|
@@ -599,18 +324,11 @@ module ZuoraAPI
|
|
599
324
|
end
|
600
325
|
end
|
601
326
|
|
602
|
-
#Zuora REST Actions error (Create, Update, Delete
|
327
|
+
#Zuora REST Actions error (Create, Update, Delete)
|
603
328
|
if body.class == Array
|
604
329
|
all_errors = body.select {|obj| !obj['Success'] || !obj['success'] }.map {|obj| obj['Errors'] || obj['errors'] }.compact
|
605
330
|
all_success = body.select {|obj| obj['Success'] || obj['success']}.compact
|
606
331
|
|
607
|
-
if all_success.blank? && all_errors.present?
|
608
|
-
error_codes = all_errors.flatten.group_by {|error| error['Code']}.keys.uniq
|
609
|
-
if error_codes.size == 1 && error_codes[0] == "LOCK_COMPETITION"
|
610
|
-
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", body, response.code)
|
611
|
-
end
|
612
|
-
end
|
613
|
-
|
614
332
|
if all_errors.size > 0
|
615
333
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{all_errors.flatten.group_by {|error| error['Message']}.keys.uniq.join(' ')}", body, response.code, all_errors, all_success )
|
616
334
|
end
|
@@ -670,11 +388,9 @@ module ZuoraAPI
|
|
670
388
|
|
671
389
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
672
390
|
url = object ? "#{base}/apps/api/describe/#{object}" : "#{base}/apps/api/describe/"
|
673
|
-
headers = self.entity_id.
|
391
|
+
headers = !self.entity_id.blank? ? {"entityId" => self.entity_id, 'Content-Type' => "text/xml; charset=utf-8"} : {'Content-Type' => "text/xml; charset=utf-8"}
|
674
392
|
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
|
675
393
|
|
676
|
-
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401' ) if response.code == 401
|
677
|
-
|
678
394
|
output_xml = Nokogiri::XML(response.body)
|
679
395
|
des_hash = Hash.new
|
680
396
|
if object == nil
|
@@ -704,7 +420,7 @@ module ZuoraAPI
|
|
704
420
|
end
|
705
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
|
706
422
|
end
|
707
|
-
rescue
|
423
|
+
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
|
708
424
|
if !(tries -= 1).zero?
|
709
425
|
Rails.logger.info("Describe - #{ex.class} Timed out will retry after 5 seconds")
|
710
426
|
sleep(self.timeout_sleep)
|
@@ -712,30 +428,17 @@ module ZuoraAPI
|
|
712
428
|
else
|
713
429
|
raise ex
|
714
430
|
end
|
715
|
-
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
716
|
-
if !(tries -= 1).zero?
|
717
|
-
Rails.logger.info("Session expired. Starting new session.")
|
718
|
-
self.new_session
|
719
|
-
retry
|
720
|
-
else
|
721
|
-
raise ex
|
722
|
-
end
|
723
431
|
rescue => ex
|
724
432
|
raise ex
|
725
433
|
else
|
726
434
|
return des_hash
|
727
435
|
end
|
728
436
|
|
729
|
-
def rest_call(method: :get, body: nil,
|
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)
|
730
438
|
tries ||= 2
|
731
|
-
|
732
|
-
if self.entity_id.present?
|
733
|
-
headers["Zuora-Entity-Ids"] = self.entity_id if headers.dig("Zuora-Entity-Ids").nil?
|
734
|
-
headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
735
|
-
end
|
736
|
-
|
439
|
+
headers["entityId"] = self.entity_id if !self.entity_id.blank?
|
737
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)
|
738
|
-
|
441
|
+
|
739
442
|
authentication_headers = z_session ? {"Authorization" => self.get_session(prefix: true, auth_type: session_type) } : {}
|
740
443
|
headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(headers).merge(authentication_headers)
|
741
444
|
|
@@ -752,7 +455,7 @@ module ZuoraAPI
|
|
752
455
|
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
753
456
|
if self.class.to_s == 'ZuoraAPI::Oauth'
|
754
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)
|
755
|
-
else
|
458
|
+
else
|
756
459
|
Rails.logger.debug("Rest Call - Session Bad Auth type")
|
757
460
|
raise ex
|
758
461
|
end
|
@@ -776,15 +479,7 @@ module ZuoraAPI
|
|
776
479
|
end
|
777
480
|
rescue ZuoraAPI::Exceptions::BadEntityError => ex
|
778
481
|
raise ex
|
779
|
-
rescue
|
780
|
-
if !(tries -= 1).zero?
|
781
|
-
Rails.logger.info("Rest Call - #{ex.class} Timed out will retry after 5 seconds")
|
782
|
-
sleep(self.timeout_sleep)
|
783
|
-
retry
|
784
|
-
else
|
785
|
-
raise ex
|
786
|
-
end
|
787
|
-
rescue *CONNECTION_READ_EXCEPTIONS => ex
|
482
|
+
rescue Net::OpenTimeout, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError => ex
|
788
483
|
if !(tries -= 1).zero? && timeout_retry
|
789
484
|
Rails.logger.info("Rest Call - #{ex.class} Timed out will retry after 5 seconds")
|
790
485
|
sleep(self.timeout_sleep)
|
@@ -844,7 +539,7 @@ module ZuoraAPI
|
|
844
539
|
return products, catalog_map
|
845
540
|
end
|
846
541
|
|
847
|
-
def get_file(url: nil, headers: {}, count: 3, z_session: true, tempfile: true,
|
542
|
+
def get_file(url: nil, headers: {}, count: 3, z_session: true, tempfile: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 2, timeout: 120, **execute_params)
|
848
543
|
raise "file_path must be of class Pathname" if file_path.class != Pathname
|
849
544
|
|
850
545
|
#Make sure directory exists
|
@@ -857,126 +552,100 @@ module ZuoraAPI
|
|
857
552
|
http = Net::HTTP.new(uri.host, uri.port)
|
858
553
|
http.read_timeout = timeout #Seconds
|
859
554
|
http.use_ssl = true if uri.scheme.downcase == 'https'
|
860
|
-
if z_session
|
861
|
-
headers = headers.merge({"Authorization" => self.get_session(prefix: true)})
|
862
|
-
headers = headers.merge({"Zuora-Entity-Ids" => self.entity_id}) if !self.entity_id.blank?
|
863
|
-
end
|
555
|
+
headers = headers.merge({"Authorization" => self.get_session(prefix: true)}) if z_session
|
864
556
|
|
865
557
|
response_save = nil
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
headers =
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
case response.header["Content-Disposition"]
|
906
|
-
when /.*; filename\*=.*/
|
907
|
-
full_filename ||= /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[2].strip
|
908
|
-
encoding = /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[1].strip
|
909
|
-
when /.*; filename=/
|
910
|
-
full_filename ||= /.*; filename=(.*)/.match(response.header["Content-Disposition"])[1].strip
|
911
|
-
else
|
912
|
-
raise "Can't parse Content-Disposition header: #{response.header["Content-Disposition"]}"
|
913
|
-
end
|
914
|
-
file_ending ||= full_filename.end_with?(".csv.zip") ? ".csv.zip" : File.extname(full_filename)
|
915
|
-
filename ||= File.basename(full_filename, file_ending)
|
916
|
-
end
|
917
|
-
|
918
|
-
#If user supplied a filename use it, else default to content header filename, else default to uri pattern
|
919
|
-
file_ending ||= uri.path.end_with?(".csv.zip") ? ".csv.zip" : File.extname(uri.path)
|
920
|
-
filename ||= File.basename(uri.path, file_ending)
|
921
|
-
|
922
|
-
if response.header["Content-Type"].present?
|
923
|
-
case response.header["Content-Type"]
|
924
|
-
when /.*;charset=.*/
|
925
|
-
type = /(.*);charset=(.*)/.match(response.header["Content-Type"])[1]
|
926
|
-
encoding = /(.*);charset=(.*)/.match(response.header["Content-Type"])[2]
|
927
|
-
else
|
928
|
-
type = response.header["Content-Type"]
|
929
|
-
encoding ||= 'UTF-8'
|
930
|
-
end
|
558
|
+
http.request_get(uri.path, headers) do |response|
|
559
|
+
response_save = response
|
560
|
+
status_code = response.code if response
|
561
|
+
|
562
|
+
case response
|
563
|
+
when Net::HTTPNotFound
|
564
|
+
Rails.logger.fatal("404 - Not Found")
|
565
|
+
raise response
|
566
|
+
|
567
|
+
when Net::HTTPUnauthorized
|
568
|
+
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) if count <= 0
|
569
|
+
Rails.logger.fatal("Unauthorized: Retry")
|
570
|
+
self.new_session
|
571
|
+
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)
|
572
|
+
|
573
|
+
when Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError
|
574
|
+
Rails.logger.fatal("#{response.class} timeout - retry")
|
575
|
+
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)
|
576
|
+
|
577
|
+
when Net::HTTPClientError
|
578
|
+
Rails.logger.fatal("Login: #{self.username} Export")
|
579
|
+
raise response
|
580
|
+
|
581
|
+
when Net::HTTPOK
|
582
|
+
headers = {}
|
583
|
+
response.each_header do |k,v|
|
584
|
+
headers[k] = v
|
585
|
+
end
|
586
|
+
Rails.logger.debug("Headers: #{headers.to_s}")
|
587
|
+
|
588
|
+
size, export_progress = [0, 0]
|
589
|
+
encoding, type, full_filename = [nil, nil, nil]
|
590
|
+
if response.header["Content-Disposition"].present?
|
591
|
+
case response.header["Content-Disposition"]
|
592
|
+
when /.*; filename\*=.*/
|
593
|
+
full_filename = /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[2].strip
|
594
|
+
encoding = /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[1].strip
|
595
|
+
when /.*; filename=/
|
596
|
+
full_filename = /.*; filename=(.*)/.match(response.header["Content-Disposition"])[1].strip
|
931
597
|
end
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
598
|
+
file_ending = ".#{full_filename.partition(".").last}"
|
599
|
+
end
|
600
|
+
#If user supplied a filename use it, else default to content header filename, else default to uri pattern
|
601
|
+
filename = full_filename.present? ? full_filename.split(file_ending).first : File.basename(uri.path).rpartition('.').first
|
602
|
+
|
603
|
+
if response.header["Content-Type"].present?
|
604
|
+
case response.header["Content-Type"]
|
605
|
+
when /.*;charset=.*/
|
606
|
+
type = /(.*);charset=(.*)/.match(response.header["Content-Type"])[1]
|
607
|
+
encoding = /(.*);charset=(.*)/.match(response.header["Content-Type"])[2]
|
608
|
+
else
|
609
|
+
type = response.header["Content-Type"]
|
610
|
+
encoding ||= 'UTF-8'
|
937
611
|
end
|
612
|
+
end
|
613
|
+
Rails.logger.info("File: #{filename}#{file_ending} #{encoding} #{type}")
|
938
614
|
|
939
|
-
|
615
|
+
if response.header["Content-Length"].present?
|
616
|
+
export_size = response.header["Content-Length"].to_i
|
617
|
+
elsif response.header["ContentLength"].present?
|
618
|
+
export_size = response.header["ContentLength"].to_i
|
619
|
+
end
|
940
620
|
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
621
|
+
file_handle = nil
|
622
|
+
timestamp = Time.now.to_i
|
623
|
+
if tempfile
|
624
|
+
require 'tempfile'
|
625
|
+
file_handle = ::Tempfile.new(["#{filename}_#{timestamp}", "#{file_ending}"], file_path)
|
626
|
+
file_handle.binmode
|
627
|
+
else
|
628
|
+
file_handle = File.new(file_path.join("#{filename}_#{timestamp}#{file_ending}"), "w+")
|
948
629
|
file_handle.binmode
|
630
|
+
end
|
949
631
|
|
950
|
-
|
951
|
-
|
952
|
-
file_handle << chunk.force_encoding(encoding)
|
953
|
-
else
|
954
|
-
file_handle << chunk
|
955
|
-
end
|
632
|
+
response.read_body do |chunk|
|
633
|
+
file_handle << chunk.force_encoding(encoding)
|
956
634
|
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
end
|
963
|
-
export_progress = new_progress
|
635
|
+
if defined?(export_size) && export_size != 0 && export_size.class == Integer
|
636
|
+
size += chunk.size
|
637
|
+
new_progress = (size * 100) / export_size
|
638
|
+
unless new_progress == export_progress
|
639
|
+
Rails.logger.debug("Login: #{self.username} Export Downloading %s (%3d%%)" % [filename, new_progress])
|
964
640
|
end
|
641
|
+
export_progress = new_progress
|
965
642
|
end
|
643
|
+
end
|
966
644
|
|
967
|
-
|
968
|
-
|
645
|
+
file_handle.close
|
646
|
+
Rails.logger.debug("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb")
|
969
647
|
|
970
|
-
|
971
|
-
end
|
972
|
-
end
|
973
|
-
rescue *(CONNECTION_EXCEPTIONS).concat(CONNECTION_READ_EXCEPTIONS).concat([Net::HTTPBadResponse]) => e
|
974
|
-
sleep(5)
|
975
|
-
if (timeout_retries -= 1) >= 0
|
976
|
-
Rails.logger.warn("Download Failed: #{e.class} : #{e.message}")
|
977
|
-
retry
|
978
|
-
else
|
979
|
-
raise
|
648
|
+
return file_handle
|
980
649
|
end
|
981
650
|
end
|
982
651
|
rescue Exception => e
|
@@ -987,6 +656,8 @@ module ZuoraAPI
|
|
987
656
|
end
|
988
657
|
|
989
658
|
def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
|
659
|
+
Rails.logger.debug("Build export")
|
660
|
+
Rails.logger.debug("#{query}")
|
990
661
|
request = Nokogiri::XML::Builder.new do |xml|
|
991
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
|
992
663
|
xml['SOAP-ENV'].Header do
|
@@ -1009,7 +680,7 @@ module ZuoraAPI
|
|
1009
680
|
end
|
1010
681
|
|
1011
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)
|
1012
|
-
|
683
|
+
|
1013
684
|
output_xml = Nokogiri::XML(response_query.body)
|
1014
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"
|
1015
686
|
id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
@@ -1033,7 +704,7 @@ module ZuoraAPI
|
|
1033
704
|
while result != "Completed"
|
1034
705
|
sleep 3
|
1035
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)
|
1036
|
-
|
707
|
+
|
1037
708
|
output_xml = Nokogiri::XML(response_query.body)
|
1038
709
|
result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text
|
1039
710
|
status_code = response_query.code if response_query
|
@@ -1041,6 +712,7 @@ module ZuoraAPI
|
|
1041
712
|
end
|
1042
713
|
|
1043
714
|
file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
|
715
|
+
Rails.logger.debug('=====> Export finished')
|
1044
716
|
export_file = get_file(:url => self.fileURL(file_id))
|
1045
717
|
export_file_path = export_file.path
|
1046
718
|
Rails.logger.debug("=====> Export path #{export_file.path}")
|
@@ -1059,6 +731,7 @@ module ZuoraAPI
|
|
1059
731
|
end
|
1060
732
|
|
1061
733
|
def query(query, parse = false)
|
734
|
+
Rails.logger.debug("Querying Zuora for #{query}")
|
1062
735
|
output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
|
1063
736
|
xml['ns1'].query do
|
1064
737
|
xml['ns1'].queryString query
|
@@ -1083,7 +756,7 @@ module ZuoraAPI
|
|
1083
756
|
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
1084
757
|
http.request req
|
1085
758
|
end
|
1086
|
-
|
759
|
+
|
1087
760
|
Rails.logger.debug("Response #{response.code} #{response.message}: #{response.body}")
|
1088
761
|
|
1089
762
|
result = JSON.parse(response.body)
|
@@ -27,11 +27,11 @@ module ZuoraAPI
|
|
27
27
|
|
28
28
|
input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
|
29
29
|
input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
|
30
|
-
Rails.logger.debug('Connect') {"Request
|
30
|
+
Rails.logger.debug('Connect') {"Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
31
31
|
|
32
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
33
|
@output_xml = Nokogiri::XML(@response_query.body)
|
34
|
-
Rails.logger.debug('Connect') {"Response
|
34
|
+
Rails.logger.debug('Connect') {"Response SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
|
35
35
|
|
36
36
|
if !@response_query.success?
|
37
37
|
self.current_session = nil
|
@@ -70,9 +70,6 @@ module ZuoraAPI
|
|
70
70
|
self.status = 'Locked'
|
71
71
|
self.current_error = 'Locked user login, please wait or navigate to Zuora to unlock user'
|
72
72
|
self.errors[:username] = self.current_error
|
73
|
-
elsif self.current_error.include?('Entity not exist:')
|
74
|
-
self.status = 'Entity Missing'
|
75
|
-
self.errors[:base] = self.current_error
|
76
73
|
else
|
77
74
|
self.status = 'Unknown'
|
78
75
|
self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
|
@@ -88,11 +85,10 @@ module ZuoraAPI
|
|
88
85
|
#Username & password combo
|
89
86
|
retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
|
90
87
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
|
91
|
-
self.status = 'Active'
|
92
88
|
self.current_session = retrieved_session
|
93
89
|
end
|
94
90
|
return self.status
|
95
|
-
rescue
|
91
|
+
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
|
96
92
|
if !(tries -= 1).zero?
|
97
93
|
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
98
94
|
sleep(self.timeout_sleep)
|
@@ -102,12 +98,6 @@ module ZuoraAPI
|
|
102
98
|
self.status = 'Timeout'
|
103
99
|
return self.status
|
104
100
|
end
|
105
|
-
rescue EOFError
|
106
|
-
if self.url.match?(/.*services\d{1,}.zuora.com*/)
|
107
|
-
self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available."
|
108
|
-
self.status = 'Not Available'
|
109
|
-
return self.status
|
110
|
-
end
|
111
101
|
end
|
112
102
|
end
|
113
103
|
end
|
@@ -24,14 +24,9 @@ module ZuoraAPI
|
|
24
24
|
return self.status
|
25
25
|
end
|
26
26
|
|
27
|
-
def get_active_bearer_token
|
28
|
-
self.get_bearer_token if self.oauth_expired?
|
29
|
-
return self.bearer_token
|
30
|
-
end
|
31
|
-
|
32
27
|
def get_z_session(debug: false)
|
33
28
|
tries ||= 2
|
34
|
-
headers = self.entity_id.present? ? {
|
29
|
+
headers = self.entity_id.present? ? {:entityId => self.entity_id } : {}
|
35
30
|
output_json, response = self.rest_call(:url => self.rest_endpoint("connections"), :session_type => :bearer, :headers => headers)
|
36
31
|
self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=')
|
37
32
|
rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
|
@@ -52,7 +47,7 @@ module ZuoraAPI
|
|
52
47
|
else
|
53
48
|
return [output_json, response]
|
54
49
|
end
|
55
|
-
rescue
|
50
|
+
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
|
56
51
|
if !(tries -= 1).zero?
|
57
52
|
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
58
53
|
sleep(self.timeout_sleep)
|
@@ -92,7 +87,7 @@ module ZuoraAPI
|
|
92
87
|
else
|
93
88
|
return [output_json, response]
|
94
89
|
end
|
95
|
-
rescue
|
90
|
+
rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => ex
|
96
91
|
if !(tries -= 1).zero?
|
97
92
|
Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
|
98
93
|
sleep(self.timeout_sleep)
|
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.03
|
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:
|
11
|
+
date: 2018-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -153,7 +153,6 @@ files:
|
|
153
153
|
- ".gitlab-ci.yml"
|
154
154
|
- ".rspec"
|
155
155
|
- ".travis.yml"
|
156
|
-
- CHANGELOG.md
|
157
156
|
- Gemfile
|
158
157
|
- Gemfile.lock
|
159
158
|
- README.md
|
@@ -182,11 +181,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
182
181
|
version: '0'
|
183
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
183
|
requirements:
|
185
|
-
- - "
|
184
|
+
- - ">="
|
186
185
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
186
|
+
version: '0'
|
188
187
|
requirements: []
|
189
|
-
|
188
|
+
rubyforge_project:
|
189
|
+
rubygems_version: 2.6.8
|
190
190
|
signing_key:
|
191
191
|
specification_version: 4
|
192
192
|
summary: Gem that provides easy integration to Zuora
|
data/CHANGELOG.md
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# Changelog
|
2
|
-
All notable changes to this project will be documented in this file.
|
3
|
-
|
4
|
-
## [1.6.28] - 2018-3-12
|
5
|
-
### Added
|
6
|
-
- Way to avoid force encoding for filedownload
|
7
|
-
|
8
|
-
## [1.6.22] - 2019-01-03
|
9
|
-
### Changed
|
10
|
-
- get_identity method - supports ZSession auth now
|
11
|
-
- updated rspecs accordingly
|
12
|
-
|
13
|
-
## [1.6.18] - 2018-12-06
|
14
|
-
### Added
|
15
|
-
- zconnect_provider attribute accessor for identifying ZConnect cookies
|
16
|
-
- Methods for Hallway integration:
|
17
|
-
- get_identity
|
18
|
-
- get_full_nav
|
19
|
-
- set_nav
|
20
|
-
- refresh_nav
|
21
|
-
- get_oauth_client
|
22
|
-
|
23
|
-
### Changed
|
24
|
-
- The way environment and region are set
|
25
|
-
|
26
|
-
|