zuora_api 1.6.255 → 1.7.00

Sign up to get free protection for your applications and to get access to all the features.
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