zuora_api 1.6.255 → 1.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5e6a8e9ae21ef49ef02ea0c4f68a568d5e0e8bb8
4
- data.tar.gz: 29eb9ef8d16d22b41e0b446d89f86e416c03fb21
2
+ SHA256:
3
+ metadata.gz: ecec87283f238f546be12e3fadb16e9fabbee7aec1129d47401876359271f868
4
+ data.tar.gz: 98d980959dcf672fad54bdc87fa89061f6aee4627eebb4ef89da8573c204419b
5
5
  SHA512:
6
- metadata.gz: 53b80cc5f612a4b59fc80280fd1e9b8a694de301aa43f481ab5af4f33647ae65188e51399d9be59c161d8d7dfb7eeecbcc6667e5f0ab195cb56c3de91c2ced15
7
- data.tar.gz: b955ba0161c862c0a7b96ab5b29e282548ace81f23b8df999710d1647c5e1e66ff5898781454df41b9f7cc6905c4ad95353c0c75c10cd7f1c6d6a8d582d72809
6
+ metadata.gz: 0f18782b6e2bc5d2433c4f0b632fe931205392db8b334edf524accec0e17821394a064f82cb45983d0a0ae7cbbc106b8ae8911b90c35651445e139bf94d261d7
7
+ data.tar.gz: 56555f10ce5434a30a54d4cad556170987a033f1cbfef34dc0b246fd935878ae4e7bd989e4c7ba7f3f95a73d291c25983d39260b41a8c91a1dcb9a019e879eab
@@ -1,5 +1,4 @@
1
-
2
- image: ruby:2.3.1
1
+ image: ruby:2.6
3
2
  stages:
4
3
  - setup
5
4
  - test
@@ -41,10 +40,24 @@ rubygems-deploy:
41
40
  stage: deploy
42
41
  allow_failure: false
43
42
  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"
44
56
  - bundle install
45
57
  - gem install rake
46
58
  - version=$(rake install | grep -o 'pkg/zuora_api-.*gem')
47
59
  - curl -u $USERNAME:$PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
48
60
  - gem push $version
49
61
  only:
50
- - master
62
+ - master
63
+ - staging
@@ -1,6 +1,63 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [1.7.00] - 2018-8-05
5
+ ### Changed
6
+ - Raise proper exception when oauth client is from deactivated user.
7
+ - Support for rails < 6
8
+
9
+ ## [1.6.53] - 2018-7-29
10
+ ### Changed
11
+ - Don't attempt zsession login if bearer token is bad
12
+
13
+ ## [1.6.51 - 1.6.51] - 2018-7-22
14
+ ### Changed
15
+ - Retry on address not available.
16
+
17
+ ## [1.6.47 - 1.6.48] - 2018-6-26
18
+ ### Changed
19
+ - Changed error raise statements when incorrect credentials are supplied to Basic/Oauth Logins
20
+
21
+ ## [1.6.45] - 2018-5-30
22
+ ### Changed
23
+ - Fix retry so headers are reinstaniated on session failure.
24
+
25
+ ## [1.6.41] - 2018-5-30
26
+ ### Changed
27
+ - Retry added on SSL connection failure
28
+
29
+ ## [1.6.39-1.6.40] - 2018-5-30
30
+ ### Changed
31
+ - Added validation to fix bad urls entered into object initialization
32
+
33
+ ## [1.6.38] - 2018-5-26
34
+ ### Changed
35
+ - HttpParty validation before code extraction
36
+
37
+ ## [1.6.37] - 2018-5-23
38
+ ### Added
39
+ - Added method to determine rest endpoint domain
40
+
41
+ ## [1.6.36] - 2018-5-22
42
+ ### Changed
43
+ - Fixed zuora staging 2 endpoint
44
+
45
+ ## [1.6.33] - 2018-5-15
46
+ ### Changed
47
+ - Added Errno::EHOSTUNREACH to list of retriable error codes
48
+
49
+ ## [1.6.32] - 2018-5-14
50
+ ### Changed
51
+ - Don't log fatal errors, allow application to decide for file download
52
+ - Don't change api url if the user set a high api url
53
+
54
+ ###Removed
55
+ - Force encoding
56
+
57
+ ## [1.6.28] - 2018-3-12
58
+ ### Added
59
+ - Way to avoid force encoding for filedownload
60
+
4
61
  ## [1.6.28] - 2018-3-12
5
62
  ### Added
6
63
  - Way to avoid force encoding for filedownload
@@ -6,8 +6,8 @@ module ZuoraAPI
6
6
  attr_reader :code, :response
7
7
  attr_writer :default_message
8
8
 
9
- def initialize(message = nil,response=nil, code =nil)
10
- @code = code
9
+ def initialize(message = nil,response=nil)
10
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
11
11
  @message = message
12
12
  @response = response
13
13
  @default_message = "Error with Zuora Session."
@@ -22,8 +22,8 @@ module ZuoraAPI
22
22
  attr_reader :code, :response, :errors, :successes
23
23
  attr_writer :default_message
24
24
 
25
- def initialize(message = nil,response=nil, code =nil, errors = [], successes = [])
26
- @code = code
25
+ def initialize(message = nil,response=nil, errors = [], successes = [], *args)
26
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
27
27
  @message = message
28
28
  @response = response
29
29
  @default_message = "Error with Zuora Entity"
