zuora_api 1.7.81 → 1.8.00

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.
@@ -10,22 +10,113 @@ module ZuoraAPI
10
10
  end
11
11
 
12
12
  def new_session(auth_type: :basic, debug: false, zuora_track_id: nil)
13
- super do
14
- raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
15
- raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Basic Login but either 'Username' or 'Password' were not passed.") if (self.password.blank? && self.username.blank?)
13
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
14
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Basic Login but either 'Username' or 'Password' were not passed.") if (self.password.blank? && self.username.blank?)
16
15
 
17
- output_xml, input_xml, response = soap_call(timeout_retry: true, skip_session: true, zuora_track_id: zuora_track_id) do |xml|
18
- xml['api'].login do
19
- xml['api'].username self.username
20
- xml['api'].password self.password
21
- xml['api'].entityId self.entity_id if !self.entity_id.blank?
16
+ tries ||= 2
17
+ request = Nokogiri::XML::Builder.new do |xml|
18
+ xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' =>"http://schemas.xmlsoap.org/soap/envelope/", 'xmlns:api' => "http://api.zuora.com/" ) do
19
+ xml['SOAP-ENV'].Header
20
+ xml['SOAP-ENV'].Body do
21
+ xml['api'].login do
22
+ xml['api'].username self.username
23
+ xml['api'].password self.password
24
+ xml['api'].entityId self.entity_id if !self.entity_id.blank?
25
+ end
22
26
  end
23
27
  end
