zuora_api 1.9.09 → 1.10.3
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 +4 -4
- data/lib/zuora_api/exceptions.rb +6 -0
- data/lib/zuora_api/login.rb +132 -16
- data/lib/zuora_api/logins/oauth.rb +3 -1
- data/lib/zuora_api/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb8a07811203b9141471afb4cb85bc7b3c62b6e2ce6c9254985d3ad7683f2540
|
4
|
+
data.tar.gz: 58fefaba666d1999c169fcc02208b6df7fca95aa0bc9b219d7aa1fb8c02e1599
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c3c2d7503e8afb612edf442105d6c78d8feb6b480d625dc119ce2cd49645bbd2ad60e9090c93489e56af2921cc97921178c31aa0384a966fb3ed74efb5d2d32
|
7
|
+
data.tar.gz: ec1bc529dba10ef46600ae676fe693d63a3852ee466acd10332cdfb611beb4bee52d3c909a2b4d39d4b303f42782391fd0e32c63ecd54d5006c3cd1cbea8ca5f
|
data/lib/zuora_api/exceptions.rb
CHANGED
@@ -125,6 +125,12 @@ module ZuoraAPI
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
|
+
class ZuoraAPIRequestConcurrentLimit < ZuoraAPIRequestLimit
|
129
|
+
end
|
130
|
+
|
131
|
+
class ZuoraAPIRequestRateLimit < ZuoraAPIRequestLimit
|
132
|
+
end
|
133
|
+
|
128
134
|
class ZuoraAPIUnkownError < Error
|
129
135
|
attr_reader :code, :response
|
130
136
|
attr_writer :default_message
|
data/lib/zuora_api/login.rb
CHANGED
@@ -30,6 +30,8 @@ module ZuoraAPI
|
|
30
30
|
ZUORA_API_ERRORS = [
|
31
31
|
ZuoraAPI::Exceptions::ZuoraAPIError,
|
32
32
|
ZuoraAPI::Exceptions::ZuoraAPIRequestLimit,
|
33
|
+
ZuoraAPI::Exceptions::ZuoraAPIRequestConcurrentLimit,
|
34
|
+
ZuoraAPI::Exceptions::ZuoraAPIRequestRateLimit,
|
33
35
|
ZuoraAPI::Exceptions::ZuoraAPILockCompetition,
|
34
36
|
ZuoraAPI::Exceptions::ZuoraAPITemporaryError,
|
35
37
|
ZuoraAPI::Exceptions::ZuoraDataIntegrity,
|
@@ -45,9 +47,9 @@ module ZuoraAPI
|
|
45
47
|
ZuoraAPI::Exceptions::ZuoraUnexpectedError
|
46
48
|
].freeze
|
47
49
|
|
48
|
-
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
|
50
|
+
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, :entity_identifier, :entity_header_type, :timeout_sleep, :hostname, :zconnect_provider
|
49
51
|
|
50
|
-
def initialize(url: nil, entity_id: nil, session: nil, status: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args)
|
52
|
+
def initialize(url: nil, entity_id: nil, entity_identifier: nil, session: nil, status: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args)
|
51
53
|
raise "URL is nil or empty, but URL is required" if url.nil? || url.empty?
|
52
54
|
# raise "URL is improper. URL must contain zuora.com, zuora.eu, or zuora.na" if /zuora.com|zuora.eu|zuora.na/ === url
|
53
55
|
self.hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil?
|
@@ -61,6 +63,8 @@ module ZuoraAPI
|
|
61
63
|
self.url = url
|
62
64
|
end
|
63
65
|
self.entity_id = get_entity_id(entity_id: entity_id)
|
66
|
+
self.entity_identifier = entity_identifier
|
67
|
+
self.entity_header_type = :entity_id
|
64
68
|
self.errors = Hash.new
|
65
69
|
self.current_session = session
|
66
70
|
self.bearer_token = bearer_token
|
@@ -454,6 +458,8 @@ module ZuoraAPI
|
|
454
458
|
|
455
459
|
headers.merge!({ 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'})
|
456
460
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
461
|
+
headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present?
|
462
|
+
|
457
463
|
headers["User-Agent"] = USER_AGENT
|
458
464
|
|
459
465
|
request = HTTParty::Request.new(
|
@@ -614,10 +620,7 @@ module ZuoraAPI
|
|
614
620
|
case response.code
|
615
621
|
when 504
|
616
622
|
raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response)
|
617
|
-
when 429
|
618
|
-
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)
|
619
|
-
when 401
|
620
|
-
|
623
|
+
when 401, 429
|
621
624
|
else
|
622
625
|
if body.class == Hash
|
623
626
|
case request_path
|
@@ -634,6 +637,21 @@ module ZuoraAPI
|
|
634
637
|
when :SOAP
|
635
638
|
error, success, message = get_soap_error_and_message(body)
|
636
639
|
|
640
|
+
if response.code == 429
|
641
|
+
if message.to_s.downcase.include?('concurrent')
|
642
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestConcurrentLimit.new(
|
643
|
+
"The total number of concurrent requests has exceeded the limit allowed by the system. " \
|
644
|
+
"Please resubmit your request later.",
|
645
|
+
response
|
646
|
+
)
|
647
|
+
else
|
648
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestRateLimit.new(
|
649
|
+
"Rate limiting. Please resubmit your request later.",
|
650
|
+
response
|
651
|
+
)
|
652
|
+
end
|
653
|
+
end
|
654
|
+
|
637
655
|
if body.xpath('//fns:LoginFault', 'fns' =>'http://fault.api.zuora.com/').present?
|
638
656
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response)
|
639
657
|
end
|
@@ -726,7 +744,12 @@ module ZuoraAPI
|
|
726
744
|
codes_array = codes_array.push(body.dig("error", 'code')).compact
|
727
745
|
end
|
728
746
|
|
729
|
-
|
747
|
+
body_message = body.fetch('message', '').downcase
|
748
|
+
if body_message.include?('rate limit exceeded')
|
749
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestRateLimit.new("The total number of requests has exceeded the rate limit allowed by the system. Please resubmit your request later.", response)
|
750
|
+
end
|
751
|
+
|
752
|
+
if body_message.include?('request exceeded limit')
|
730
753
|
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)
|
731
754
|
end
|
732
755
|
|
@@ -798,7 +821,7 @@ module ZuoraAPI
|
|
798
821
|
|
799
822
|
#Request exceeded limit
|
800
823
|
if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70)
|
801
|
-
raise ZuoraAPI::Exceptions::
|
824
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestConcurrentLimit.new("#{messages_array.join(', ')}", response)
|
802
825
|
end
|
803
826
|
|
804
827
|
#All Errors catch
|
@@ -806,6 +829,10 @@ module ZuoraAPI
|
|
806
829
|
raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{messages_array.join(', ')}", response)
|
807
830
|
end
|
808
831
|
|
832
|
+
if response.code == 429
|
833
|
+
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)
|
834
|
+
end
|
835
|
+
|
809
836
|
#Zuora REST Query Errors
|
810
837
|
if body["faultcode"].present?
|
811
838
|
raise_errors_helper(error: body["faultcode"], message: body["faultstring"], response: response)
|
@@ -941,7 +968,11 @@ module ZuoraAPI
|
|
941
968
|
when /.*INVALID_SESSION/
|
942
969
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(message, response, errors, success)
|
943
970
|
when /.*REQUEST_EXCEEDED_LIMIT/
|
944
|
-
|
971
|
+
if message.to_s.downcase.include?('concurrent')
|
972
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestConcurrentLimit.new(message, response, errors, success)
|
973
|
+
else
|
974
|
+
raise ZuoraAPI::Exceptions::ZuoraAPIRequestRateLimit.new(message, response, errors, success)
|
975
|
+
end
|
945
976
|
when /.*LOCK_COMPETITION/
|
946
977
|
raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(message, response, errors, success)
|
947
978
|
when /.*BATCH_FAIL_ERROR/
|
@@ -1022,12 +1053,44 @@ module ZuoraAPI
|
|
1022
1053
|
return self.get_file(url: self.aqua_endpoint("file/#{fileId}"))
|
1023
1054
|
end
|
1024
1055
|
|
1056
|
+
def entity_header
|
1057
|
+
if self.entity_header_type == :entity_name && self.entity_identifier.present?
|
1058
|
+
{ "entityName" => self.entity_identifier }
|
1059
|
+
elsif self.entity_id.present?
|
1060
|
+
{ "Zuora-Entity-Ids" => self.entity_id }
|
1061
|
+
else
|
1062
|
+
{}
|
1063
|
+
end
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
def insert_entity_header(destination_headers, lookup_headers: nil)
|
1067
|
+
# The entity header may be added to a place other than where we look for it
|
1068
|
+
lookup_headers = destination_headers if lookup_headers.nil?
|
1069
|
+
|
1070
|
+
entity_header_options = %w(zuora-entity-ids entityid entityname)
|
1071
|
+
# If the customer doesn't supply an entity header, fill it in
|
1072
|
+
if (entity_header_options & lookup_headers.keys.map(&:downcase)).blank?
|
1073
|
+
entity_header = self.entity_header
|
1074
|
+
if entity_header.present?
|
1075
|
+
destination_headers.merge!(entity_header)
|
1076
|
+
entity_header_options_to_exclude =
|
1077
|
+
entity_header_options.
|
1078
|
+
reject { |header| header == entity_header.keys.first&.downcase }
|
1079
|
+
destination_headers.delete_if { |key, _| entity_header_options_to_exclude.include?(key.to_s.downcase) }
|
1080
|
+
end
|
1081
|
+
end
|
1082
|
+
end
|
1083
|
+
|
1025
1084
|
def describe_call(object = nil, log_errors = true)
|
1026
1085
|
tries ||= 2
|
1027
1086
|
|
1028
1087
|
base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu")
|
1029
|
-
|
1030
|
-
|
1088
|
+
|
1089
|
+
version = self.url.scan(/(\d+\.\d)$/).dig(0,0).to_f
|
1090
|
+
url = object ? "#{base}/apps/api/#{version}/describe/#{object}" : "#{base}/apps/api/#{version}/describe/"
|
1091
|
+
|
1092
|
+
headers = { "Content-Type" => "text/xml; charset=utf-8" }.merge(self.entity_header)
|
1093
|
+
|
1031
1094
|
response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic), "User-Agent" => USER_AGENT}.merge(headers), :timeout => 130)
|
1032
1095
|
|
1033
1096
|
raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401
|
@@ -1114,12 +1177,12 @@ module ZuoraAPI
|
|
1114
1177
|
authentication_headers = {}
|
1115
1178
|
if z_session
|
1116
1179
|
authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type, zuora_track_id: zuora_track_id) }
|
1117
|
-
|
1118
|
-
|
1119
|
-
authentication_headers.delete_if { |key, value| ["entityId", "entityName"].include?(key.to_s) }
|
1120
|
-
end
|
1180
|
+
|
1181
|
+
self.insert_entity_header(authentication_headers, lookup_headers: headers)
|
1121
1182
|
end
|
1122
1183
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
1184
|
+
headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present?
|
1185
|
+
|
1123
1186
|
headers['User-Agent'] = USER_AGENT
|
1124
1187
|
|
1125
1188
|
modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers)
|
@@ -1282,10 +1345,13 @@ module ZuoraAPI
|
|
1282
1345
|
http.use_ssl = true if !uri.scheme.nil? && uri.scheme.downcase == 'https'
|
1283
1346
|
if z_session
|
1284
1347
|
headers = headers.merge({"Authorization" => self.get_session(prefix: true)})
|
1285
|
-
|
1348
|
+
|
1349
|
+
self.insert_entity_header(headers)
|
1286
1350
|
end
|
1287
1351
|
|
1288
1352
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
1353
|
+
headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present?
|
1354
|
+
|
1289
1355
|
headers["User-Agent"] = USER_AGENT
|
1290
1356
|
|
1291
1357
|
response_save = nil
|
@@ -1401,6 +1467,56 @@ module ZuoraAPI
|
|
1401
1467
|
raise
|
1402
1468
|
end
|
1403
1469
|
|
1470
|
+
def create_data_source_export(query: "", encrypted: false, zip: true, z_track_id: "")
|
1471
|
+
begin
|
1472
|
+
output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true, zuora_track_id: z_track_id) do |xml|
|
1473
|
+
xml['ns1'].create do
|
1474
|
+
xml['ns1'].zObjects('xsi:type' => "ns2:Export") do
|
1475
|
+
xml['ns2'].Format 'csv'
|
1476
|
+
xml['ns2'].Zip zip
|
1477
|
+
xml['ns2'].Name 'googman'
|
1478
|
+
xml['ns2'].Query query
|
1479
|
+
xml['ns2'].Encrypted encrypted
|
1480
|
+
end
|
1481
|
+
end
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
return output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text
|
1485
|
+
rescue Exception => ex
|
1486
|
+
raise ex.class.new("#{z_track_id} #{ex.message}")
|
1487
|
+
end
|
1488
|
+
end
|
1489
|
+
|
1490
|
+
def check_export_status(export_id: "")
|
1491
|
+
begin
|
1492
|
+
response, full_response = self.rest_call(method: :get,url: self.rest_endpoint("object/export/#{export_id}"))
|
1493
|
+
|
1494
|
+
return full_response.parsed_response
|
1495
|
+
rescue Exception => ex
|
1496
|
+
raise ex
|
1497
|
+
end
|
1498
|
+
end
|
1499
|
+
|
1500
|
+
def get_export_file(file_id: "", extract: true, zip: true)
|
1501
|
+
begin
|
1502
|
+
export_file_path = self.get_file(:url => self.rest_endpoint("files/#{file_id}")).path
|
1503
|
+
|
1504
|
+
if extract && zip
|
1505
|
+
require "zip"
|
1506
|
+
new_path = export_file_path.partition('.zip').first
|
1507
|
+
zipped = Zip::File.open(export_file_path)
|
1508
|
+
file_handle = zipped.entries.first
|
1509
|
+
file_handle.extract(new_path)
|
1510
|
+
File.delete(export_file_path)
|
1511
|
+
return new_path
|
1512
|
+
else
|
1513
|
+
return export_file_path
|
1514
|
+
end
|
1515
|
+
rescue Exception => ex
|
1516
|
+
raise ex
|
1517
|
+
end
|
1518
|
+
end
|
1519
|
+
|
1404
1520
|
def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "")
|
1405
1521
|
tries ||= 3
|
1406
1522
|
|
@@ -32,8 +32,9 @@ module ZuoraAPI
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def get_z_session(debug: false, zuora_track_id: nil)
|
35
|
-
headers = self.
|
35
|
+
headers = self.entity_header
|
36
36
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
37
|
+
headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present?
|
37
38
|
output_json, response = self.rest_call(:url => self.rest_endpoint("connections"), :session_type => :bearer, :headers => headers)
|
38
39
|
begin
|
39
40
|
self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=')
|
@@ -54,6 +55,7 @@ module ZuoraAPI
|
|
54
55
|
|
55
56
|
headers = { "content-type" => "application/x-www-form-urlencoded" }
|
56
57
|
headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present?
|
58
|
+
headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present?
|
57
59
|
|
58
60
|
output_json, response = self.rest_call(:method => :post,
|
59
61
|
url: self.rest_endpoint.chomp('v1/').concat("oauth/token"),
|
data/lib/zuora_api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zuora_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zuora Strategic Solutions Group
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -219,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
219
|
- !ruby/object:Gem::Version
|
220
220
|
version: '0'
|
221
221
|
requirements: []
|
222
|
-
rubygems_version: 3.2.
|
222
|
+
rubygems_version: 3.2.32
|
223
223
|
signing_key:
|
224
224
|
specification_version: 4
|
225
225
|
summary: Gem that provides easy integration to Zuora
|