zuora_api 1.6.25 → 1.6.26

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
2
  SHA1:
3
- metadata.gz: e550dd86e9507f9652c0523af913d907dfefa22f
4
- data.tar.gz: 66c1f11eda0adab384baf5d2a970ccf72163fe25
3
+ metadata.gz: e86b5da627b9f51c342da05d5e4110e3385a35a4
4
+ data.tar.gz: 9ccf40e8d6dfca789d16207421dc07352ad8c921
5
5
  SHA512:
6
- metadata.gz: adedd68525df111f61712740df8d292578e883320e4b15f508087dea1e684d59eebd8eb09ff45e2fed64d7da277e73f1dad3d3182eb40a9164b465320fdfdbd1
7
- data.tar.gz: 260d9b579be019134023fd270003341ed471f6d2897a02d2cae100fe8dcfc306b2723dc5793a0dec2be4e5d1e9235eeaa5c064764394a16729f8e3fc2c86e87e
6
+ metadata.gz: 35a3fb0d447a8a52d11762133e0fe11cccea7e5970c74aa31bc121153dc62d3aece97adaf08fa1a8cc6562c5eee2b74c9c24144ff981d503083530b10c1e3bb3
7
+ data.tar.gz: ef0b5f9af4d236df06de046d3afd6e8e649a007281036c9770df4cb289d31df99f3f1ae535eae55ff28154b6f098b60e0e46f90724b894d0b1dc27a0743b3795
data/CHANGELOG.md CHANGED
@@ -11,12 +11,6 @@ All notable changes to this project will be documented in this file.
11
11
  ### Removed
12
12
  - Example
13
13
 
14
- ## [1.6.22] - 2019-01-03
15
-
16
- ### Changed
17
- - get_identity method - supports ZSession auth now
18
- - updated rspecs accordingly
19
-
20
14
  ## [1.6.18] - 2018-12-06
21
15
  ### Added
22
16
  - zconnect_provider attribute accessor for identifying ZConnect cookies
@@ -30,4 +24,15 @@ All notable changes to this project will be documented in this file.
30
24
  ### Changed
31
25
  - The way environment and region are set
32
26
 
27
+ ## [1.6.22] - 2019-01-03
33
28
 
29
+ ### Changed
30
+ - get_identity method - supports ZSession auth now
31
+ - updated rspecs accordingly
32
+
33
+ ## [1.6.26] - 2019-03-04
34
+
35
+ ### Changed
36
+ - fixed get_oauth_client for non-staging environments
37
+ - fixed to use correct rest endpoint without version for oauth creation api
38
+ - changed get_oauth_client to no longer accept client id and secret as parameters
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- zuora_api (1.6.25)
4
+ zuora_api (1.6.26)
5
5
  httparty
6
6
  nokogiri
7
7
  railties (>= 4.1.0, < 5.2)
@@ -42,7 +42,7 @@ GEM
42
42
  httparty (0.16.4)
43
43
  mime-types (~> 3.0)
44
44
  multi_xml (>= 0.5.2)
45
- i18n (1.5.3)
45
+ i18n (1.6.0)
46
46
  concurrent-ruby (~> 1.0)
47
47
  json (2.1.0)
48
48
  loofah (2.2.3)
@@ -156,13 +156,11 @@ module ZuoraAPI
156
156
  end
157
157
 
158
158
  # There are two ways to call this method. The first way is best.
159
- # 1. Pass in cookies and optionally custom_authorities, name, and description
160
- # 2. Pass in user_id, entity_ids, client_id, client_secret, and optionally custom_authorities, name, and description
159
+ # 1. Pass in cookies, name, and description
160
+ # 2. Pass in user_id, entity_ids, an existing client_id and client_secret, name, and description
161
161
  # https://intranet.zuora.com/confluence/display/Sunburst/Create+an+OAuth+Client+through+API+Gateway#CreateanOAuthClientthroughAPIGateway-ZSession
162
- def get_oauth_client (custom_authorities = [], info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, new_client_id: nil, new_client_secret: nil, cookies: nil)
162
+ def get_oauth_client (info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, cookies: nil)
163
163
  authorization = ""
164
- new_client_id = SecureRandom.uuid if new_client_id.blank?
165
- new_client_secret = SecureRandom.hex(10) if new_client_secret.blank?
166
164
 
167
165
  if !cookies.nil?
168
166
  authorization = cookies["ZSession"]
@@ -178,18 +176,18 @@ module ZuoraAPI
178
176
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided", {}, 400)
179
177
  end
180
178
  elsif !client_id.nil? && !client_secret.nil?