@@ -40,8 +40,8 @@ module ZuoraAPI
40
40
  attr_reader :code, :response, :errors, :successes
41
41
  attr_writer :default_message
42
42
 
43
- def initialize(message = nil,response=nil, code =nil, errors = [], successes = [])
44
- @code = code
43
+ def initialize(message = nil,response=nil, errors = [], successes = [], *args)
44
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
45
45
  @message = message
46
46
  @response = response
47
47
  @default_message = "Error communicating with Zuora."
@@ -58,8 +58,8 @@ module ZuoraAPI
58
58
  attr_reader :code, :response
59
59
  attr_writer :default_message
60
60
 
61
- def initialize(message = nil,response=nil, code =nil)
62
- @code = code
61
+ def initialize(message = nil,response=nil, *args)
62
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
63
63
  @message = message
64
64
  @response = response
65
65
  @default_message = "Your request limit has been exceeded for zuora."
@@ -74,8 +74,24 @@ module ZuoraAPI
74
74
  attr_reader :code, :response
75
75
  attr_writer :default_message
76
76
 
77
- def initialize(message = nil,response=nil, code =nil)
78
- @code = code
77
+ def initialize(message = nil,response=nil, *args)
78
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
79
+ @message = message
80
+ @response = response
81
+ @default_message = "Operation failed due to lock competition. Please retry"
82
+ end
83
+
84
+ def to_s
85
+ @message || @default_message
86
+ end
87
+ end
88
+
89
+ class ZuoraDataIntegrity < Error
90
+ attr_reader :code, :response
91
+ attr_writer :default_message
92
+
93
+ def initialize(message = nil,response=nil, *args)
94
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
79
95
  @message = message
80
96
  @response = response
81
97
  @default_message = "Operation failed due to lock competition. Please retry"
@@ -90,8 +106,8 @@ module ZuoraAPI
90
106
  attr_reader :code, :response
91
107
  attr_writer :default_message
92
108
 
93
- def initialize(message = nil,response=nil, code =nil)
94
- @code = code
109
+ def initialize(message = nil,response=nil, *args)
110
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
95
111
  @message = message
96
112
  @response = response
97
113
  @default_message = "There is a temporary error with zuora system."
@@ -106,8 +122,8 @@ module ZuoraAPI
106
122
  attr_reader :code, :response
107
123
  attr_writer :default_message
108
124
 
109
- def initialize(message = nil,response=nil, code =nil)
110
- @code = code
125
+ def initialize(message = nil,response=nil, *args)
126
+ @code = response.present? && response.class.to_s == "HTTParty::Response" ? response.code : nil
111
127
  @message = message
112
128
  @response = response
113
129
  @default_message = "Authentication type is not supported by this Login"
@@ -1,28 +1,38 @@
1
1
  require "httparty"
2
2
  require "nokogiri"
3
3
  require "uri"
4
+ require 'zuora_api/exceptions'
4
5
 
5
6
  module ZuoraAPI
6
7
  class Login
7
8
  ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown', STAGING = 'Staging' ]
8
9
  REGIONS = [EU = 'EU', US = 'US', NA = 'NA' ]
9
- MIN_Endpoint = '91.0'
10
+ MIN_Endpoint = '96.0'
10
11
  XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
11
- CONNECTION_EXCEPTIONS = [Net::OpenTimeout, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError]
12
+ CONNECTION_EXCEPTIONS = [Net::OpenTimeout, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, SocketError, Errno::EHOSTUNREACH, Errno::EADDRNOTAVAIL]
12
13
  CONNECTION_READ_EXCEPTIONS = [Net::ReadTimeout, Errno::ECONNRESET, Errno::EPIPE]
14
+ ZUORA_API_ERRORS = [ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition, ZuoraAPI::Exceptions::ZuoraAPITemporaryError, ZuoraAPI::Exceptions::ZuoraDataIntegrity]
15
+
16
+ attr_accessor :region, :url, :wsdl_number, :current_session, :bearer_token, :oauth_session_expires_at, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep, :hostname, :zconnect_provider
13
17
 
14
- attr_accessor :region, :url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep, :hostname, :zconnect_provider
15
-
16
- def initialize(url: nil, entity_id: nil, session: nil, status: nil, **keyword_args)
17
- raise "URL is nil or empty, but URL is required" if url.nil? | url.empty?
18
+ def initialize(url: nil, entity_id: nil, session: nil, status: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args)
19
+ raise "URL is nil or empty, but URL is required" if url.nil? || url.empty?
18
20
  # raise "URL is improper. URL must contain zuora.com, zuora.eu, or zuora.na" if /zuora.com|zuora.eu|zuora.na/ === url
19
- @url = url.gsub(/(\d{2}\.\d)$/, MIN_Endpoint)
20
- @hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil?
21
- @entity_id = get_entity_id(entity_id: entity_id)
22
- @errors = Hash.new
23
- @current_session = session
24
- @status = status.blank? ? "Active" : status
25
- @user_info = Hash.new
21
+ self.hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil?
22
+ if !/apps\/services\/a\/\d{2}\.\d$/.match(url.strip)
23
+ self.url = "https://#{hostname}/apps/services/a/#{MIN_Endpoint}"
24
+ elsif MIN_Endpoint.to_f > url.scan(/(\d{2}\.\d)$/).dig(0,0).to_f
25
+ self.url = url.gsub(/(\d{2}\.\d)$/, MIN_Endpoint)
26
+ else
27
+ self.url = url
28
+ end
29
+ self.entity_id = get_entity_id(entity_id: entity_id)
30
+ self.errors = Hash.new
31
+ self.current_session = session
32
+ self.bearer_token = bearer_token
33
+ self.oauth_session_expires_at = oauth_session_expires_at
34
+ self.status = status.blank? ? "Active" : status
35
+ self.user_info = Hash.new
26
36
  self.update_region
