Class: ZuoraAPI::Login
- Inherits:
-
Object
- Object
- ZuoraAPI::Login
- Defined in:
- lib/zuora_api/login.rb
Constant Summary collapse
- ENVIRONMENTS =
[TEST = 'Test', SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown', STAGING = 'Staging', PREPROD='Preprod', QAD5='QAD5', QAD6='QAD6', QAD6='QAD7', QAD6='QAD8', QAD6='QAD9' ]
- REGIONS =
[EU = 'EU', US = 'US', NA = 'NA', JP = 'JP' ]
- MIN_Endpoints =
{'Test': '140.0', 'Sandbox': '140.0', 'Production': '140.0', 'Performance': '140.0', 'Services': '96.0', 'Unknown': '96.0', 'Staging': '140.0', 'Preprod': '140.0', 'QAD5': '140.0', 'QAD6': '140.0', 'QAD7': '140.0', 'QAD8': '140.0', 'QAD9': '140.0'}.freeze
- XML_SAVE_OPTIONS =
Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
- USER_AGENT =
"Zuora#{ENV['Z_APPLICATION_NAME']&.capitalize}/#{ENV['Z_APPLICATION_VERSION']&.delete('v')}"
- CONNECTION_EXCEPTIONS =
[ Net::OpenTimeout, SocketError, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, #A remote host refused to allow the network connection Errno::EINVAL, #Invalid argument. This is used to indicate various kinds of problems with passing the wrong argument to a library function. Errno::EHOSTUNREACH, #The remote host for a requested network connection is not reachable. Errno::EADDRNOTAVAIL, Errno::ETIMEDOUT, #ETIMEDOUT A socket operation with a specified timeout received no response during the timeout period. ].freeze
- CONNECTION_READ_EXCEPTIONS =
[ Timeout::Error, Errno::ECONNRESET, Errno::EPIPE ].freeze
- ZUORA_API_ERRORS =
[ ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition, ZuoraAPI::Exceptions::ZuoraAPITemporaryError, ZuoraAPI::Exceptions::ZuoraDataIntegrity, ZuoraAPI::Exceptions::ZuoraAPIInternalServerError, ZuoraAPI::Exceptions::ZuoraUnexpectedError, ZuoraAPI::Exceptions::ZuoraAPIUnkownError ].freeze
- ZUORA_SERVER_ERRORS =
[ ZuoraAPI::Exceptions::ZuoraAPIInternalServerError, ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout, ZuoraAPI::Exceptions::ZuoraAPIReadTimeout, ZuoraAPI::Exceptions::ZuoraUnexpectedError ].freeze
Instance Attribute Summary collapse
-
#bearer_token ⇒ Object
Returns the value of attribute bearer_token.
-
#current_error ⇒ Object
Returns the value of attribute current_error.
-
#current_session ⇒ Object
Returns the value of attribute current_session.
-
#entity_header_type ⇒ Object
Returns the value of attribute entity_header_type.
-
#entity_id ⇒ Object
Returns the value of attribute entity_id.
-
#entity_identifier ⇒ Object
Returns the value of attribute entity_identifier.
-
#environment ⇒ Object
Returns the value of attribute environment.
-
#errors ⇒ Object
Returns the value of attribute errors.
-
#hostname ⇒ Object
Returns the value of attribute hostname.
-
#oauth_session_expires_at ⇒ Object
Returns the value of attribute oauth_session_expires_at.
-
#region ⇒ Object
Returns the value of attribute region.
-
#status ⇒ Object
Returns the value of attribute status.
-
#tenant_id ⇒ Object
Returns the value of attribute tenant_id.
-
#tenant_name ⇒ Object
Returns the value of attribute tenant_name.
-
#timeout_sleep ⇒ Object
Returns the value of attribute timeout_sleep.
-
#url ⇒ Object
Returns the value of attribute url.
-
#user_info ⇒ Object
Returns the value of attribute user_info.
-
#wsdl_number ⇒ Object
Returns the value of attribute wsdl_number.
-
#zconnect_provider ⇒ Object
Returns the value of attribute zconnect_provider.
Class Method Summary collapse
Instance Method Summary collapse
- #aqua_endpoint(url = "") ⇒ Object
- #aqua_query(queryName: '', query: '', version: '1.2', jobName: 'Aqua', partner: '', project: '') ⇒ Object
- #checkJRStatus(jrNumber) ⇒ Object
- #createJournalRun(call) ⇒ Object
- #dateFormat ⇒ Object
- #describe_call(object = nil, log_errors = true) ⇒ Object
- #entity_header ⇒ Object
- #error_logger(ex, **args) ⇒ Object
- #errors_via_content_type(response: nil, type: :xml) ⇒ Object
- #exception_args(ex) ⇒ Object
- #fileURL(url = "") ⇒ Object
- #get_catalog(page_size: 40) ⇒ Object
- #get_entity_id(entity_id: nil) ⇒ Object
- #get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout: 130, session_type: :basic, **execute_params) ⇒ Object
- #get_full_nav(cookies) ⇒ Object
- #get_identity(cookies) ⇒ Object
-
#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, chomp_v1_from_genesis_endpoint: false, use_api_generated_client_secret: false) ⇒ Object
There are two ways to call this method.
- #get_session(prefix: false, auth_type: :basic, zuora_track_id: nil) ⇒ Object
- #get_soap_error_and_message(body) ⇒ Object
- #getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "") ⇒ Object
- #getFileById(id: "2c92c0f85e7f88ff015e86b8f8f4517f") ⇒ Object
-
#initialize(url: nil, entity_id: nil, entity_identifier: nil, session: nil, status: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args) ⇒ Login
constructor
A new instance of Login.
- #insert_entity_header(destination_headers, lookup_headers: nil) ⇒ Object
- #log(location: "Rest Call", exception: nil, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :info) ⇒ Object
- #new_session(auth_type: :basic, debug: false, zuora_track_id: nil) ⇒ Object
- #query(query, parse = false) ⇒ Object
- #raise_errors(type: :SOAP, body: nil, response: nil) ⇒ Object
- #raise_errors_helper(error: nil, message: nil, response: nil, errors: [], success: [], raise_final: true) ⇒ Object
- #refresh_nav(cookies) ⇒ Object
- #reporting_url(path) ⇒ Object
- #reset_files(body) ⇒ Object
- #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: 130, timeout_sleep_interval: self.timeout_sleep, multipart: false, stream_body: false, output_exception_messages: true, zuora_track_id: nil, **keyword_args, &block) ⇒ Object
- #rest_domain(endpoint: self.rest_endpoint) ⇒ Object
- #rest_endpoint(url = "", domain = true, prefix = '/v1/') ⇒ Object
- #set_nav(state, cookies) ⇒ Object
- #soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, headers: {}, single_transaction: false, debug: false, zuora_track_id: nil, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS), z_session: true, timeout_retry: false, timeout: 130, timeout_sleep_interval: self.timeout_sleep, output_exception_messages: true, skip_session: false, **keyword_args) ⇒ Object
- #update_create_tenant ⇒ Object
- #update_environment ⇒ Object
- #update_region ⇒ Object
- #update_zconnect_provider ⇒ Object
Constructor Details
#initialize(url: nil, entity_id: nil, entity_identifier: nil, session: nil, status: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args) ⇒ Login
Returns a new instance of Login.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/zuora_api/login.rb', line 51 def initialize(url: nil, entity_id: nil, entity_identifier: nil, session: nil, status: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args) raise "URL is nil or empty, but URL is required" if url.nil? || url.empty? # raise "URL is improper. URL must contain zuora.com, zuora.eu, or zuora.na" if /zuora.com|zuora.eu|zuora.na/ === url self.hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil? self.update_environment min_endpoint = MIN_Endpoints[self.environment.to_sym] if !/apps\/services\/a\/\d+\.\d$/.match(url.strip) self.url = "https://#{hostname}/apps/services/a/#{min_endpoint}" elsif min_endpoint.to_f > url.scan(/(\d+\.\d)$/).dig(0,0).to_f self.url = url.gsub(/(\d+\.\d)$/, min_endpoint) else self.url = url end self.entity_id = get_entity_id(entity_id: entity_id) self.entity_identifier = entity_identifier self.entity_header_type = :entity_id self.errors = Hash.new self.current_session = session self.bearer_token = bearer_token self.oauth_session_expires_at = oauth_session_expires_at self.status = status.blank? ? "Active" : status self.user_info = Hash.new self.update_region self.update_zconnect_provider @timeout_sleep = 5 end |
Instance Attribute Details
#bearer_token ⇒ Object
Returns the value of attribute bearer_token.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def bearer_token @bearer_token end |
#current_error ⇒ Object
Returns the value of attribute current_error.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def current_error @current_error end |
#current_session ⇒ Object
Returns the value of attribute current_session.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def current_session @current_session end |
#entity_header_type ⇒ Object
Returns the value of attribute entity_header_type.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def entity_header_type @entity_header_type end |
#entity_id ⇒ Object
Returns the value of attribute entity_id.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def entity_id @entity_id end |
#entity_identifier ⇒ Object
Returns the value of attribute entity_identifier.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def entity_identifier @entity_identifier end |
#environment ⇒ Object
Returns the value of attribute environment.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def environment @environment end |
#errors ⇒ Object
Returns the value of attribute errors.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def errors @errors end |
#hostname ⇒ Object
Returns the value of attribute hostname.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def hostname @hostname end |
#oauth_session_expires_at ⇒ Object
Returns the value of attribute oauth_session_expires_at.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def oauth_session_expires_at @oauth_session_expires_at end |
#region ⇒ Object
Returns the value of attribute region.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def region @region end |
#status ⇒ Object
Returns the value of attribute status.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def status @status end |
#tenant_id ⇒ Object
Returns the value of attribute tenant_id.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def tenant_id @tenant_id end |
#tenant_name ⇒ Object
Returns the value of attribute tenant_name.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def tenant_name @tenant_name end |
#timeout_sleep ⇒ Object
Returns the value of attribute timeout_sleep.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def timeout_sleep @timeout_sleep end |
#url ⇒ Object
Returns the value of attribute url.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def url @url end |
#user_info ⇒ Object
Returns the value of attribute user_info.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def user_info @user_info end |
#wsdl_number ⇒ Object
Returns the value of attribute wsdl_number.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def wsdl_number @wsdl_number end |
#zconnect_provider ⇒ Object
Returns the value of attribute zconnect_provider.
49 50 51 |
# File 'lib/zuora_api/login.rb', line 49 def zconnect_provider @zconnect_provider end |
Class Method Details
.endpoints ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/zuora_api/login.rb', line 217 def self.endpoints return {"US" => {"Sandbox" => "https://apisandbox.zuora.com/apps/services/a/", "Production" => "https://www.zuora.com/apps/services/a/", "Performance" => "https://pt1.zuora.com/apps/services/a/", "Services" => "https://services347.zuora.com/apps/services/a/", "Staging" => "https://staging2.zuora.com/apps/services/a/", "Test" => "https://test.zuora.com/apps/services/a/", "Preprod" => "https://preprod.zuora.com/apps/services/a/", "QAD5" => "https://app-5.qad.na.zuora.com/apps/services/a/", "QAD6" => "https://app-6.qad.na.zuora.com/apps/services/a/", "QAD7" => "https://app-7.qad.na.zuora.com/apps/services/a/", "QAD8" => "https://app-8.qad.na.zuora.com/apps/services/a/", "QAD9" => "https://app-9.qad.na.zuora.com/apps/services/a/", }, "EU" => {"Sandbox" => "https://sandbox.eu.zuora.com/apps/services/a/", "Production" => "https://eu.zuora.com/apps/services/a/", "Performance" => "https://pt1.eu.zuora.com/apps/services/a/", "Services" => "https://services347.eu.zuora.com/apps/services/a/", "Test" => "https://test.eu.zuora.com/apps/services/a/"}, "NA" => {"Sandbox" => "https://sandbox.na.zuora.com/apps/services/a/", "Production" => "https://na.zuora.com/apps/services/a/", "Performance" => "https://pt1.na.zuora.com/apps/services/a/", "Services" => "https://services347.na.zuora.com/apps/services/a/", "Test" => "https://test.zuora.com/apps/services/a/", "Preprod" => "https://preprod.zuora.com/apps/services/a/", "QAD5" => "https://app-5.qad.na.zuora.com/apps/services/a/", "QAD6" => "https://app-6.qad.na.zuora.com/apps/services/a/", "QAD7" => "https://app-7.qad.na.zuora.com/apps/services/a/", "QAD8" => "https://app-8.qad.na.zuora.com/apps/services/a/", "QAD9" => "https://app-9.qad.na.zuora.com/apps/services/a/", }, "JP" => {"Sandbox" => "https://sandbox.ap.zuora.com/apps/services/a/", "Production" => "https://ap.zuora.com/apps/services/a/", "Test" => "https://test.ap.zuora.com/apps/services/a/"} } end |
.environments ⇒ Object
209 210 211 |
# File 'lib/zuora_api/login.rb', line 209 def self.environments %w(Sandbox Production Services Performance Staging Test Preprod QAD5 QAD6 QAD7 QAD8 QAD9) end |
.regions ⇒ Object
213 214 215 |
# File 'lib/zuora_api/login.rb', line 213 def self.regions %w(US EU NA JP) end |
Instance Method Details
#aqua_endpoint(url = "") ⇒ Object
329 330 331 332 333 334 335 336 337 |
# File 'lib/zuora_api/login.rb', line 329 def aqua_endpoint(url="") match = /.*(\/apps\/)/.match(self.url) if !match.nil? url_slash_apps_slash = match[0] else raise "self.url has no /apps in it" end return "#{url_slash_apps_slash}api/#{url}" end |
#aqua_query(queryName: '', query: '', version: '1.2', jobName: 'Aqua', partner: '', project: '') ⇒ Object
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 |
# File 'lib/zuora_api/login.rb', line 1079 def aqua_query(queryName: '', query: '', version: '1.2', jobName: 'Aqua',partner: '', project: '') params = { "format" => 'csv', "version" => version, "name" => jobName, "encrypted" => 'none', "useQueryLabels" => 'true', "partner" => partner, "project" => project, "queries" => [{ "name" => queryName, "query" => query, "type" => 'zoqlexport' }] } response = self.rest_call(method: :post, body: params.to_json, url: self.aqua_endpoint("batch-query/")) if(response[0]["id"].nil?) raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error in AQuA Process.", response) end return getFileById(id: response[0]["id"]) end |
#checkJRStatus(jrNumber) ⇒ Object
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 |
# File 'lib/zuora_api/login.rb', line 1642 def checkJRStatus(jrNumber) Rails.logger.info("Check for completion") url = rest_endpoint("/journal-runs/#{jrNumber}") uri = URI(url) req = Net::HTTP::Get.new(uri,initheader = {'Content-Type' =>'application/json'}) req["Authorization"] = self.get_session(prefix: true) response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http| http.request req end result = JSON.parse(response.body) if result["success"] if !(result["status"].eql? "Completed") sleep(20.seconds) end return result["status"] else = result["reasons"][0]["message"] Rails.logger.info("Checking status of journal run failed with message #{}") end return "failure" end |
#createJournalRun(call) ⇒ Object
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 |
# File 'lib/zuora_api/login.rb', line 1617 def createJournalRun(call) url = rest_endpoint("/journal-runs") uri = URI(url) req = Net::HTTP::Post.new(uri,initheader = {'Content-Type' =>'application/json'}) req["Authorization"] = self.get_session(prefix: true) req.body = call response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http| http.request req end Rails.logger.debug("Response #{response.code} #{response.}: #{response.body}") result = JSON.parse(response.body) if result["success"] jrNumber = result["journalRunNumber"] return jrNumber else = result["reasons"][0]["message"] Rails.logger.error("Journal Run failed with message #{}") return result end end |
#dateFormat ⇒ Object
386 387 388 |
# File 'lib/zuora_api/login.rb', line 386 def dateFormat return self.wsdl_number > 68 ? '%Y-%m-%d' : '%Y-%m-%dT%H:%M:%S' end |
#describe_call(object = nil, log_errors = true) ⇒ Object
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 |
# File 'lib/zuora_api/login.rb', line 1145 def describe_call(object = nil, log_errors = true) tries ||= 2 base = self.url.include?(".com") ? self.url.split(".com")[0].concat(".com") : self.url.split(".eu")[0].concat(".eu") version = self.url.scan(/(\d+\.\d)$/).dig(0,0).to_f url = object ? "#{base}/apps/api/#{version}/describe/#{object}" : "#{base}/apps/api/#{version}/describe/" headers = { "Content-Type" => "text/xml; charset=utf-8" }.merge(self.entity_header) response = HTTParty.get(url, headers: {"Authorization" => self.get_session(prefix: true, auth_type: :basic), "User-Agent" => USER_AGENT}.merge(headers), :timeout => 130) raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error.present? ? self.current_error : 'Describe call 401', response) if response.code == 401 output_xml = Nokogiri::XML(response.body) des_hash = Hash.new if object == nil output_xml.xpath("//object").each do |object| temp = {:label => object.xpath(".//label").text, :url => object.attributes["href"].value } des_hash[object.xpath(".//name").text] = temp end else output_xml.xpath("//field").each do |object| temp = {:label => object.xpath(".//label").text,:selectable => object.xpath(".//selectable").text, :createable => object.xpath(".//label").text == "ID" ? "false" : object.xpath(".//createable").text, :filterable => object.xpath(".//filterable").text, :updateable => object.xpath(".//label").text == "ID" ? "false" : object.xpath(".//updateable").text, :custom => object.xpath(".//custom").text,:maxlength => object.xpath(".//maxlength").text, :required => object.xpath(".//required").text, :type => object.xpath(".//type").text, :context => object.xpath(".//context").collect{ |x| x.text } } temp[:options] = object.xpath(".//option").collect{ |x| x.text } if object.xpath(".//option").size > 0 des_hash[object.xpath(".//name").text.to_sym] = temp des_hash[:fieldsToNull] = {:label => "FieldsToNull",:selectable => "false", :createable => "false",:filterable => "false", :updateable => "true",:custom => "false", :required => "false",:type => "picklist", :maxlength => "" ,:context => ["soap"], :options => des_hash.map {|k,v| k if v[:updateable] == "true" && v[:required] == "false"}.compact.uniq } end des_hash[:related_objects] = output_xml.xpath(".//related-objects").xpath(".//object").map{ |x| [x.xpath(".//name").text.to_sym, [ [:url, x.attributes["href"].value], [:label, x.xpath(".//name").text ] ].to_h] }.to_h end return des_hash rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex if !tries.zero? tries -= 1 self.log(location: "Describe", exception: ex, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :debug) sleep(self.timeout_sleep) retry end self.log(location: "Describe", exception: ex, message: "Timed out", level: :error) if log_errors raise ex rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex if !tries.zero? && self.status == 'Active' tries -= 1 Rails.logger.debug("Describe session expired. Starting new session.") self.new_session retry end Rails.logger.error("Describe session expired. Starting new session.") if log_errors raise ex rescue => ex raise ex end |
#entity_header ⇒ Object
1117 1118 1119 1120 1121 1122 1123 1124 1125 |
# File 'lib/zuora_api/login.rb', line 1117 def entity_header if self.entity_header_type == :entity_name && self.entity_identifier.present? { "entityName" => self.entity_identifier } elsif self.entity_id.present? { "Zuora-Entity-Ids" => self.entity_id } else {} end end |
#error_logger(ex, **args) ⇒ Object
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
# File 'lib/zuora_api/login.rb', line 592 def error_logger(ex, **args) return unless Rails.logger.is_a? Ougai::Logger exception_args = Rails.logger.with_fields.merge(self.exception_args(ex)) exception_args.merge!(**args) if args[:log_error_requests] case ex when ZuoraAPI::Exceptions::ZuoraAPIUnkownError, ZuoraAPI::Exceptions::ZuoraDataIntegrity Rails.logger.error('Zuora Unknown/Integrity Error', ex, exception_args) when ZuoraAPI::Exceptions::ZuoraAPIRequestLimit if ex.logged.nil? || !ex.logged ex.logged = true Rails.logger.info('Zuora APILimit Reached', ex, exception_args) end when *(ZuoraAPI::Login::ZUORA_API_ERRORS-ZuoraAPI::Login::ZUORA_SERVER_ERRORS) Rails.logger.error('Zuora API Error', ex, exception_args) if args[:log_error_requests] when *ZuoraAPI::Login::ZUORA_SERVER_ERRORS Rails.logger.error('Zuora Server Error', ex, exception_args) else end end |
#errors_via_content_type(response: nil, type: :xml) ⇒ Object
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 |
# File 'lib/zuora_api/login.rb', line 953 def errors_via_content_type(response: nil, type: :xml) response_content_types = response.headers.transform_keys(&:downcase).fetch('content-type', []).first || "" if response_content_types.include?('application/json') && type != :json output_json = JSON.parse(response.body) self.raise_errors(type: :JSON, body: output_json, response: response) elsif (response_content_types.include?('application/xml') || response_content_types.include?('text/xml') || response_content_types.include?('application/soap+xml')) and type != :xml output_xml = Nokogiri::XML(response.body) self.raise_errors(type: :SOAP, body: output_xml, response: response) elsif response_content_types.include?('text/html') raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Akamai Error", response) if response.headers.fetch('server', '') == 'AkamaiGHost' parse_body = Nokogiri::HTML(response.body) error_title = parse_body.xpath('//h2').text error_title = parse_body.xpath('//h1').text if error_title.blank? = parse_body.xpath('//p').text = error_title if .blank? if error_title.present? case error_title when /Service Unavailable/ raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new(, response) when /Client sent a bad request./, /Bad Request/, /403 Forbidden/ raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(, response) when /414 Request-URI Too Large/ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Request URL is too long", response) when /Not Found/ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("The page you were looking for could not be found. If you believe you reached this page in error, please email support.", response) else raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(, response) end end raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Http response body is missing", response) if response.body.blank? end raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(response.body, response) if response.code == 500 end |
#exception_args(ex) ⇒ Object
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 |
# File 'lib/zuora_api/login.rb', line 623 def exception_args(ex) args = {} if defined?(ex.response) && ex.response.present? args.merge!({ url: {full: ex.response.request.path.to_s}, request: { method: ex.response.request.http_method.to_s.split("Net::HTTP::").last.upcase, params: ex.response.request.raw_body.to_s, headers: ex.response.request.[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h, }, response: { status: ex.response.code, params: ex.response.body.to_s, headers: ex.response.headers, }, zuora_trace_id: ex.response.headers["zuora-request-id"], zuora_track_id: ex.response.request.[:headers]["Zuora-Track-Id"], }) elsif defined?(ex.request) && ex.request.present? args.merge!({ url: {full: ex.request.path.to_s}, request: { method: ex.request.http_method.to_s.split("Net::HTTP::").last.upcase, params: ex.request.[:body], headers: ex.request.[:headers].map{|k,v| [k.to_s, k.to_s.downcase.strip == "authorization" ? "VALUE FILTERED" : v]}.to_h } }) args.merge!({ zuora_track_id: ex.request.[:headers]["Zuora-Track-Id"] }) if ex.request.[:headers]["Zuora-Track-Id"].present? end rescue => ex Rails.logger.error("Failed to create exception arguments", ex, args) ensure return args end |
#fileURL(url = "") ⇒ Object
382 383 384 |
# File 'lib/zuora_api/login.rb', line 382 def fileURL(url="") return self.rest_endpoint("file/").concat(url) end |
#get_catalog(page_size: 40) ⇒ Object
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 |
# File 'lib/zuora_api/login.rb', line 1362 def get_catalog(page_size: 40) products, catalog_map, response = [{}, {}, {'nextPage' => self.rest_endpoint("catalog/products?pageSize=#{page_size}") }] while !response["nextPage"].blank? url = self.rest_endpoint(response["nextPage"].split('/v1/').last) Rails.logger.debug("Fetch Catalog URL #{url}") output_json, response = self.rest_call(debug: false, url: url, timeout_retry: true) if !/(true|t|yes|y|1)$/.match(output_json['success'].to_s) || output_json['success'].class != TrueClass raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Error Getting Catalog: #{output_json}", response) end output_json["products"].each do |product| catalog_map[product["id"]] = {"productId" => product["id"]} rateplans = {} product["productRatePlans"].each do |rateplan| catalog_map[rateplan["id"]] = {"productId" => product["id"], "productRatePlanId" => rateplan["id"]} charges = {} rateplan["productRatePlanCharges"].each do |charge| catalog_map[charge["id"]] = {"productId" => product["id"], "productRatePlanId" => rateplan["id"], "productRatePlanChargeId" => charge["id"]} charges[charge["id"]] = charge.merge({"productId" => product["id"], "productName" => product["name"], "productRatePlanId" => rateplan["id"], "productRatePlanName" => rateplan["name"] }) end rateplan["productRatePlanCharges"] = charges rateplans[rateplan["id"]] = rateplan.merge({"productId" => product["id"], "productName" => product["name"]}) end product["productRatePlans"] = rateplans products[product['id']] = product end end return products, catalog_map end |
#get_entity_id(entity_id: nil) ⇒ Object
254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/zuora_api/login.rb', line 254 def get_entity_id(entity_id: nil) if entity_id.present? entity_match = /[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}$/.match(entity_id) if entity_match.blank? raise "Entity length is wrong." if entity_id.length != 32 part_one, part_two, part_three, part_four, part_five = [entity_id[0..7], entity_id[8..11], entity_id[12..15], entity_id[16..19], entity_id[20..31]] entity_id = "#{part_one}-#{part_two}-#{part_three}-#{part_four}-#{part_five}" end end return entity_id end |
#get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout: 130, session_type: :basic, **execute_params) ⇒ Object
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 |
# File 'lib/zuora_api/login.rb', line 1395 def get_file(url: nil, headers: {}, z_session: true, tempfile: true, output_file_name: nil, zuora_track_id: nil, add_timestamp: true, file_path: defined?(Rails.root.join('tmp')) ? Rails.root.join('tmp') : Pathname.new(Dir.pwd), timeout_retries: 3, timeout: 130, session_type: :basic, **execute_params) raise "file_path must be of class Pathname" if file_path.class != Pathname retry_count ||= timeout_retries #Make sure directory exists require 'fileutils' FileUtils.mkdir_p(file_path) unless File.exist?(file_path) status_code = nil uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) http.read_timeout = timeout #Seconds http.use_ssl = true if !uri.scheme.nil? && uri.scheme.downcase == 'https' if z_session headers = headers.merge({"Authorization" => self.get_session(prefix: true)}) self.insert_entity_header(headers) end headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present? headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present? headers["User-Agent"] = USER_AGENT response_save = nil http.request_get(uri.request_uri, headers) do |response| response_save = response status_code = response.code if response case response when Net::HTTPOK if output_file_name.present? file_ending ||= output_file_name.end_with?(".csv.zip") ? ".csv.zip" : File.extname(output_file_name) filename ||= File.basename(output_file_name, file_ending) end size, export_progress = [0, 0] encoding, type, full_filename = [nil, nil, nil] if response.get_fields("Content-Disposition").present? content_disposition = response.get_fields("Content-Disposition")[0] case content_disposition when /.*; filename\*=.*/ full_filename ||= /.*; filename\*=(.*)''(.*)/.match(content_disposition)[2].strip encoding = /.*; filename\*=(.*)''(.*)/.match(content_disposition)[1].strip when /.*; filename=/ full_filename ||= /.*; filename=(.*)/.match(content_disposition)[1].strip else raise "Can't parse Content-Disposition header: #{content_disposition}" end file_ending ||= full_filename.end_with?(".csv.zip") ? ".csv.zip" : File.extname(full_filename) filename ||= File.basename(full_filename, file_ending) end #If user supplied a filename use it, else default to content header filename, else default to uri pattern file_ending ||= uri.path.end_with?(".csv.zip") ? ".csv.zip" : File.extname(uri.path) filename ||= File.basename(uri.path, file_ending) if response.get_fields("Content-Type").present? content_type = response.get_fields("Content-Type")[0] case content_type when /.*;charset=.*/ type = /(.*);charset=(.*)/.match(content_type)[1] encoding = /(.*);charset=(.*)/.match(content_type)[2] else type = content_type encoding ||= 'UTF-8' end end if response.get_fields("Content-Length").present? export_size = response.get_fields("Content-Length")[0].to_i elsif response.get_fields("ContentLength").present? export_size = response.get_fields("ContentLength")[0].to_i end Rails.logger.info("File: #{filename}#{file_ending} #{encoding} #{type} #{export_size}") file_prefix = ? "#{filename}_#{Time.now.to_i}" : filename if tempfile require 'tempfile' file_handle = ::Tempfile.new([file_prefix, "#{file_ending}"], file_path) else file_handle = File.new(file_path.join("#{file_prefix}#{file_ending}"), "w+") end file_handle.binmode response.read_body do |chunk| file_handle << chunk if defined?(export_size) && export_size != 0 && export_size.class == Integer size += chunk.size new_progress = (size * 100) / export_size unless new_progress == export_progress Rails.logger.debug("Login: Export Downloading %s (%3d%%)" % [filename, new_progress]) end export_progress = new_progress end end file_handle.close Rails.logger.debug("Filepath: #{file_handle.path} Size: #{File.size(file_handle.path).to_f/1000000} mb") raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Downloaded file is not a file: #{file_handle.class}") if !["Tempfile", "File"].include?(file_handle.class.to_s) return file_handle when Net::HTTPUnauthorized if z_session unless (retry_count -= 1).zero? self.new_session raise ZuoraAPI::Exceptions::ZuoraAPISessionError, 'Retrying' end raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) end raise when Net::HTTPNotFound if url.include?(self.fileURL) raise ZuoraAPI::Exceptions::FileDownloadError.new( "The current tenant does not have a file with id '#{url.split('/').last}'" ) else raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}") end else raise ZuoraAPI::Exceptions::FileDownloadError.new("File Download Failed #{response.class}") end end rescue ZuoraAPI::Exceptions::FileDownloadError => ex if ex..match(/.*The current tenant does not have a file with id.*/) raise else Rails.logger.error("File Download Failed") raise end rescue => ex sleep(5) if (retry_count -= 1) >= 0 retry end Rails.logger.error("File Download Failed") raise end |
#get_full_nav(cookies) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/zuora_api/login.rb', line 94 def get_full_nav() zsession = ["ZSession"] begin if zsession.present? response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json', "User-Agent" => USER_AGENT}) output_json = JSON.parse(response.body) else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present") end rescue JSON::ParserError => ex output_json = {} end raise_errors(type: :JSON, body: output_json, response: response) return output_json end |
#get_identity(cookies) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/zuora_api/login.rb', line 78 def get_identity() zsession = ["ZSession"] begin if !zsession.blank? response = HTTParty.get("https://#{self.hostname}/apps/v1/identity", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json', "User-Agent" => USER_AGENT}) output_json = JSON.parse(response.body) else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present") end rescue JSON::ParserError => ex output_json = {} end raise_errors(type: :JSON, body: output_json, response: response) return output_json end |
#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, chomp_v1_from_genesis_endpoint: false, use_api_generated_client_secret: false) ⇒ Object
There are two ways to call this method. The first way is best.
-
Pass in cookies and optionally custom_authorities, name, and description
-
Pass in user_id, entity_ids, client_id, client_secret, and optionally custom_authorities, name, and description
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/zuora_api/login.rb', line 167 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, new_client_id: nil, new_client_secret: nil, cookies: nil, chomp_v1_from_genesis_endpoint: false, use_api_generated_client_secret: false) = "" new_client_id = SecureRandom.uuid if new_client_id.blank? new_client_secret = SecureRandom.hex(10) if new_client_secret.blank? if !.nil? = ["ZSession"] = "ZSession-a3N2w #{}" if entity_ids.blank? && ["ZuoraCurrentEntity"].present? entity_ids = Array(["ZuoraCurrentEntity"].unpack("a8a4a4a4a12").join('-')) else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora Entity ID not provided") end if user_id.blank? && ["Zuora-User-Id"].present? user_id = ["Zuora-User-Id"] else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided") end elsif !client_id.nil? && !client_secret.nil? bearer_response = HTTParty.post("https://#{self.hostname}/oauth/token", :headers => {'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => 'application/json', "User-Agent" => USER_AGENT}, :body => {'client_id' => client_id, 'client_secret' => URI::encode(client_secret), 'grant_type' => 'client_credentials'}) bearer_hash = JSON.parse(bearer_response.body) bearer_token = bearer_hash["access_token"] = "Bearer #{bearer_token}" end if !.blank? && !user_id.blank? && !entity_ids.blank? endpoint = chomp_v1_from_genesis_endpoint ? self.rest_endpoint.chomp("v1/").concat("genesis/clients") : self.rest_endpoint("genesis/clients") oauth_response = HTTParty.post(endpoint, :headers => {'authorization' => , 'Content-Type' => 'application/json', "User-Agent" => USER_AGENT}, :body => {'clientId' => new_client_id, 'clientSecret' => new_client_secret, 'userId' => user_id, 'entityIds' => entity_ids, 'customAuthorities' => , 'additionalInformation' => {'description' => info_desc, 'name' => info_name}}.to_json) output_json = JSON.parse(oauth_response.body) if oauth_response.code == 201 output_json["clientSecret"] = new_client_secret if !use_api_generated_client_secret return output_json elsif oauth_response.code == 401 && !oauth_response..blank? raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], oauth_response) else raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["error"], oauth_response) end else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Insufficient credentials provided") end end |
#get_session(prefix: false, auth_type: :basic, zuora_track_id: nil) ⇒ Object
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/zuora_api/login.rb', line 425 def get_session(prefix: false, auth_type: :basic, zuora_track_id: nil) case auth_type when :basic if self.current_session.blank? case self.class.to_s when 'ZuoraAPI::Oauth' if self.bearer_token.blank? || self.oauth_expired? self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id) end self.get_z_session(zuora_track_id: zuora_track_id) when 'ZuoraAPI::Basic' self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id) else self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id) end end return prefix ? "ZSession #{self.current_session}" : self.current_session.to_s when :bearer case self.class.to_s when 'ZuoraAPI::Oauth' if self.bearer_token.blank? || self.oauth_expired? self.new_session(auth_type: :bearer, zuora_track_id: zuora_track_id) end when 'ZuoraAPI::Basic' raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Basic Login, does not support Authentication of Type: #{auth_type}") else raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Unknown Login, does not support Authentication of Type: #{auth_type}") end return prefix ? "Bearer #{self.bearer_token}" : self.bearer_token.to_s end end |
#get_soap_error_and_message(body) ⇒ Object
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 |
# File 'lib/zuora_api/login.rb', line 996 def (body) error = body.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text = body.xpath('//fns:FaultMessage', 'fns' =>'http://fault.api.zuora.com/').text if error.blank? || .blank? error = body.xpath('//faultcode').text = body.xpath('//faultstring').text end if error.blank? || .blank? error = body.xpath('//ns1:Code', 'ns1' =>'http://api.zuora.com/').text = body.xpath('//ns1:Message', 'ns1' =>'http://api.zuora.com/').text end if error.blank? || .blank? error = body.xpath('//soapenv:Value', 'soapenv'=>'http://www.w3.org/2003/05/soap-envelope').text = body.xpath('//soapenv:Text', 'soapenv'=>'http://www.w3.org/2003/05/soap-envelope').text end #Update/Create/Delete Calls with multiple requests and responses if body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').size > 0 && body.xpath('//ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0 error = [] success = [] body.xpath('//ns1:result', 'ns1' =>'http://api.zuora.com/').each_with_index do |call, object_index| if call.xpath('./ns1:Success', 'ns1' =>'http://api.zuora.com/').text == 'false' && call.xpath('./ns1:Errors', 'ns1' =>'http://api.zuora.com/').size > 0 = "#{call.xpath('./*/ns1:Code', 'ns1' =>'http://api.zuora.com/').text}::#{call.xpath('./*/ns1:Message', 'ns1' =>'http://api.zuora.com/').text}" error.push() else success.push(call.xpath('./ns1:Id', 'ns1' =>'http://api.zuora.com/').text) end end end return error, success, end |
#getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "") ⇒ Object
1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 |
# File 'lib/zuora_api/login.rb', line 1536 def getDataSourceExport(query, extract: true, encrypted: false, zip: true, z_track_id: "") tries ||= 3 output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true, zuora_track_id: z_track_id) do |xml| xml['ns1'].create do xml['ns1'].zObjects('xsi:type' => "ns2:Export") do xml['ns2'].Format 'csv' xml['ns2'].Zip zip xml['ns2'].Name 'googman' xml['ns2'].Query query xml['ns2'].Encrypted encrypted end end end id = output_xml.xpath('//ns1:Id', 'ns1' =>'http://api.zuora.com/').text result = 'Waiting' while result != "Completed" sleep 3 output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true, zuora_track_id: z_track_id) do |xml| xml['ns1'].query do xml['ns1'].queryString "SELECT Id, CreatedById, CreatedDate, Encrypted, FileId, Format, Name, Query, Size, Status, StatusReason, UpdatedById, UpdatedDate, Zip From Export where Id = '#{id}'" end end result = output_xml.xpath('//ns2:Status', 'ns2' =>'http://object.api.zuora.com/').text end file_id = output_xml.xpath('//ns2:FileId', 'ns2' =>'http://object.api.zuora.com/').text export_file = get_file(:url => self.fileURL(file_id)) export_file_path = export_file.path if extract && zip require "zip" new_path = export_file_path.partition('.zip').first zipped = Zip::File.open(export_file_path) file_handle = zipped.entries.first file_handle.extract(new_path) File.delete(export_file_path) return new_path else return export_file_path end rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex if !(tries -= 1).zero? Rails.logger.info("Export call failed - Trace ID: #{z_track_id}") self.new_session retry end raise ex rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex if !(tries -= 1).zero? Rails.logger.info("Trace ID: #{z_track_id} UnexpectedError, will retry after 10 seconds") sleep(self.timeout_sleep) retry end raise ex rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex if !(tries -= 1).zero? Rails.logger.info("Trace ID: #{z_track_id} Timed out will retry after 5 seconds") sleep(self.timeout_sleep) retry end raise ex end |
#getFileById(id: "2c92c0f85e7f88ff015e86b8f8f4517f") ⇒ Object
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 |
# File 'lib/zuora_api/login.rb', line 1101 def getFileById(id: "2c92c0f85e7f88ff015e86b8f8f4517f") response = nil result = "new" while result != "completed" do sleep(2)#sleep 2 seconds response, fullResponse = self.rest_call(method: :get, body: {}, url: self.aqua_endpoint("batch-query/jobs/#{id}")) result = response["batches"][0]["status"] if result == "error" raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Aqua Error", response) break end end fileId = response["batches"][0]["fileId"] return self.get_file(url: self.aqua_endpoint("file/#{fileId}")) end |
#insert_entity_header(destination_headers, lookup_headers: nil) ⇒ Object
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 |
# File 'lib/zuora_api/login.rb', line 1127 def insert_entity_header(destination_headers, lookup_headers: nil) # The entity header may be added to a place other than where we look for it lookup_headers = destination_headers if lookup_headers.nil? = %w(zuora-entity-ids entityid entityname) # If the customer doesn't supply an entity header, fill it in if ( & lookup_headers.keys.map(&:downcase)).blank? entity_header = self.entity_header if entity_header.present? destination_headers.merge!(entity_header) = . reject { |header| header == entity_header.keys.first&.downcase } destination_headers.delete_if { |key, _| .include?(key.to_s.downcase) } end end end |
#log(location: "Rest Call", exception: nil, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :info) ⇒ Object
614 615 616 617 618 619 620 621 |
# File 'lib/zuora_api/login.rb', line 614 def log(location: "Rest Call", exception: nil, message: "Timed out will retry after #{self.timeout_sleep} seconds", level: :info ) level = :debug if ![:debug, :info, :warn, :error, :fatal].include?(level) if Rails.logger.is_a? Ougai::Logger Rails.logger.send(level.to_sym, "#{location} - #{}", exception) else Rails.logger.send(level.to_sym, "#{location} - #{exception.class} #{}") end end |
#new_session(auth_type: :basic, debug: false, zuora_track_id: nil) ⇒ Object
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/zuora_api/login.rb', line 390 def new_session(auth_type: :basic, debug: false, zuora_track_id: nil) retries ||= 2 yield rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex self.status = 'Invalid' self.current_error = ex. raise rescue ZuoraAPI::Exceptions::ZuoraAPIError => ex raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(ex., ex.response) rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex raise ex if retries.zero? retries -= 1 sleep(self.timeout_sleep) retry rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex self.log(location: "BasicLogin", exception: ex, message: "Timed out", level: :error) self.current_error = "Request timed out. Try again" self.status = 'Timeout' raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) rescue EOFError if self.url.match?(/.*services\d{1,}.zuora.com*/) self.current_error = "Services tenant '#{self.url.scan(/.*\/\/(services\d{1,}).zuora.com*/).last.first}' is no longer available." self.status = 'Not Available' raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(self.current_error) end end |
#query(query, parse = false) ⇒ Object
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 |
# File 'lib/zuora_api/login.rb', line 1602 def query(query, parse = false) output_xml, input_xml = self.soap_call(debug: false, timeout_retry: true) do |xml| xml['ns1'].query do xml['ns1'].queryString query end end if parse return [] if output_xml.xpath('//ns1:size', 'ns1' =>'http://api.zuora.com/').text == '0' data = output_xml.xpath('//ns1:records', 'ns1' =>'http://api.zuora.com/').map {|record| record.children.map {|element| [element.name, element.text]}.to_h} return data else return output_xml end end |
#raise_errors(type: :SOAP, body: nil, response: nil) ⇒ Object
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 |
# File 'lib/zuora_api/login.rb', line 660 def raise_errors(type: :SOAP, body: nil, response: nil) request_uri, request_path, match_string = "", "", "" if response.class.to_s == "HTTP::Message" request_uri = response.http_header.request_uri.to_s request_path = response.http_header.request_uri.path match_string = "#{response.http_header.request_method}::#{response.code}::#{request_uri}" else request = response.request request_uri = response.request.uri request_path = request.path.path match_string = "#{request.http_method.to_s.split("Net::HTTP::").last.upcase}::#{response.code}::#{request_path}" end if [502,503].include?(response.code) raise ZuoraAPI::Exceptions::ZuoraAPIConnectionTimeout.new("Received #{response.code} from 'https://#{rest_domain(endpoint: request_uri)}'", response) end # Check failure response code case response.code when 504 raise ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received 504 from 'https://#{rest_domain(endpoint: request_uri)}'", response) when 429 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) when 401 else if body.class == Hash case request_path when /^\/v1\/connections$/ response_headers = response.headers.to_h raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing cookies for authentication call", response) if response_headers['set-cookie'].blank? = response_headers.fetch('set-cookie', []).select{|x| x.match(/^ZSession=.*/) }.first raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Missing ZSession cookie for authentication call", response) if .blank? end end end case type when :SOAP error, success, = (body) if body.xpath('//fns:LoginFault', 'fns' =>'http://fault.api.zuora.com/').present? raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(, response) end if body.xpath('//ns1:queryResponse', 'ns1' => 'http://api.zuora.com/').present? && body.xpath( '//ns1:records[@xsi:type="ns2:Export"]', 'ns1' => 'http://api.zuora.com/', 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance' ).present? result = body.xpath('//ns2:Status', 'ns2' => 'http://object.api.zuora.com/').text if result == 'Failed' = body.xpath('//ns2:StatusReason', 'ns2' => 'http://object.api.zuora.com/').text error = 'UNEXPECTED_ERROR' if .present? identifier, = .scan(/^([\w\d]{16})\: (.*)/).first if .present? if .include?("The query exceeded maximum processing time") error, = ['TRANSACTION_FAILED', .concat(" Please see KC for the Max Timeout Specification https://community.zuora.com/t5/Release-Notifications/Upcoming-Change-for-AQuA-and-Data-Source-Export-January-2021/ba-p/35024")] elsif .include?("There is no field named") error, = ['TRANSACTION_FAILED', ] else error, = ['UNEXPECTED_ERROR', ] end else error, = ['UNEXPECTED_ERROR', ] end else = 'Export failed due to unknown reason. Consult api logs.' end end end #By default response if not passed in for SOAP as all SOAP is 200 if error.present? if error.class == String raise_errors_helper(error: error, message: , response: response) elsif error.class == Array if error.uniq.size == 1 err, msg = error[0].split('::') raise_errors_helper(error: err, message: msg, response: response, errors: error, success: success) else 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) end end end self.errors_via_content_type(response: response, type: :xml) when :JSON case request_path when /^\/query\/jobs.*/ #DataQuery Paths return if body.class != Hash case match_string when /^GET::200::\/query\/jobs\/([a-zA-Z0-9\-_]+)$/ #Get DQ job, Capture of the id is present if needed in future error responses. if body.dig('data', "errorCode") == "LINK_10000005" raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body.dig('data', "errorMessage"), response) elsif (body.dig('data', "errorMessage").present? || body.dig('data', "queryStatus") == "failed") raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new("Data query failed for unknown reasons. No error message.", response) if body.dig('data', "errorMessage").blank? raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('data', "errorMessage"), response) end when /^GET::404::\/query\/jobs\/([a-zA-Z0-9\-_]+)$/ #Get DQ job not found, capture of the id is present if needed in future error responses. raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('message'), response) if body.dig('message').present? when /^POST::400::\/query\/jobs$/ #Create DQ job raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body.dig('message'), response) if body.dig('message').present? end when /^\/api\/rest\/v1\/reports.*/ #Reporting Paths = response.parsed_response.dig("ZanResponse", "response", "message") || body.dig("message") if &.include?("com.zuora.rest.RestUsageException: The user does not have permissions for this API.") raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response) elsif &.include?("500 Internal Server Error") raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Internal Server Error. The Reporting API is down. Contact Support.", response) end case match_string when /^GET::400::\/api\/rest\/v1\/reports\/(reportlabels\/)?([a-zA-Z0-9\-_]+)\/report-details$/ # Get report, capture of the id is present if needed in future error responses. raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response) if .present? end when /\/objects\/batch\// if body['code'].present? && /61$/.match(body['code'].to_s).present? # if last 2 digits of code are 61 raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(body['message'], nil, body['details']) end when /^\/api\/v1\/payment_plans.*/ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['error'], response) if body['error'] end body = body.dig("results").present? ? body["results"] : body if body.class == Hash if body.class == Hash && (!(body["success"] || body["Success"]) || response.code != 200) reason_keys = %w(reasons errors) = %w(message title) , codes_array = [[],[]] reason_keys.each do |rsn_key| .each do |msg_key| = body.fetch(rsn_key, []).map {|error| error[msg_key]}.compact break if .present? end codes_array = body.fetch(rsn_key, []).map {|error| error['code']}.compact break if .present? && codes_array.present? end if body.dig('error').class == Hash = .push(body.dig("error", 'message')).compact codes_array = codes_array.push(body.dig("error", 'code')).compact end if body['message'] == 'request exceeded limit' 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) end if (body.dig('message') || '').downcase.include?('unexpected error') && response.code != 500 raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(body['message'], response) end if body['message'] == "No bearer token" && response.code == 400 raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Authentication type is not supported by this Login", response) end if body['errorMessage'] raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errorMessage'], response) end if body.dig("reasons").nil? ? false : body.dig("reasons")[0].dig("code") == 90000020 raise ZuoraAPI::Exceptions::BadEntityError.new("#{.join(', ')}", response) end #Oauth Tokens - User deactivated if body['path'] == '/oauth/token' if body['status'] == 403 && response.code == 403 raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Forbidden", response) elsif body['status'] == 400 && response.code == 400 raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("Invalid Oauth Client Id", response) end end if body['error'] == 'Unauthorized' && body['status'] == 401 if body['message'].present? raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(body['message'], response) else raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{.join(', ')}", response) end end #Authentication failed if (codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(11) || response.code == 401) && !codes_array.include?(422) = .join(', ') if .present? raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(, response) else raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(body['message'], response) end end #Zuora REST Create Amendment error #Authentication failed if body["faultcode"].present? && body["faultcode"] == "fns:INVALID_SESSION" raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new("#{body['faultstring']}", response) end #Locking contention if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(50) raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("#{.join(', ')}", response) end #Internal Server Error if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(60) if .uniq.size == 1 if .first.match(/^Transaction declined.*|^There is an invoice pending tax.*|^The Zuora GetTax call to Avalara.*|^The tax calculation call to Zuora Connect returned the following error: Status Code: 4.*/) raise ZuoraAPI::Exceptions::ZuoraAPIError.new(.first, response) end end raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("#{.join(', ')}", response) end #Retryiable Service Error if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(61) raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new("#{.join(', ')}", response) end #Request exceeded limit if codes_array.map{|code| code.to_s.slice(6,7).to_i}.include?(70) raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new("#{.join(', ')}", response) end #All Errors catch if codes_array.size > 0 raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{.join(', ')}", response) end #Zuora REST Query Errors if body["faultcode"].present? raise_errors_helper(error: body["faultcode"], message: body["faultstring"], response: response) end if body["Errors"].present? || body["errors"].present? codes, = [[],[]] body.fetch("Errors", []).each { |obj| .push(obj["Message"]); .push(obj["title"]); codes.push(obj["Code"]); codes.push(obj["code"]) } body.fetch("errors", []).each { |obj| .push(obj["Message"]); .push(obj["title"]); codes.push(obj["Code"]); codes.push(obj["code"]) } codes, = [codes.uniq.compact, .uniq.compact] if codes.size > 0 if codes.size == 1 raise_errors_helper(error: codes.first, message: .first, response: response, errors: ) else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{.join(", ")}", response, ) end end end end #Zuora REST Actions error (Create, Update, Delete, Amend) if body.class == Array && !body.compact.blank? all_errors = body.select {|obj| !obj['Success'] || !obj['success'] }.map {|obj| obj['Errors'] || obj['errors'] }.compact all_success = body.select {|obj| obj['Success'] || obj['success']}.compact if all_success.blank? && all_errors.present? error_codes = all_errors.flatten.group_by {|error| error['Code']}.keys.uniq = all_errors.flatten.group_by {|error| error['Message']}.keys.uniq if error_codes.size == 1 || .size == 1 if error_codes.first == "LOCK_COMPETITION" raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new("Retry Lock Competition", response) elsif .first.include?("data integrity violation") raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response) end end end if all_errors.size > 0 raise ZuoraAPI::Exceptions::ZuoraAPIError.new("#{all_errors.flatten.group_by {|error| error['Message']}.keys.uniq.join(' ')}", response, all_errors, all_success) end end if body.class == Hash && body['message'].present? if body['message'] && body['code'].present? raise_errors_helper(error: body['code'], message: body['message'], raise_final: false) end raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(body['message'], response) if response.code == 500 raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['message'], response) if ![200,201,202].include?(response.code) end if body.class == Hash && body['errors'].present? if body['errors'].class == Array && body.dig('errors', 0).is_a?(Hash) raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errors'][0].fetch("message", "No error message. Zuora API Error"), response) end end self.errors_via_content_type(response: response, type: :json) #All other errors if ![200,201,202].include?(response.code) if body == [nil] raise ZuoraAPI::Exceptions::ZuoraAPIError.new('No error message. Invalid API request', response) end raise ZuoraAPI::Exceptions::ZuoraAPIError.new(response.body, response) end end end |
#raise_errors_helper(error: nil, message: nil, response: nil, errors: [], success: [], raise_final: true) ⇒ Object
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 |
# File 'lib/zuora_api/login.rb', line 1031 def raise_errors_helper(error: nil, message: nil, response: nil, errors: [], success: [], raise_final: true) case error when /.*INVALID_SESSION/ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(, response, errors, success) when /.*REQUEST_EXCEEDED_LIMIT/ raise ZuoraAPI::Exceptions::ZuoraAPIRequestLimit.new(, response, errors, success) when /.*LOCK_COMPETITION/ raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(, response, errors, success) when /.*BATCH_FAIL_ERROR/ if .include?("optimistic locking failed") || .include?("Operation failed due to a lock competition, please retry later.") raise ZuoraAPI::Exceptions::ZuoraAPILockCompetition.new(, response, errors, success) elsif .include?("org.hibernate.exception.ConstraintViolationException") raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(, response, errors, success) end raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response, errors, success) when /.*TEMPORARY_ERROR/, /.*TRANSACTION_TIMEOUT/ raise ZuoraAPI::Exceptions::ZuoraAPITemporaryError.new(, response, errors, success) when /.*INVALID_VALUE/ if .include?("data integrity violation") raise ZuoraAPI::Exceptions::ZuoraDataIntegrity.new("Data Integrity Violation", response, errors), success end raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response, errors, success) when /.*UNKNOWN_ERROR/ if /payment\/refund|Credit Balance Adjustment|Payment Gateway|ARSettlement permission/.match().nil? raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(, response, errors, success) end raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response, errors, success) when /^EXTENSION_ERROR/, /^INVALID_VERSION/, /invalid/, /^DUPLICATE_VALUE/, /^REQUEST_REJECTED/, /INVALID_ID/, /MAX_RECORDS_EXCEEDED/, /INVALID_FIELD/, /MALFORMED_QUERY/, /NO_PERMISSION/, /PDF_QUERY_ERROR/, /MISSING_REQUIRED_VALUE/, /INVALID_TYPE/, /TRANSACTION_FAILED/, /API_DISABLED/, /CANNOT_DELETE/, /ACCOUNTING_PERIOD_CLOSED/ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response, errors, success) when /.*UNEXPECTED_ERROR/ raise ZuoraAPI::Exceptions::ZuoraUnexpectedError.new(, response, errors, success) when /.*soapenv:Server.*/ if /^Invalid value.*for type.*|^Id is invalid|^date string can not be less than 19 charactors$/.match().present? raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response, errors, success) elsif /^unknown$|^Invalid white space character \(.*\) in text to output$|^Invalid null character in text to output$/.match().present? raise ZuoraAPI::Exceptions::ZuoraAPIUnkownError.new(, response, errors, success) end raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(, response, errors, success) when /soapenv:Receiver/ if /^com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character.*$/.match().present? raise ZuoraAPI::Exceptions::ZuoraAPIError.new(, response, errors, success) end raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new(, response, errors, success) else raise ZuoraAPI::Exceptions::ZuoraAPIInternalServerError.new("Z:#{error}::#{}", response, errors, success) if raise_final end end |
#refresh_nav(cookies) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/zuora_api/login.rb', line 126 def refresh_nav() zsession = ["ZSession"] begin if !zsession.blank? response = HTTParty.post("https://#{self.hostname}/apps/v1/navigation/fetch", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json', "User-Agent" => USER_AGENT}) output_json = JSON.parse(response.body) else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present") end rescue JSON::ParserError => ex output_json = {} end raise_errors(type: :JSON, body: output_json, response: response) return output_json end |
#reporting_url(path) ⇒ Object
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/zuora_api/login.rb', line 142 def reporting_url(path) map = {"US" => {"Sandbox" => "https://zconnectsandbox.zuora.com/api/rest/v1/", "Production" => "https://zconnect.zuora.com/api/rest/v1/", "Test" => "https://zconnect-services0001.test.zuora.com/api/rest/v1/", "Staging" => "https://reporting-stg11.zan.svc.auw2.zuora.com/api/rest/v1/", "Performance" => "https://zconnectpt1.zuora.com/api/rest/v1/", "Services" => "https://reporting-svc08.svc.auw2.zuora.com/api/rest/v1/"}, "EU" => {"Sandbox" => "https://zconnect.sandbox.eu.zuora.com/api/rest/v1/", "Production" => "https://zconnect.eu.zuora.com/api/rest/v1/", "Services"=> "https://reporting-sbx0000.sbx.aec1.zuora.com/api/rest/v1/", "Test" => "https://zconnect-services0002.test.eu.zuora.com/api/rest/v1/"}, "NA" => {"Sandbox" => "https://zconnect.sandbox.na.zuora.com/api/rest/v1/", "Production" => "https://zconnect.na.zuora.com/api/rest/v1/", "Services"=> ""}, "JP" => {"Sandbox" => "https://zconnect.sandbox.ap.zuora.com/api/rest/v1/", "Production" => "https://zconnect.ap.zuora.com/api/rest/v1/", "Services"=> ""} } return map[self.region][self.environment].insert(-1, path) end |
#reset_files(body) ⇒ Object
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 |
# File 'lib/zuora_api/login.rb', line 1666 def reset_files(body) return unless body.is_a? Hash body.transform_values! do |v| if v.is_a?(File) v.reopen(v.path) else v end end end |
#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: 130, timeout_sleep_interval: self.timeout_sleep, multipart: false, stream_body: false, output_exception_messages: true, zuora_track_id: nil, **keyword_args, &block) ⇒ Object
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 |
# File 'lib/zuora_api/login.rb', line 1212 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: 130, timeout_sleep_interval: self.timeout_sleep, multipart: false, stream_body: false, output_exception_messages: true, zuora_track_id: nil, **keyword_args, &block ) tries ||= 2 raise "Method not supported, supported methods include: :get, :post, :put, :delete, :patch, :head, :options" if ![:get, :post, :put, :delete, :patch, :head, :options].include?(method) authentication_headers = {} if z_session authentication_headers = {"Authorization" => self.get_session(prefix: true, auth_type: session_type, zuora_track_id: zuora_track_id) } self.insert_entity_header(authentication_headers, lookup_headers: headers) end headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present? headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present? headers['User-Agent'] = USER_AGENT modified_headers = {'Content-Type' => "application/json; charset=utf-8"}.merge(authentication_headers).merge(headers) begin request = HTTParty::Request.new( "Net::HTTP::#{method.to_s.capitalize}".constantize, url, body: body, headers: modified_headers, timeout: timeout, multipart: multipart, stream_body: stream_body ) response = request.perform(&block) Rails.logger.debug("Response Code: #{response.code}") if debug begin output_json = JSON.parse(response.body) rescue JSON::ParserError => ex output_json = {} end Rails.logger.debug("Response JSON: #{output_json}") if debug && output_json.present? raise_errors(type: :JSON, body: output_json, response: response) rescue => ex reset_files(body) if multipart raise end return [output_json, response] rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex if self.class.to_s == 'ZuoraAPI::Oauth' && ex..include?("Authentication type is not supported by this Login") session_type = :bearer retry end Rails.logger.debug("Rest Call - Session Bad Auth type") raise ex rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex if !tries.zero? && z_session tries -= 1 Rails.logger.debug("Rest Call - Session Invalid #{session_type}") begin self.new_session(auth_type: session_type) rescue *ZUORA_API_ERRORS => ex return [output_json, ex.response] end retry end raise ex if errors.include?(ex.class) return [output_json, response] rescue *ZUORA_API_ERRORS => ex raise ex if errors.include?(ex.class) response = ex.response unless response return [output_json, response] rescue ZuoraAPI::Exceptions::BadEntityError => ex raise ex rescue *CONNECTION_EXCEPTIONS => ex if !tries.zero? tries -= 1 self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug) sleep(timeout_sleep_interval) retry end self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if raise ex rescue *CONNECTION_READ_EXCEPTIONS => ex if !tries.zero? tries -= 1 self.log(location: "Rest Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug) if ex.is_a?(Errno::ECONNRESET) && ex..include?('SSL_connect') retry elsif timeout_retry sleep(timeout_sleep_interval) retry end end self.log(location: "Rest Call", exception: ex, message: "Timed out", level: :error) if ex = ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read/write timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.is_a?(Timeout::Error) && !ex.instance_of?(ZuoraAPI::Exceptions::ZuoraAPIReadTimeout) raise ex rescue => ex raise ex ensure if defined?(ex) if keyword_args[:log_error_requests] self.error_logger(ex, **keyword_args) else self.error_logger(ex) end end end |
#rest_domain(endpoint: self.rest_endpoint) ⇒ Object
378 379 380 |
# File 'lib/zuora_api/login.rb', line 378 def rest_domain(endpoint: self.rest_endpoint) return URI(endpoint).host end |
#rest_endpoint(url = "", domain = true, prefix = '/v1/') ⇒ Object
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# File 'lib/zuora_api/login.rb', line 339 def rest_endpoint(url="", domain=true, prefix='/v1/') update_environment endpoint = url url_postfix = {"US" => ".", "EU" => ".eu.", "NA" => ".na.", "JP" => ".ap."}[self.region] case self.environment when 'Test' endpoint = "https://rest.test#{url_postfix}zuora.com" when 'Sandbox' endpoint = "https://rest.sandbox#{url_postfix}zuora.com" endpoint = "https://rest.apisandbox.zuora.com" if self.region == "US" when 'Production' endpoint = "https://rest#{url_postfix}zuora.com" when 'Performance' endpoint = "https://rest.pt1.zuora.com" when 'Services' https = /https:\/\/|http:\/\//.match(self.url)[0] host = self.hostname endpoint = "#{https}rest#{host}" when 'Staging' endpoint = "https://rest-staging2.zuora.com" when 'Preprod' endpoint = "https://rest.preprod.zuora.com" when 'QAD5' endpoint = "https://rest-5.qad.na.zuora.com" when 'QAD6' endpoint = "https://rest-6.qad.na.zuora.com" when 'QAD7' endpoint = "https://rest-7.qad.na.zuora.com" when 'QAD8' endpoint = "https://rest-8.qad.na.zuora.com" when 'QAD9' endpoint = "https://rest-9.qad.na.zuora.com" when 'Unknown' raise "Environment unknown, returning passed in parameter unaltered" end return domain ? endpoint.concat(prefix).concat(url) : prefix.concat(url) end |
#set_nav(state, cookies) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/zuora_api/login.rb', line 110 def set_nav(state, ) zsession = ["ZSession"] begin if !zsession.blank? response = HTTParty.put("https://#{self.hostname}/apps/v1/preference/navigation", :body => state.to_json, :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json', "User-Agent" => USER_AGENT}) output_json = JSON.parse(response.body) else raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present") end rescue JSON::ParserError => ex output_json = {} end raise_errors(type: :JSON, body: output_json, response: response) return output_json end |
#soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, headers: {}, single_transaction: false, debug: false, zuora_track_id: nil, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS), z_session: true, timeout_retry: false, timeout: 130, timeout_sleep_interval: self.timeout_sleep, output_exception_messages: true, skip_session: false, **keyword_args) ⇒ Object
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
# File 'lib/zuora_api/login.rb', line 457 def soap_call( ns1: 'ns1', ns2: 'ns2', batch_size: nil, headers: {}, single_transaction: false, debug: false, zuora_track_id: nil, errors: [ZuoraAPI::Exceptions::ZuoraAPISessionError].concat(ZUORA_API_ERRORS), z_session: true, timeout_retry: false, timeout: 130, timeout_sleep_interval: self.timeout_sleep, output_exception_messages: true, skip_session: false, **keyword_args) tries ||= 2 xml = Nokogiri::XML::Builder.new do |xml| 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:api' => "http://api.zuora.com/", "xmlns:#{ns1}" => "http://api.zuora.com/") do xml['SOAP-ENV'].Header do if !skip_session xml["#{ns1}"].SessionHeader do xml["#{ns1}"].session self.get_session(prefix: false, auth_type: :basic, zuora_track_id: zuora_track_id) end end if single_transaction xml["#{ns1}"].CallOptions do xml["#{ns1}"].useSingleTransaction single_transaction end end if batch_size xml["#{ns1}"].QueryOptions do xml["#{ns1}"].batchSize batch_size end end end xml['SOAP-ENV'].Body do yield xml, keyword_args end end end input_xml = Nokogiri::XML(xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip) input_xml.xpath('//ns1:session', 'ns1' =>'http://api.zuora.com/').children.remove Rails.logger.debug("Request SOAP XML: #{input_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug headers.merge!({ 'Content-Type' => "text/xml; charset=utf-8", 'Accept' => 'text/xml'}) headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present? headers['X-Amzn-Trace-Id'] = zuora_track_id if zuora_track_id.present? headers["User-Agent"] = USER_AGENT request = HTTParty::Request.new( Net::HTTP::Post, self.url, body: xml.doc.to_xml(:save_with => XML_SAVE_OPTIONS).strip, headers: headers, timeout: timeout, ) response = request.perform output_xml = Nokogiri::XML(response.body) Rails.logger.debug("Response SOAP XML: #{output_xml.to_xml(:save_with => XML_SAVE_OPTIONS).strip}") if debug raise_errors(type: :SOAP, body: output_xml, response: response) return output_xml, input_xml, response rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex raise if skip_session if !tries.zero? && z_session tries -= 1 Rails.logger.debug("SOAP Call - Session Invalid") begin self.new_session(auth_type: :basic, zuora_track_id: zuora_track_id) rescue *ZUORA_API_ERRORS => ex return output_xml, input_xml, ex.response end retry end raise ex if errors.include?(ex.class) return output_xml, input_xml, response rescue *ZUORA_API_ERRORS => ex raise ex if errors.include?(ex.class) response = ex.response unless response return output_xml, input_xml, response rescue *CONNECTION_EXCEPTIONS => ex if !tries.zero? tries -= 1 self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug) sleep(timeout_sleep_interval) retry end self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if raise ex rescue *CONNECTION_READ_EXCEPTIONS => ex if !tries.zero? tries -= 1 self.log(location: "SOAP Call", exception: ex, message: "Timed out will retry after #{timeout_sleep_interval} seconds", level: :debug) if ex.is_a?(Errno::ECONNRESET) && ex..include?('SSL_connect') retry elsif timeout_retry sleep(timeout_sleep_interval) retry end end self.log(location: "SOAP Call", exception: ex, message: "Timed out", level: :error) if ex = ZuoraAPI::Exceptions::ZuoraAPIReadTimeout.new("Received read/write timeout from 'https://#{rest_domain(endpoint: url)}'", nil, request) if ex.is_a?(Timeout::Error) && !ex.instance_of?(ZuoraAPI::Exceptions::ZuoraAPIReadTimeout) raise ex rescue => ex raise ex ensure if defined?(ex) if keyword_args[:log_error_requests] self.error_logger(ex, **keyword_args) else self.error_logger(ex) end end end |
#update_create_tenant ⇒ Object
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 |
# File 'lib/zuora_api/login.rb', line 1348 def update_create_tenant Rails.logger.debug("Update and/or Create Tenant") output_xml, input_xml = soap_call() do |xml| xml['api'].getUserInfo end user_info = output_xml.xpath('//ns1:getUserInfoResponse', 'ns1' =>'http://api.zuora.com/') output_hash = Hash[user_info.children.map {|x| [x.name.to_sym, x.text] }] self.user_info = output_hash self.user_info['entities'] = self.rest_call(:url => self.rest_endpoint("user-access/user-profile/#{self.user_info['UserId']}/accessible-entities"))['entities'] self.tenant_name = output_hash[:TenantName] self.tenant_id = output_hash[:TenantId] return self end |
#update_environment ⇒ Object
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/zuora_api/login.rb', line 283 def update_environment if !self.hostname.blank? case self.hostname when /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/ self.environment = 'Sandbox' when /(?<=\.|\/|-|^)(app-5\.qad)(?=\.|\/|-|$)/ self.environment = 'QAD5' when /(?<=\.|\/|-|^)(app-6\.qad)(?=\.|\/|-|$)/ self.environment = 'QAD6' when /(?<=\.|\/|-|^)(app-7\.qad)(?=\.|\/|-|$)/ self.environment = 'QAD7' when /(?<=\.|\/|-|^)(app-8\.qad)(?=\.|\/|-|$)/ self.environment = 'QAD8' when /(?<=\.|\/|-|^)(app-9\.qad)(?=\.|\/|-|$)/ self.environment = 'QAD9' when /(?<=\.|\/|^)(service[\d]*|services[\d]*|ep-edge)(?=\.|\/|$)/ self.environment = 'Services' when /(?<=\.|\/|-|^)(pt[\d]*)(?=\.|\/|-|$)/ self.environment = 'Performance' when /(?<=\.|\/|^)(staging1|staging2|stg)(?=\.|\/|$)/ self.environment = 'Staging' when /(?<=\.|\/|^)(test)(?=\.|\/|$)/ self.environment = 'Test' when /(?<=\.|\/|^)(www|api)(?=\.|\/|$)/, /(^|tls10\.|origin-www\.|zforsf\.|eu\.|na\.|ap\.)(zuora\.com)/ self.environment = 'Production' when /(?<=\.|\/|-|^)(preprod|preprod)(?=\.|\/|-|$)/ self.environment = 'Preprod' else self.environment = 'Unknown' end else # this will never happen raise "Can't determine environment from blank URL" end end |
#update_region ⇒ Object
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/zuora_api/login.rb', line 266 def update_region if !self.hostname.blank? if /(?<=\.|\/|^)(eu)(?=\.|\/|$)/ === self.hostname self.region = "EU" elsif /(?<=\.|\/|^)(na)(?=\.|\/|$)/ === self.hostname self.region = "NA" elsif /(?<=\.|\/|^)(ap)(?=\.|\/|$)/ === self.hostname self.region = "JP" else self.region = "US" end else # This will never happen # raise "Can't update region because URL is blank" self.region = "Unknown" end end |
#update_zconnect_provider ⇒ Object
318 319 320 321 322 323 324 325 326 327 |
# File 'lib/zuora_api/login.rb', line 318 def update_zconnect_provider update_region if self.region.blank? update_environment if self.environment.blank? mappings = {"US" => {"Sandbox" => "ZConnectSbx", "Services" => "ZConnectSvcUS", "Production" => "ZConnectProd", "Performance" => "ZConnectPT1", "Preprod" => "ZConnectPreprod", "Test" => "ZConnectTest", "Staging" => "ZConnectQA", "QAD5" => "ZConnectQA", "QAD6" => "ZConnectQA", "QAD7" => "ZConnectQA", "QAD8" => "ZConnectQA", "QAD9" => "ZConnectQA", "KubeSTG" => "ZConnectDev", "KubeDEV" => "ZConnectDev", "KubePROD" => "ZConnectDev"}, "NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "ZConnectSvcNA", "Production" => "ZConnectProdNA", "Performance" => "ZConnectPT1NA", "QAD5" => "ZConnectQA", "QAD6" => "ZConnectQA", "QAD7" => "ZConnectQA", "QAD8" => "ZConnectQA", "QAD9" => "ZConnectQA"}, "EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "ZConnectSvcEU", "Production" => "ZConnectProdEU", "Performance" => "ZConnectPT1EU", "Test" => "ZConnectTest"}, "JP" => {"Sandbox" => "ZConnectSbxAP", "Services" => "ZConnectSvcAP", "Production" => "ZConnectProdAP", "Performance" => "ZConnectPT1AP", "Test" => "ZConnectTest"}, "Unknown" => {"Unknown" => "Unknown"}} self.zconnect_provider = mappings[self.region][self.environment] end |