181
- bearer_response = HTTParty.post("https://#{self.hostname}/oauth/token", :headers => {'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => 'application/json'}, :body => {'client_id' => client_id, 'client_secret' => URI::encode(client_secret), 'grant_type' => 'client_credentials'})
179
+ endpoint = self.rest_endpoint("oauth/token").gsub("v1/", "")
180
+ bearer_response = HTTParty.post(endpoint, :headers => {'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => 'application/json'}, :body => {'client_id' => client_id, 'client_secret' => URI::encode(client_secret), 'grant_type' => 'client_credentials'})
182
181
  bearer_hash = JSON.parse(bearer_response.body)
183
182
  bearer_token = bearer_hash["access_token"]
184
183
  authorization = "Bearer #{bearer_token}"
185
184
  end
186
185
 
187
186
  if !authorization.blank? && !user_id.blank? && !entity_ids.blank?
188
- endpoint = self.rest_endpoint("genesis/clients")
189
- oauth_response = HTTParty.post(endpoint, :headers => {'authorization' => authorization, 'Content-Type' => 'application/json'}, :body => {'clientId' => new_client_id, 'clientSecret' => new_client_secret, 'userId' => user_id, 'entityIds' => entity_ids, 'customAuthorities' => custom_authorities, 'additionalInformation' => {'description' => info_desc, 'name' => info_name}}.to_json)
187
+ endpoint = self.rest_endpoint("genesis/clients").gsub("v1/", "")
188
+ oauth_response = HTTParty.post(endpoint, :headers => {'authorization' => authorization, 'Content-Type' => 'application/json'}, :body => {'userId' => user_id, 'entityIds' => entity_ids, 'additionalInformation' => {'description' => info_desc, 'name' => info_name}}.to_json)
190
189
  output_json = JSON.parse(oauth_response.body)
191
190
  if oauth_response.code == 201
192
- output_json["clientSecret"] = new_client_secret
193
191
  return output_json
194
192
  elsif oauth_response.code == 401 && !oauth_response.message.blank?
195
193
  raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], {}, oauth_response.code)
@@ -529,6 +527,7 @@ module ZuoraAPI
529
527
  end
530
528
 
531
529
  when :JSON
530
+ body = body.dig("results").present? ? body["results"] : body if body.class == Hash
532
531
  if body.class == Hash && (!body["success"] || !body["Success"] || response.code != 200)
533
532
  messages_array = (body["reasons"] || []).map {|error| error['message']}.compact
534
533
  codes_array = (body["reasons"] || []).map {|error| error['code']}.compact
@@ -599,7 +598,7 @@ module ZuoraAPI
599
598
  end
600
599
  end
601
600
 
602
- #Zuora REST Actions error (Create, Update, Delete)
601
+ #Zuora REST Actions error (Create, Update, Delete, Amend)
603
602
  if body.class == Array
604
603
  all_errors = body.select {|obj| !obj['Success'] || !obj['success'] }.map {|obj| obj['Errors'] || obj['errors'] }.compact
605
604
  all_success = body.select {|obj| obj['Success'] || obj['success']}.compact
@@ -863,110 +862,116 @@ module ZuoraAPI
863
862
  end
864
863
 
865
864
  response_save = nil
866
- http.request_get(uri.request_uri, headers) do |response|
867
- response_save = response
868
- status_code = response.code if response
869
-
870
- case response
871
- when Net::HTTPNotFound
872
- Rails.logger.fatal("404 - Not Found")
873
- raise
874
-
875
- when Net::HTTPUnauthorized
876
- if count <= 0
877
- if z_session
878
- raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
879
- else
880
- raise
865
+ begin
866
+ http.request_get(uri.request_uri, headers) do |response|
867
+ response_save = response
868
+ status_code = response.code if response
869
+
870
+ case response
871
+ when Net::HTTPNotFound
872
+ Rails.logger.fatal("404 - Not Found")
873
+ raise
874
+
875
+ when Net::HTTPUnauthorized
876
+ if count <= 0
877
+ if z_session
878
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error)
879
+ else
880
+ raise
881
+ end
881
882
  end
882
- end
883
- Rails.logger.fatal("Unauthorized: Retry")
884
- self.new_session if z_session
885
- 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)
883
+ Rails.logger.fatal("Unauthorized: Retry")
884
+ self.new_session if z_session
885
+ 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)
886
886
 
887
- when *(CONNECTION_EXCEPTIONS).concat(CONNECTION_READ_EXCEPTIONS)
888
- Rails.logger.fatal("#{response.class} timeout - retry")
889
- return get_file(:url => url, :headers => headers, :count => count, :z_session => z_session, :tempfile => tempfile, :file_path => file_path, :timeout_retries => timeout_retries - 1, :timeout => timeout)
887
+ when Net::HTTPClientError
888
+ raise
890
889
 