27
37
  self.update_environment
28
38
  self.update_zconnect_provider
@@ -36,21 +46,21 @@ module ZuoraAPI
36
46
  if !zsession.blank?
37
47
  response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
38
48
  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(":")
49
+ elsif zconnect_accesstoken.present?
42
50
  begin
51
+ code = zconnect_accesstoken.split("#!").last
52
+ encrypted_token, tenant_id = Base64.decode64(code).split(":")
43
53
  body = {'token' => encrypted_token}.to_json
44
54
  rescue => ex
45
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie", {}, 400)
55
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie")
46
56
  end
47
57
  response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
48
58
  output_json = JSON.parse(response.body)
49
59
  else
50
60
  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)
61
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
52
62
  else
53
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
63
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
54
64
  end
55
65
  end
56
66
  rescue JSON::ParserError => ex
@@ -64,17 +74,17 @@ module ZuoraAPI
64
74
  zsession = cookies["ZSession"]
65
75
  zconnect_accesstoken = get_zconnect_accesstoken(cookies)
66
76
  begin
67
- if !zsession.blank?
77
+ if zsession.present?
68
78
  response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
69
79
  output_json = JSON.parse(response.body)
70
- elsif !zconnect_accesstoken.blank?
80
+ elsif zconnect_accesstoken.present?
71
81
  response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
72
82
  output_json = JSON.parse(response.body)
73
83
  else
74
84
  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)
85
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
76
86
  else
77
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
87
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
78
88
  end
79
89
  end
80
90
  rescue JSON::ParserError => ex
@@ -96,9 +106,9 @@ module ZuoraAPI
96
106
  output_json = JSON.parse(response.body)
97
107
  else
98
108
  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)
109
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
100
110
  else
101
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
111
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
102
112
  end
103
113
  end
104
114
  rescue JSON::ParserError => ex
@@ -120,9 +130,9 @@ module ZuoraAPI
120
130
  output_json = JSON.parse(response.body)
121
131
  else
122
132
  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)
133
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}")
124
134
  else
125
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
135
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present")
126
136
  end
127
137
  end
128
138
  rescue JSON::ParserError => ex
@@ -170,12 +180,12 @@ module ZuoraAPI
170
180
  if entity_ids.blank? && cookies["ZuoraCurrentEntity"].present?
171
181
  entity_ids = Array(cookies["ZuoraCurrentEntity"].unpack("a8a4a4a4a12").join('-'))
172
182
  else
173
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora Entity ID not provided", {}, 400)
183
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora Entity ID not provided")
174
184
  end
175
185
  if user_id.blank? && cookies["Zuora-User-Id"].present?
176
186
  user_id = cookies["Zuora-User-Id"]
177
187
  else
178
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided", {}, 400)
188
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided")
179
189
  end
180
190
  elsif !client_id.nil? && !client_secret.nil?
181
191
  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'})
@@ -192,12 +202,12 @@ module ZuoraAPI
192
202
  output_json["clientSecret"] = new_client_secret
193
203
  return output_json
194
204
  elsif oauth_response.code == 401 && !oauth_response.message.blank?
195
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], {}, oauth_response.code)
205
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], oauth_response)
196
206
  else
197
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["error"], {}, oauth_response.code)
207
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["error"], oauth_response)
198
208
  end
199
209
  else
200
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Insufficient credentials provided", {}, 400)
210
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Insufficient credentials provided")
201
211
  end
202
212
  end
203
213
 
@@ -257,7 +267,7 @@ module ZuoraAPI
257
267
  if !self.url.blank?
258
268
  if /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/ === self.hostname
259
269
  self.environment = 'Sandbox'
260
- elsif /(?<=\.|\/|^)(service|services[\d]*|ep-edge)(?=\.|\/|$)/ === self.hostname
270
+ elsif /(?<=\.|\/|^)(service[\d]*|services[\d]*|ep-edge)(?=\.|\/|$)/ === self.hostname
261
271
  self.environment = 'Services'
262
272
  elsif /(?<=\.|\/|-|^)(pt[\d]*)(?=\.|\/|-|$)/ === self.hostname
263
273
  self.environment = 'Performance'
@@ -332,17 +342,22 @@ module ZuoraAPI
332
342
  when 'Services'
333
343
  https = /https:\/\/|http:\/\//.match(self.url)[0]
334
344
  host = self.hostname
335
- endpoint = "#{https}#{host}/apps/v1/#{url}"
345
+ endpoint = "#{https}rest#{host}/v1/#{url}"
336
346
  when 'Staging'
337
- endpoint = "https://rest-staging2.zuora.com/".concat(url)
347
+ endpoint = "https://rest-staging2.zuora.com/v1/".concat(url)
338
348
  when 'Unknown'
339
349
  raise "Environment unknown, returning passed in parameter unaltered"
340
350
  end
341
351
  return endpoint
342
352
  end
343
353
 