28
+ end
29
+
30
+ input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
31
+ input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
32
+ Rails.logger.debug('Connect') {"SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
33
+
34
+ headers = { 'Content-Type' => "text/xml; charset=utf-8" }
35
+ headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
24
36
 
37
+ response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => headers, :timeout => 10)
38
+ output_xml = Nokogiri::XML(response_query.body)
39
+ Rails.logger.debug('Connect') {"Response Code: #{response_query.code} SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
40
+
41
+ if !response_query.success?
42
+ self.current_session = nil
43
+ if output_xml.namespaces.size > 0 && output_xml.xpath('//soapenv:Fault').size > 0
44
+ self.current_error = output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
45
+ if self.current_error.include?('deactivated')
46
+ self.status = 'Deactivated'
47
+ self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
48
+ self.errors[:username] = self.current_error
49
+ elsif self.current_error.include?('inactive')
50
+ self.status = 'Inactive'
51
+ self.current_error = 'Inactive user login, please check with Zuora tenant administrator'
52
+ self.errors[:username] = self.current_error
53
+ elsif self.current_error.include?("invalid username or password") || self.current_error.include?("Invalid login. User name and password do not match.")
54
+ self.status = 'Invalid Login'
55
+ self.current_error = 'Invalid login, please check username and password or URL endpoint'
56
+ self.errors[:username] = self.current_error
57
+ self.errors[:password] = self.current_error
58
+ elsif self.current_error.include?('unsupported version')
59
+ self.status = 'Unsupported API Version'
60
+ self.current_error = 'Unsupported API version, please verify URL endpoint'
61
+ self.errors[:url] = self.current_error
62
+ elsif self.current_error.include?('invalid api version')
63
+ self.status = 'Invalid API Version'
64
+ self.current_error = 'Invalid API version, please verify URL endpoint'
65
+ self.errors[:url] = self.current_error
66
+ elsif self.current_error.include?('invalid session')
67
+ self.status = 'Invalid Session'
68
+ self.current_error = 'Session invalid, please update session and verify URL endpoint'
69
+ self.errors[:session] = self.current_error
70
+ elsif self.current_error.include?('Your IP address')
71
+ self.status = 'Restricted IP'
72
+ self.current_error = 'IP restricted, contact Zuora tenant administrator and remove IP restriction'
73
+ self.errors[:base] = self.current_error
74
+ elsif self.current_error.include?('This account has been locked')
75
+ self.status = 'Locked'
76
+ self.current_error = 'Locked user login, please wait or navigate to Zuora to unlock user'
77
+ self.errors[:username] = self.current_error
78
+ elsif self.current_error.include?('Entity not exist:')
79
+ self.status = 'Entity Missing'
80
+ self.errors[:base] = self.current_error
81
+ else
82
+ self.status = 'Unknown'
83
+ self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
84
+ self.errors[:base] = self.current_error
85
+ end
86
+
87
+ else
88
+ self.status = 'Unknown'
89
+ self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
90
+ self.errors[:base] = self.current_error
91
+ end
92
+ else
93
+ #Username & password combo
25
94
  retrieved_session = output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
26
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.", response) if retrieved_session.blank?
27
- self.current_session = retrieved_session
95
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.", response_query) if retrieved_session.blank?
28
96
  self.status = 'Active'
97
+ self.current_session = retrieved_session
98
+ end
99
+ return self.status
100
+ rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
101
+ if !tries.zero?
102
+ tries -= 1
103
+ sleep(self.timeout_sleep)
104
+ retry
105
+ else
106
+ if Rails.logger.class.to_s == "Ougai::Logger"
107
+ Rails.logger.error("BasicLogin - Timed out", ex)
108
+ else
109
+ Rails.logger.error("BasicLogin - #{ex.class} Timed out")
110
+ end
111
+
112
+ self.current_error = "Request timed out. Try again"
113
+ self.status = 'Timeout'
114
+ return self.status
115
+ end
116
+ rescue EOFError
117
+ if self.url.match?(/.*services\d{1,}.zuora.com*/)
118
+ self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available."
119
+ self.status = 'Not Available'
29
120
  return self.status
30
121
  end
31
122
  end
@@ -12,18 +12,16 @@ module ZuoraAPI
12
12
  end
13
13
 
14
14
  def new_session(auth_type: nil, zuora_track_id: nil)
15
- super do
16
- if auth_type == :bearer
17
- get_bearer_token(zuora_track_id: zuora_track_id)
18
- elsif auth_type == :basic
19
- get_bearer_token(zuora_track_id: zuora_track_id) if self.oauth_expired?
20
- get_z_session(zuora_track_id: zuora_track_id)
21
- else
22
- get_bearer_token(zuora_track_id: zuora_track_id) if self.oauth_expired?
23
- get_z_session(zuora_track_id: zuora_track_id)
24
- end
25
- return self.status
15
+ if auth_type == :bearer
16
+ get_bearer_token(zuora_track_id: zuora_track_id)
17
+ elsif auth_type == :basic
18
+ get_bearer_token(zuora_track_id: zuora_track_id) if self.oauth_expired?
19
+ get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
20
+ else
21
+ get_bearer_token(zuora_track_id: zuora_track_id)
22
+ get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active'
26
23
  end
24
+ return self.status
27
25
  end
28
26
 
29
27
  def get_active_bearer_token
@@ -32,35 +30,59 @@ module ZuoraAPI
32
30
  end
33
31
 
34
32
  def get_z_session(debug: false, zuora_track_id: nil)
33
+ tries ||= 2
35
34
  headers = self.entity_id.present? ? {"Zuora-Entity-Ids" => self.entity_id } : {}
36
35
  headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
37
36
  output_json, response = self.rest_call(:url => self.rest_endpoint("connections"), :session_type => :bearer, :headers => headers)
38
37
  begin
39
38
  self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=')
40
39
  rescue NoMethodError => ex
41
- Rails.logger.fatal("Failure Parsing Cookie Headers", {
42
- response: {
43
- status: response.code,
44
- params: response.body.to_s,
45
- headers: response.headers.to_s,
46
- }
47
- })
48
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Failure Parsing Cookie Headers", response)
40
+ Rails.logger.fatal("Failure Parsing Cookie Headers", response.headers.to_s)
41
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Failure Parsing Cookie Headers")
49
42
  end
43
+ rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
44
+ if !tries.zero?
45
+ tries -= 1
46
+ Rails.logger.debug {"Session Invalid"}
47
+ self.new_session(auth_type: :bearer)
48
+ retry
49
+ end
50
+ raise ex if errors.include?(ex.class)
51
+ return [output_json, response]
52
+
53
+ rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
54
+ raise ex if errors.include?(ex.class)
55
+ return [output_json, response]
56
+
57
+ rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
58
+ if !tries.zero?
59
+ tries -= 1
60
+ sleep(self.timeout_sleep)
61
+ retry
62
+ end
63
+ if Rails.logger.class.to_s == "Ougai::Logger"
64
+ Rails.logger.error("OAuthLogin - Timed out", ex)
65
+ else
66
+ Rails.logger.error("OAuthLogin - #{ex.class} Timed out")
67
+ end
68
+ self.current_error = "Request timed out. Try again"
69
+ self.status = 'Timeout'
70
+ return self.status
50
71
  end
51
72
 
52
73
  def get_bearer_token(zuora_track_id: nil)
74
+ tries ||= 2
53
75
  raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if self.oauth_client_id.blank? || self.oauth_secret.blank?
54
76
 
55
77
  headers = { "content-type" => "application/x-www-form-urlencoded" }
56
78
  headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
57
79
 
58
80
  output_json, response = self.rest_call(:method => :post,
59
- url: self.rest_endpoint.chomp('v1/').concat("oauth/token"),
60
- z_session: false,
61
- timeout_retry: true,
62
- headers: headers,
63
- body: {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"}
81
+ :url => self.rest_endpoint.chomp('v1/').concat("oauth/token"),
82
+ :z_session => false,
83
+ :session_type => :bearer,
84
+ :headers => headers,
85
+ :body => {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"}
64
86
  )
65
87
 
66
88
  self.bearer_token = output_json["access_token"]
@@ -70,6 +92,44 @@ module ZuoraAPI
70
92
  self.status = 'Active'
71
93
 
72
94
  return self.status
95
+
96
+ rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex
97
+ raise ex if tries.zero?
98
+
99
+ tries -= 1
100
+ sleep(self.timeout_sleep)
101
+ retry
102
+ rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
103
+ self.bearer_token = nil
104
+ self.oauth_session_expires_at = nil
105
+ self.current_error = ex.message
106
+ case ex.message
107
+ when "Forbidden"
108
+ self.current_error = "The user associated to OAuth credential set has been deactivated."
109
+ self.status = 'Deactivated'
110
+ else
111
+ self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
112
+ self.status = 'Invalid Login'
113
+ end
114
+
115
+ return self.status
116
+ rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
117
+ raise ex
118
+ rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex
119
+ if !tries.zero?
120
+ tries -= 1
121
+ sleep(self.timeout_sleep)
122
+ retry
123
+ else
124
+ if Rails.logger.class.to_s == "Ougai::Logger"
125
+ Rails.logger.error("OAuthLogin - Timed out will retry after #{self.timeout_sleep} seconds", ex)
126
+ else
127
+ Rails.logger.error("OAuthLogin - #{ex.class} Timed out will retry after #{self.timeout_sleep} seconds")
128
+ end
129
+ self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
130
+ self.status = 'Timeout'
131
+ return self.status
132
+ end
73
133
  end
74
134
 
75
135
  def oauth_expired?
@@ -1,3 +1,3 @@
1
1
  module ZuoraAPI
2
- VERSION = "1.7.81"
2
+ VERSION = "1.8.00"
3
3
  end
data/zuora_api.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'zuora_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "zuora_api"
8
+ spec.version = ZuoraAPI::VERSION
9
+ spec.authors = ["Zuora Strategic Solutions Group"]
10
+ spec.email = ["connect@zuora.com"]
11
+
12
+ spec.summary = %q{Gem that provides easy integration to Zuora}
13
+ spec.description = %q{Gem that provides easy integration to Zuora}
14
+ spec.homepage = "https://connect.zuora.com"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.12"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency("webmock")
25
+ spec.add_development_dependency("simplecov")
26
+ spec.add_dependency("nokogiri")
27
+ spec.add_dependency("httparty")
28
+ spec.add_dependency("rubyzip")
29
+ spec.add_dependency("railties", ">= 4.1.0", "< 6")
30
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zuora_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.81
4
+ version: 1.8.00
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: 2021-03-12 00:00:00.000000000 Z
11
+ date: 2020-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.12'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '1.12'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -68,26 +68,12 @@ dependencies:
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 0.18.5
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 0.18.5
83
- - !ruby/object:Gem::Dependency
84
- name: ougai
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - ">="
88
74
  - !ruby/object:Gem::Version
89
75
  version: '0'
90
- type: :runtime
76
+ type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
@@ -145,7 +131,7 @@ dependencies:
145
131
  version: 4.1.0
146
132
  - - "<"
147
133
  - !ruby/object:Gem::Version
148
- version: '6.1'
134
+ version: '6'
149
135
  type: :runtime
150
136
  prerelease: false
151
137
  version_requirements: !ruby/object:Gem::Requirement
@@ -155,7 +141,7 @@ dependencies:
155
141
  version: 4.1.0
156
142
  - - "<"
157
143
  - !ruby/object:Gem::Version
158
- version: '6.1'
144
+ version: '6'
159
145
  description: Gem that provides easy integration to Zuora
160
146
  email:
161
147
  - connect@zuora.com
@@ -163,9 +149,17 @@ executables: []
163
149
  extensions: []
164
150
  extra_rdoc_files: []
165
151
  files:
166
- - MIT-LICENSE
152
+ - ".gitignore"
153
+ - ".gitlab-ci.yml"
154
+ - ".rspec"
155
+ - ".travis.yml"
156
+ - CHANGELOG.md
157
+ - Gemfile
158
+ - Gemfile.lock
167
159
  - README.md
168
160
  - Rakefile
161
+ - bin/console
162
+ - bin/setup
169
163
  - lib/insights_api/login.rb
170
164
  - lib/zuora_api.rb
171
165
  - lib/zuora_api/exceptions.rb
@@ -173,6 +167,7 @@ files:
173
167
  - lib/zuora_api/logins/basic.rb
174
168
  - lib/zuora_api/logins/oauth.rb
175
169
  - lib/zuora_api/version.rb
170
+ - zuora_api.gemspec
176
171
  homepage: https://connect.zuora.com
177
172
  licenses: []
178
173
  metadata: {}
@@ -191,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
186
  - !ruby/object:Gem::Version
192
187
  version: '0'
193
188
  requirements: []
194
- rubygems_version: 3.1.4
189
+ rubygems_version: 3.0.3
195
190
  signing_key:
196
191
  specification_version: 4
197
192
  summary: Gem that provides easy integration to Zuora
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright 2021 Zuora, Inc.
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.