891
- when Net::HTTPClientError
892
- raise
890
+ when Net::HTTPOK
891
+ headers = {}
892
+ response.each_header do |k,v|
893
+ headers[k] = v
894
+ end
895
+ Rails.logger.debug("Headers: #{headers.to_s}")
893
896
 
894
- when Net::HTTPOK
895
- headers = {}
896
- response.each_header do |k,v|
897
- headers[k] = v
898
- end
899
- Rails.logger.debug("Headers: #{headers.to_s}")
897
+ if output_file_name.present?
898
+ file_ending ||= output_file_name.end_with?(".csv.zip") ? ".csv.zip" : File.extname(output_file_name)
899
+ filename ||= File.basename(output_file_name, file_ending)
900
+ end
900
901
 
901
- if output_file_name.present?
902
- file_ending ||= output_file_name.end_with?(".csv.zip") ? ".csv.zip" : File.extname(output_file_name)
903
- filename ||= File.basename(output_file_name, file_ending)
904
- end
902
+ size, export_progress = [0, 0]
903
+ encoding, type, full_filename = [nil, nil, nil]
904
+ if response.header["Content-Disposition"].present?
905
+ case response.header["Content-Disposition"]
906
+ when /.*; filename\*=.*/
907
+ full_filename ||= /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[2].strip
908
+ encoding = /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[1].strip
909
+ when /.*; filename=/
910
+ full_filename ||= /.*; filename=(.*)/.match(response.header["Content-Disposition"])[1].strip
911
+ else
912
+ raise "Can't parse Content-Disposition header: #{response.header["Content-Disposition"]}"
913
+ end
914
+ file_ending ||= full_filename.end_with?(".csv.zip") ? ".csv.zip" : File.extname(full_filename)
915
+ filename ||= File.basename(full_filename, file_ending)
916
+ end
905
917
 
906
- size, export_progress = [0, 0]
907
- encoding, type, full_filename = [nil, nil, nil]
908
- if response.header["Content-Disposition"].present?
909
- case response.header["Content-Disposition"]
910
- when /.*; filename\*=.*/
911
- full_filename ||= /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[2].strip
912
- encoding = /.*; filename\*=(.*)''(.*)/.match(response.header["Content-Disposition"])[1].strip
913
- when /.*; filename=/
914
- full_filename ||= /.*; filename=(.*)/.match(response.header["Content-Disposition"])[1].strip
915
- else
916
- raise "Can't parse Content-Disposition header: #{response.header["Content-Disposition"]}"
918
+ #If user supplied a filename use it, else default to content header filename, else default to uri pattern
919
+ file_ending ||= uri.path.end_with?(".csv.zip") ? ".csv.zip" : File.extname(uri.path)
920
+ filename ||= File.basename(uri.path, file_ending)
921
+
922
+ if response.header["Content-Type"].present?
923
+ case response.header["Content-Type"]
924
+ when /.*;charset=.*/
925
+ type = /(.*);charset=(.*)/.match(response.header["Content-Type"])[1]
926
+ encoding = /(.*);charset=(.*)/.match(response.header["Content-Type"])[2]
927
+ else
928
+ type = response.header["Content-Type"]
929
+ encoding ||= 'UTF-8'
930
+ end
917
931
  end
918
- file_ending ||= full_filename.end_with?(".csv.zip") ? ".csv.zip" : File.extname(full_filename)
919
- filename ||= File.basename(full_filename, file_ending)
920
- end
932
+ Rails.logger.info("File: #{filename}#{file_ending} #{encoding} #{type}")
921
933
 
922
- #If user supplied a filename use it, else default to content header filename, else default to uri pattern
923
- file_ending ||= uri.path.end_with?(".csv.zip") ? ".csv.zip" : File.extname(uri.path)
924
- filename ||= File.basename(uri.path, file_ending)
934
+ if response.header["Content-Length"].present?
935
+ export_size = response.header["Content-Length"].to_i
936
+ elsif response.header["ContentLength"].present?
937
+ export_size = response.header["ContentLength"].to_i
938
+ end
925
939
 
926
- if response.header["Content-Type"].present?
927
- case response.header["Content-Type"]
928
- when /.*;charset=.*/
929
- type = /(.*);charset=(.*)/.match(response.header["Content-Type"])[1]
930
- encoding = /(.*);charset=(.*)/.match(response.header["Content-Type"])[2]
940
+ file_prefix = add_timestamp ? "#{filename}_#{Time.now.to_i}" : filename
941
+ if tempfile
942
+ require 'tempfile'
943
+ file_handle = ::Tempfile.new([file_prefix, "#{file_ending}"], file_path)
931
944
  else