354
+ def rest_domain
355
+ require 'addressable/uri'
356
+ return ::Addressable::URI.parse(self.rest_endpoint).host
357
+ end
358
+
344
359
  def fileURL(url="")
345
- return self.url.split(".com").first.concat(".com/apps/api/file/").concat(url)
360
+ return self.rest_endpoint("file/").concat(url)
346
361
  end
347
362
 
348
363
  def dateFormat
@@ -353,17 +368,16 @@ module ZuoraAPI
353
368
  end
354
369
 
355
370
  def get_session(prefix: false, auth_type: :basic)
356
- Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}")
371
+ Rails.logger.debug("Get session for #{auth_type} - #{self.class.to_s}") if Rails.env.to_s == 'development'
357
372
  case auth_type
358
373
  when :basic
359
374
  if self.current_session.blank?
360
- Rails.logger.debug("Create new session")
361
375
  case self.class.to_s
362
376
  when 'ZuoraAPI::Oauth'
363
377
  if self.bearer_token.blank? || self.oauth_expired?
364
378
  self.new_session(auth_type: :bearer)
365
379
  end
366
- self.get_z_session
380
+ self.get_z_session if self.status == 'Active'
367
381
  when 'ZuoraAPI::Basic'
368
382
  self.new_session(auth_type: :basic)
369
383
  else
@@ -386,7 +400,7 @@ module ZuoraAPI
386
400
  end
387
401
  end
388
402
 
389
- def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError, ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition], z_session: true, timeout_retry: false, timeout: 120,**keyword_args)
403
+ def soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false, debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS), z_session: true, timeout_retry: false, timeout: 120,**keyword_args)
390
404
  tries ||= 2
391
405
  xml = Nokogiri::XML::Builder.new do |xml|
392
406
  xml['SOAP-ENV'].Envelope('xmlns:SOAP-ENV' => "http://schemas.xmlsoap.org/soap/envelope/",
@@ -436,7 +450,7 @@ module ZuoraAPI
436
450
  return output_xml, input_xml, response
437
451
  end
438
452
  end
439
- rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
453
+ rescue *ZUORA_API_ERRORS => ex
440
454
  if errors.include?(ex.class)
441
455
  raise ex
442
456
  else
@@ -458,6 +472,12 @@ module ZuoraAPI
458
472
  else
459
473
  raise ex
460
474
  end
475
+ rescue Errno::ECONNRESET => ex
476
+ if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
477
+ retry
478
+ else
479
+ raise ex
480
+ end
461
481
  rescue => ex
462
482
  raise ex
463
483
  else
@@ -499,94 +519,107 @@ module ZuoraAPI
499
519
  if error.class == String
500
520
  case error
501
521
  when "INVALID_SESSION"
502
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{error}::#{message}", body, response.code )
522
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{error}::#{message}", response)
503
523
  when "REQUEST_EXCEEDED_LIMIT"
504
- raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{error}::#{message}", body, response.code)
524
+ raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{error}::#{message}", response)
505
525
  when "LOCK_COMPETITION"
506
- raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", body, response.code)
526
+ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
507
527
  when "BATCH_FAIL_ERROR"
508
528
  if message.include?("optimistic locking failed")
509
- raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", body, response.code)
529
+ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{error}::#{message}", response)
510
530
  else
511
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code)
531
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
512
532
  end
513
533
  when "TEMPORARY_ERROR"
514
- raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{error}::#{message}", body, response.code)
534
+ raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{error}::#{message}", response)
535
+ when "INVALID_VALUE"
536
+ if message.include?("data integrity violation")
537
+ raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
538
+ else
539
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response)
540
+ end
515
541
  else
516
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", body, response.code) if error.present?
542
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{error}::#{message}", response) if error.present?
517
543
  end
518
544
  elsif error.class == Array
519
- if error[0].include?("LOCK_COMPETITION") && error.count == 1
520
- raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), body, response.code)
521
- else
522
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), body, response.code, error, success)
523
- end
545
+ if error[0].include?("LOCK_COMPETITION") && error.count == 1
546
+ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), response)
547
+ else
548
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(error.group_by {|v| v}.map {|k,v| "(#{v.size}x) - #{k == "::" ? 'UNKNOWN::No error provided' : k}"}.join(', '), response, error, success)
549
+ end
524
550
  end
525
551
  end
526
-
552
+
527
553
  if response.code == 429
528
- raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("The total number of concurrent requests has exceeded the limit allowed by the system. Please resubmit your request later.", body, response.code)
554
+ raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("The total number of concurrent requests has exceeded the limit allowed by the system. Please resubmit your request later.", response)
529
555
  end
530
556
 
531
557
  when :JSON
532
558
  body = body.dig("results").present? ? body["results"] : body if body.class == Hash
533
559
  if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
534
- messages_array = (body["reasons"] || []).map {|error| error['message']}.compact
535
- codes_array = (body["reasons"] || []).map {|error| error['code']}.compact
560
+ messages_array = body.fetch("reasons", []).map {|error| error['message']}.compact
561
+ messages_array = messages_array.push(body.dig("error", 'message')).compact if body.dig('error').class == Hash
562
+ codes_array = body.fetch("reasons", []).map {|error| error['code']}.compact
563
+ codes_array = codes_array.push(body.dig("error", 'code')).compact if body.dig('error').class == Hash
536
564
 
537
565
  if body['message'] == "No bearer token" && response.code == 400
538
- raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new()
566
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Authentication type is not supported by this Login", response)
539
567
  end
540
568
 
541
569
  if body['errorMessage']
542
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errorMessage'],body,response.code)
570
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errorMessage'], response)
543
571
  end
544
572
 
545
573
  if body.dig("reasons").nil? ? false : body.dig("reasons")[0].dig("code") == 90000020
546
- raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", body, response.code)
574
+ raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", response)
575
+ end
576
+
577
+ #Oauth Tokens - User deactivated
578
+ if body['message'] == 'Forbidden' && body['status'] == 403 && response.code == 403
579
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Forbidden", response)
547
580
  end
548
581
 
549
- if body['error'] == 'Unauthorized' && body['status'] = 401
550
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
582
+ if body['error'] == 'Unauthorized' && body['status'] == 401
583
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
551
584
  end
552
585
  #Authentication failed
553
- if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401
554
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", body, response.code)
586
+ if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422)
587
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{messages_array.join(', ')}", response)
555
588
  end
556
589
 
557
590
  #Zuora REST Create Amendment error #Authentication failed
558
591
  if body["faultcode"].present? && body["faultcode"] == "fns:INVALID_SESSION"
559
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body['faultstring']}", body, response.code)
592
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body['faultstring']}", response)
560
593
  end
561
594
 
562
595
  #Request exceeded limit
563
596
  if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70)
564
- raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", body, response.code)
597
+ raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{messages_array.join(', ')}", response)
565
598
  end
566
599
 
567
600
  #Locking contention
568
601
  if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50)
569
- raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", body, response.code)
570
- end
602
+ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{messages_array.join(', ')}", response)
603
+ end
571
604
 
572
605
  #All Errors catch
573
606
  if codes_array.size > 0
574
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages_array.join(', ')}", body, response.code)
607
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages_array.join(', ')}", response)
575
608
  end
576
609
 
577
610
  #Zuora REST Query Errors
578
611
  if body["faultcode"].present?
579
612
  case body["faultcode"]
580
613
  when "fns:MALFORMED_QUERY"
581
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
614
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
582
615
  when "fns:REQUEST_EXCEEDED_LIMIT"
583
- raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
616
+ raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
584
617
  when "fns:LOCK_COMPETITION"
585
- raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
618
+ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
586
619
  when "INVALID_SESSION"
587
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
620
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
588
621
  else
589
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", body, response.code)
622
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{body["faultcode"]}::#{body["faultstring"]}", response)
590
623
  end
591
624
  end
592
625
 
@@ -595,7 +628,7 @@ module ZuoraAPI
595
628
  (body["Errors"] || []).select { |obj| errors.push(obj["Message"]) }.compact
596
629
  (body["errors"] || []).select { |obj| errors.push(obj["Message"]) }.compact
597
630
  if errors.size > 0
598
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{errors.join(", ")}", body, response.code, errors)
631
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{errors.join(", ")}", response, errors)
599
632
  end
600
633
  end
601
634
  end
@@ -607,22 +640,27 @@ module ZuoraAPI
607
640
 
608
641
  if all_success.blank? && all_errors.present?
609
642
  error_codes = all_errors.flatten.group_by {|error| error['Code']}.keys.uniq
610
- if error_codes.size == 1 && error_codes[0] == "LOCK_COMPETITION"
611
- raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", body, response.code)
643
+ error_messages = all_errors.flatten.group_by {|error| error['Message']}.keys.uniq
644
+ if error_codes.size == 1 || error_messages.size == 1
645
+ if error_codes.first == "LOCK_COMPETITION"
646
+ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", response)
647
+ elsif error_messages.first.include?("data integrity violation")
648
+ raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response)
649
+ end
612
650
  end
613
651
  end
614
652
 
615
653
  if all_errors.size > 0
616
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{all_errors.flatten.group_by {|error| error['Message']}.keys.uniq.join(' ')}", body, response.code, all_errors, all_success )
654
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{all_errors.flatten.group_by {|error| error['Message']}.keys.uniq.join(' ')}", response, all_errors, all_success)
617
655
  end
618
656
  end
619
657
 
620
658
  #All other errors
621
- if response.code != 200
659
+ if ![200,201].include?(response.code)
622
660
  if response.code == 429
623
- raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("The total number of concurrent requests has exceeded the limit allowed by the system. Please resubmit your request later.", body, response.code)
661
+ raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("The total number of concurrent requests has exceeded the limit allowed by the system. Please resubmit your request later.", response)
624
662
  else
625
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{response.message}", body, response.code)
663
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{response.message}", response)
626
664
  end
627
665
  end
628
666
  end
@@ -645,7 +683,7 @@ module ZuoraAPI
645
683
  }
646
684
  response = self.rest_call(method: :post, body: params.to_json, url: self.aqua_endpoint("batch-query/"))
647
685
  if(response[0]["id"].nil?)
648
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error in AQuA Process. #{response}")
686
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error in AQuA Process.", response)
649
687
  end
650
688
  return getFileById(id: response[0]["id"])
651
689
  end
@@ -658,7 +696,7 @@ module ZuoraAPI
658
696
  response, fullResponse = self.rest_call(method: :get, body: {}, url: self.aqua_endpoint("batch-query/jobs/#{id}"))
659
697
  result = response["batches"][0]["status"]
660
698
  if result == "error"
661
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Aqua Error: #{response}")
699
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Aqua Error", response)
662
700
  break
663
701
  end
664
702
  end
@@ -666,7 +704,7 @@ module ZuoraAPI
666
704
  return self.get_file(url: self.aqua_endpoint("file/#{fileId}"))
667
705
  end
668
706
 
669
- def describe_call(object = nil)
707
+ def describe_call(object = nil, log_errors = true)
670
708
  tries ||= 2
671
709
 
672
710
  base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
@@ -674,7 +712,7 @@ module ZuoraAPI
674
712
  headers = self.entity_id.present? ? {"Zuora-Entity-Ids" => self.entity_id, 'Content-Type' => "text/xml; charset=utf-8"} : {'Content-Type' => "text/xml; charset=utf-8"}
675
713
  response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic)}.merge(headers), :timeout => 120)
676
714
 
677
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401' ) if response.code == 401
715
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
678
716
 
679
717
  output_xml = Nokogiri::XML(response.body)
680
718
  des_hash = Hash.new
@@ -714,11 +752,12 @@ module ZuoraAPI
714
752
  raise ex
715
753
  end
716
754
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
717
- if !(tries -= 1).zero?
718
- Rails.logger.info("Session expired. Starting new session.")
755
+ if !(tries -= 1).zero? && self.status == 'Active'
756
+ Rails.logger.debug("Describe session expired. Starting new session.")
719
757
  self.new_session
720
758
  retry
721
759
  else
760
+ Rails.logger.error("Describe session expired. Starting new session.") if log_errors
722
761
  raise ex
723
762
  end
724
763
  rescue => ex
@@ -727,7 +766,7 @@ module ZuoraAPI
727
766
  return des_hash
728
767
  end
729
768
 
730
- 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)
769
+ def rest_call(method: :get, body: nil, headers: {}, url: rest_endpoint("catalog/products?pageSize=4"), debug: false, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS), z_session: true, session_type: :basic, timeout_retry: false, timeout: 120, **keyword_args)
731
770
  tries ||= 2
732
771
 
733
772
  if self.entity_id.present?
@@ -738,9 +777,9 @@ module ZuoraAPI
738
777
  raise "Method not supported, supported methods include: :get, :post, :put, :delete, :patch, :head, :options" if ![:get, :post, :put, :delete, :patch, :head, :options].include?(method)
739
778
 
740
779
  authentication_headers = z_session ? {"Authorization" => self.get_session(prefix: true, auth_type: session_type) } : {}
741
- headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(headers).merge(authentication_headers)
780
+ modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
742
781
 
743
- response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: headers, timeout: timeout).perform
782
+ response = HTTParty::Request.new("Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: modified_headers, timeout: timeout).perform
744
783
  Rails.logger.debug("Response Code: #{response.code}") if debug
745
784
  begin
746
785
  output_json = JSON.parse(response.body)
@@ -751,8 +790,8 @@ module ZuoraAPI
751
790
 
752
791
  raise_errors(type: :JSON, body: output_json, response: response)
753
792
  rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
754
- if self.class.to_s == 'ZuoraAPI::Oauth'
755
- 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)
793
+ if self.class.to_s == 'ZuoraAPI::Oauth' && ex.message.include?("Authentication type is not supported by this Login")
794
+ self.rest_call(method: method.to_sym, url: url, body: body, debug: debug, errors: errors, z_session: z_session, session_type: :bearer, timeout_retry: timeout_retry, timeout: timeout)
756
795
  else
757
796
  Rails.logger.debug("Rest Call - Session Bad Auth type")
758
797
  raise ex
@@ -769,7 +808,7 @@ module ZuoraAPI
769
808
  return [output_json, response]
770
809
  end
771
810
  end
772
- rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
811
+ rescue *ZUORA_API_ERRORS => ex
773
812
  if errors.include?(ex.class)
774
813
  raise ex
775
814
  else
@@ -793,6 +832,12 @@ module ZuoraAPI
793
832
  else
794
833
  raise ex
795
834
  end
835
+ rescue Errno::ECONNRESET => ex
836
+ if !(tries -= 1).zero? && ex.message.include?('SSL_connect')
837
+ retry
838
+ else
839
+ raise ex
840
+ end
796
841
  rescue => ex
797
842
  raise ex
798
843
  else
@@ -820,7 +865,7 @@ module ZuoraAPI
820
865
  Rails.logger.debug("Fetch Catalog URL #{url}")
821
866
  output_json, response = self.rest_call(:debug => false, :url => url, :errors => [ZuoraAPI::Exceptions::ZuoraAPISessionError], :timeout_retry => true )
822
867
  if !output_json['success'] =~ (/(true|t|yes|y|1)$/i) || output_json['success'].class != TrueClass
823
- raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}")
868
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response)
824
869
  end
825
870
  output_json["products"].each do |product|
826
871
  catalog_map[product["id"]] = {"productId" => product["id"]}
@@ -845,7 +890,7 @@ module ZuoraAPI
845
890
  return products, catalog_map
846
891
  end
847
892
 
848
- def get_file(url: nil, headers: {}, count: 3, z_session: true, tempfile: true, output_file_name: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 2, timeout: 120, session_type: :basic, force_encoding: true, **execute_params)
893
+ def get_file(url: nil, headers: {}, count: 3, z_session: true, tempfile: true, output_file_name: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 2, timeout: 120, session_type: :basic, **execute_params)
849
894
  raise "file_path must be of class Pathname" if file_path.class != Pathname
850
895
 
851
896
  #Make sure directory exists
@@ -857,7 +902,7 @@ module ZuoraAPI
857
902
  uri = URI.parse(url)
858
903
  http = Net::HTTP.new(uri.host, uri.port)
859
904
  http.read_timeout = timeout #Seconds
860
- http.use_ssl = true if uri.scheme.downcase == 'https'
905
+ http.use_ssl = true if !uri.scheme.nil? && uri.scheme.downcase == 'https'
861
906
  if z_session
862
907
  headers = headers.merge({"Authorization" => self.get_session(prefix: true)})
863
908
  headers = headers.merge({"Zuora-Entity-Ids" => self.entity_id}) if !self.entity_id.blank?
@@ -871,7 +916,6 @@ module ZuoraAPI
871
916
 
872
917
  case response
873
918
  when Net::HTTPNotFound
874
- Rails.logger.fatal("404 - Not Found")
875
919
  raise
876
920
 
877
921
  when Net::HTTPUnauthorized
@@ -882,9 +926,8 @@ module ZuoraAPI
882
926
  raise
883
927
  end
884
928
  end
885
- Rails.logger.fatal("Unauthorized: Retry")
886
929
  self.new_session if z_session
887
- 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, :force_encoding => force_encoding)
930
+ 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)
888
931
 
889
932
  when Net::HTTPClientError
890
933
  raise
@@ -949,11 +992,7 @@ module ZuoraAPI
949
992
  file_handle.binmode
950
993
 
951
994
  response.read_body do |chunk|
952
- if force_encoding
953
- file_handle << chunk.force_encoding(encoding)
954
- else
955
- file_handle << chunk
956
- end
995
+ file_handle << chunk
957
996
 
958
997
  if defined?(export_size) && export_size != 0 && export_size.class == Integer
959
998
  size += chunk.size
@@ -980,16 +1019,13 @@ module ZuoraAPI
980
1019
  raise
981
1020
  end
982
1021
  end
983
- rescue Exception => e
984
- Rails.logger.fatal("Download Failed: #{response_save} - #{e.class} : #{e.message}")
985
- Rails.logger.fatal("Download Failed: #{e.backtrace.join("\n")}")
1022
+ rescue => ex
1023
+ Rails.logger.fatal(ex)
986
1024
  raise
987
1025
  end
988
1026
  end
989
1027
 
990
1028
  def getDataSourceExport(query, extract: true, encrypted: false, zip: true)
991
- Rails.logger.debug("Build export")
992
- Rails.logger.debug("#{query}")
993
1029
  request = Nokogiri::XML::Builder.new do |xml|
994
1030
  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
995
1031
  xml['SOAP-ENV'].Header do
@@ -1044,7 +1080,6 @@ module ZuoraAPI
1044
1080
  end
1045
1081
 
1046
1082
  file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text
1047
- Rails.logger.debug('=====> Export finished')
1048
1083
  export_file = get_file(:url => self.fileURL(file_id))
1049
1084
  export_file_path = export_file.path
1050
1085
  Rails.logger.debug("=====> Export path #{export_file.path}")
@@ -1063,7 +1098,6 @@ module ZuoraAPI
1063
1098
  end
1064
1099
 
1065
1100
  def query(query, parse = false)
1066
- Rails.logger.debug("Querying Zuora for #{query}")
1067
1101
  output_xml, input_xml = self.soap_call({:debug => false, :timeout_retry => true}) do |xml|
1068
1102
  xml['ns1'].query do
1069
1103
  xml['ns1'].queryString query
@@ -1,15 +1,17 @@
1
1
  module ZuoraAPI
2
2
  class Basic < Login
3
- attr_accessor :username, :password
4
- def initialize(username: nil, password: nil, **keyword_args)
5
- @username = username
6
- @password = password
3
+ attr_accessor :username, :password, :session
4
+ def initialize(username: nil, password: nil, session: nil, **keyword_args)
5
+ self.username = username
6
+ self.password = password
7
+ self.current_session = session
8
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Basic Login but either 'Username' or 'Password' were not passed.") if self.current_session.blank? && (self.password.blank? && self.username.blank?)
7
9
  super
8
10
  end
9
11
 
10
- def new_session( auth_type: :basic, debug: false)
12
+ def new_session(auth_type: :basic, debug: false)
11
13
  raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") if auth_type != :basic
12
- raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login requires username and password to be set.") if auth_type == :basic && (self.password.blank? && self.username.blank?)
14
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Basic Login but either 'Username' or 'Password' were not passed.") if (self.password.blank? && self.username.blank?)
13
15
 
14
16
  tries ||= 2
15
17
  request = Nokogiri::XML::Builder.new do |xml|
@@ -27,16 +29,16 @@ module ZuoraAPI
27
29
 
28
30
  input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
29
31
  input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
30
- Rails.logger.debug('Connect') {"Request Code: #{@response_query.code} SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
32
+ Rails.logger.debug('Connect') {"SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
31
33
 
32
- @response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => 10)
33
- @output_xml = Nokogiri::XML(@response_query.body)
34
- Rails.logger.debug('Connect') {"Response Code: #{@response_query.code} SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
34
+ response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => 10)
35
+ output_xml = Nokogiri::XML(response_query.body)
36
+ Rails.logger.debug('Connect') {"Response Code: #{response_query.code} SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
35
37
 
36
- if !@response_query.success?
38
+ if !response_query.success?
37
39
  self.current_session = nil
38
- if @output_xml.namespaces.size > 0 && @output_xml.xpath('//soapenv:Fault').size > 0
39
- self.current_error = @output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
40
+ if output_xml.namespaces.size > 0 && output_xml.xpath('//soapenv:Fault').size > 0
41
+ self.current_error = output_xml.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text
40
42
  if self.current_error.include?('deactivated')
41
43
  self.status = 'Deactivated'
42
44
  self.current_error = 'Deactivated user login, please check with Zuora tenant administrator'
@@ -75,19 +77,19 @@ module ZuoraAPI
75
77
  self.errors[:base] = self.current_error
76
78
  else
77
79
  self.status = 'Unknown'
78
- self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
80
+ self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
79
81
  self.errors[:base] = self.current_error
80
82
  end
81
83
 
82
84
  else
83
85
  self.status = 'Unknown'
84
- self.current_error = @output_xml.xpath('//faultstring').text if self.current_error.blank?
86
+ self.current_error = output_xml.xpath('//faultstring').text if self.current_error.blank?
85
87
  self.errors[:base] = self.current_error
86
88
  end
87
89
  else
88
90
  #Username & password combo
89
- retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
90
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
91
+ retrieved_session = output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
92
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.", response_query) if retrieved_session.blank?
91
93
  self.status = 'Active'
92
94
  self.current_session = retrieved_session
93
95
  end
@@ -5,9 +5,9 @@ module ZuoraAPI
5
5
  def initialize(oauth_client_id: nil, oauth_secret: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args)
6
6
  self.oauth_client_id = oauth_client_id
7
7
  self.oauth_secret = oauth_secret
8
- self.bearer_token = bearer_token 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?
8
+ self.bearer_token = bearer_token
9
+ self.oauth_session_expires_at = oauth_session_expires_at
10
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if self.bearer_token.blank? && (self.oauth_client_id.blank? || self.oauth_secret.blank?)
11
11
  super
12
12
  end
13
13
 
@@ -16,10 +16,10 @@ module ZuoraAPI
16
16
  get_bearer_token()
17
17
  elsif auth_type == :basic
18
18
  get_bearer_token() if self.oauth_expired?
19
- get_z_session()
19
+ get_z_session() if self.status == 'Active'
20
20
  else
21
21
  get_bearer_token()
22
- get_z_session()
22
+ get_z_session() if self.status == 'Active'
23
23
  end
24
24
  return self.status
25
25
  end
@@ -66,6 +66,8 @@ module ZuoraAPI
66
66
 
67
67
  def get_bearer_token
68
68
  tries ||= 2
69
+ raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if self.oauth_client_id.blank? || self.oauth_secret.blank?
70
+
69
71
  output_json, response = self.rest_call(:method => :post,
70
72
  :url => self.rest_endpoint.chomp('v1/').concat("oauth/token"),
71
73
  :z_session => false,
@@ -83,15 +85,19 @@ module ZuoraAPI
83
85
  rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex
84
86
  self.bearer_token = nil
85
87
  self.oauth_session_expires_at = nil
86
- self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
87
- self.status = 'Invalid Login'
88
- return self.status
89
- rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
90
- if errors.include?(ex.class)
91
- raise ex
88
+ self.current_error = ex.message
89
+ case ex.message
90
+ when "Forbidden"
91
+ self.current_error = "The user associated to OAuth credential, '#{self.oauth_client_id}', set has been deactivated."
92
+ self.status = 'Deactivated'
92
93
  else
93
- return [output_json, response]
94
+ self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint"
95
+ self.status = 'Invalid Login'
94
96
  end
97
+
98
+ return self.status
99
+ rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex
100
+ raise ex
95
101
  rescue *(CONNECTION_EXCEPTIONS).concat(CONNECTION_READ_EXCEPTIONS) => ex
96
102
  if !(tries -= 1).zero?
97
103
  Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"}
@@ -1,3 +1,3 @@
1
1
  module ZuoraAPI
2
- VERSION = "1.6.255"
2
+ VERSION = "1.7.00"
3
3
  end
@@ -26,5 +26,5 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency("nokogiri")
27
27
  spec.add_dependency("httparty")
28
28
  spec.add_dependency("rubyzip")
29
- spec.add_dependency("railties", ">= 4.1.0", "< 5.2")
29
+ spec.add_dependency("railties", ">= 4.1.0", "< 6")
30
30
  end
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.255
4
+ version: 1.7.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: 2019-03-12 00:00:00.000000000 Z
11
+ date: 2019-08-05 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.2'
134
+ version: '6'
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.2'
144
+ version: '6'
145
145
  description: Gem that provides easy integration to Zuora
146
146
  email:
147
147
  - connect@zuora.com
@@ -186,8 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
186
  - !ruby/object:Gem::Version
187
187
  version: '0'
188
188
  requirements: []
189
- rubyforge_project:
190
- rubygems_version: 2.6.8
189
+ rubygems_version: 3.0.3
191
190
  signing_key:
192
191
  specification_version: 4
193
192
  summary: Gem that provides easy integration to Zuora