932
- type = response.header["Content-Type"]
933
- encoding ||= 'UTF-8'
945
+ file_handle = File.new(file_path.join("#{file_prefix}#{file_ending}"), "w+")
934
946
  end
935
- end
936
- Rails.logger.info("File: #{filename}#{file_ending} #{encoding} #{type}")
937
-
938
- if response.header["Content-Length"].present?
939
- export_size = response.header["Content-Length"].to_i
940
- elsif response.header["ContentLength"].present?
941
- export_size = response.header["ContentLength"].to_i
942
- end
943
-
944
- file_prefix = add_timestamp ? "#{filename}_#{Time.now.to_i}" : filename
945
- if tempfile
946
- require 'tempfile'
947
- file_handle = ::Tempfile.new([file_prefix, "#{file_ending}"], file_path)
948
- else
949
- file_handle = File.new(file_path.join("#{file_prefix}#{file_ending}"), "w+")
950
- end
951
- file_handle.binmode
952
-
953
- response.read_body do |chunk|
954
- file_handle << chunk.force_encoding(encoding)
955
-
956
- if defined?(export_size) && export_size != 0 && export_size.class == Integer
957
- size += chunk.size
958
- new_progress = (size * 100) / export_size
959
- unless new_progress == export_progress
960
- Rails.logger.debug("Login: Export Downloading %s (%3d%%)" % [filename, new_progress])
947
+ file_handle.binmode
948
+
949
+ response.read_body do |chunk|
950
+ file_handle << chunk.force_encoding(encoding)
951
+
952
+ if defined?(export_size) && export_size != 0 && export_size.class == Integer
953
+ size += chunk.size
954
+ new_progress = (size * 100) / export_size
955
+ unless new_progress == export_progress
956
+ Rails.logger.debug("Login: Export Downloading %s (%3d%%)" % [filename, new_progress])
957
+ end
958
+ export_progress = new_progress
961
959
  end
962
- export_progress = new_progress
963
960
  end
964
- end
965
961
 
966
- file_handle.close
967
- Rails.logger.debug("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb")
962
+ file_handle.close
963
+ Rails.logger.debug("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb")
968
964
 
969
- return file_handle
965
+ return file_handle
966
+ end
967
+ end
968
+ rescue *(CONNECTION_EXCEPTIONS).concat(CONNECTION_READ_EXCEPTIONS) => e
969
+ sleep(5)
970
+ if (timeout_retries -= 1) >= 0
971
+ Rails.logger.warn("Download Failed: #{e.class} : #{e.message}")
972
+ retry
973
+ else
974
+ raise
970
975
  end
971
976
  end
972
977
  rescue Exception => e
@@ -27,11 +27,11 @@ module ZuoraAPI
27
27
 
28
28
  input_xml = Nokogiri::XML(request.to_xml(:save_with => XML_SAVE_OPTIONS).strip)
29
29
  input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove
30
- Rails.logger.debug('Connect') {"Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
30
+ Rails.logger.debug('Connect') {"Request Code: #{@response_query.code} SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
31
31
 
32
32
  @response_query = HTTParty.post(self.url,:body => request.to_xml(:save_with => XML_SAVE_OPTIONS).strip, :headers => {'Content-Type' => "text/xml; charset=utf-8"}, :timeout => 10)
33
33
  @output_xml = Nokogiri::XML(@response_query.body)
34
- Rails.logger.debug('Connect') {"Response SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
34
+ Rails.logger.debug('Connect') {"Response Code: #{@response_query.code} SOAP XML: #{@output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}"} if debug
35
35
 
36
36
  if !@response_query.success?
37
37
  self.current_session = nil
@@ -88,6 +88,7 @@ module ZuoraAPI
88
88
  #Username & password combo
89
89
  retrieved_session = @output_xml.xpath('//ns1:Session', 'ns1' =>'http://api.zuora.com/').text
90
90
  raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("No session found for api call.") if retrieved_session.blank?
91
+ self.status = 'Active'
91
92
  self.current_session = retrieved_session
92
93
  end
93
94
  return self.status
@@ -101,6 +102,12 @@ module ZuoraAPI
101
102
  self.status = 'Timeout'
102
103
  return self.status
103
104
  end
105
+ rescue EOFError
106
+ if self.url.match?(/.*services\d{1,}.zuora.com*/)
107
+ self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available."
108
+ self.status = 'Not Available'
109
+ return self.status
110
+ end
104
111
  end
105
112
  end
106
113
  end
@@ -1,3 +1,3 @@
1
1
  module ZuoraAPI
2
- VERSION = "1.6.25"
2
+ VERSION = "1.6.26"
3
3
  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.25
4
+ version: 1.6.26
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-02-07 00:00:00.000000000 Z
11
+ date: 2019-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler