module ZuoraAPI class Oauth < Login attr_accessor :oauth_client_id, :oauth_secret, :bearer_token, :oauth_session_expires_at def initialize(oauth_client_id: nil, oauth_secret: nil, bearer_token: nil, oauth_session_expires_at: nil, **keyword_args) self.oauth_client_id = oauth_client_id self.oauth_secret = oauth_secret self.bearer_token = bearer_token self.oauth_session_expires_at = oauth_session_expires_at raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if self.bearer_token.blank? && (self.oauth_client_id.blank? || self.oauth_secret.blank?) super end def new_session(raise_errors: false, auth_type: nil, zuora_track_id: nil) if auth_type == :bearer get_bearer_token(zuora_track_id: zuora_track_id) elsif auth_type == :basic get_bearer_token(zuora_track_id: zuora_track_id) if self.oauth_expired? get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active' else get_bearer_token(zuora_track_id: zuora_track_id) get_z_session(zuora_track_id: zuora_track_id) if self.status == 'Active' end return self.status end def get_active_bearer_token self.get_bearer_token if self.oauth_expired? return self.bearer_token end def get_z_session(debug: false, zuora_track_id: nil) tries ||= 2 headers = self.entity_id.present? ? {"Zuora-Entity-Ids" => self.entity_id } : {} headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present? output_json, response = self.rest_call(:url => self.rest_endpoint("connections"), :session_type => :bearer, :headers => headers) self.current_session = response.headers.to_h['set-cookie'][0].split(';')[0].split('=',2)[1].gsub('%3D', '=') rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex if !tries.zero? tries -= 1 Rails.logger.debug {"Session Invalid"} self.new_session(auth_type: :bearer) retry else if errors.include?(ex.class) raise ex else return [output_json, response] end end rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex if errors.include?(ex.class) raise ex else return [output_json, response] end rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex if !tries.zero? tries -= 1 Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"} sleep(self.timeout_sleep) retry else self.current_error = "Request timed out. Try again" self.status = 'Timeout' return self.status end end def get_bearer_token(zuora_track_id: nil) tries ||= 2 raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new("Request Oauth Login but either 'Oauth Client Id' or 'Oauth Secret' were not passed") if self.oauth_client_id.blank? || self.oauth_secret.blank? headers = { "content-type" => "application/x-www-form-urlencoded" } headers['Zuora-Track-Id'] = zuora_track_id if zuora_track_id.present? output_json, response = self.rest_call(:method => :post, :url => self.rest_endpoint.chomp('v1/').concat("oauth/token"), :z_session => false, :session_type => :bearer, :headers => headers, :body => {"client_id"=> self.oauth_client_id, "client_secret"=>self.oauth_secret, "grant_type" =>"client_credentials"} ) self.bearer_token = output_json["access_token"] self.oauth_session_expires_at = Time.now.to_i + output_json["expires_in"].to_i self.current_error = nil self.status = 'Active' return self.status rescue ZuoraAPI::Exceptions::ZuoraUnexpectedError => ex raise ex if tries.zero? tries -= 1 sleep(self.timeout_sleep) retry rescue ZuoraAPI::Exceptions::ZuoraAPISessionError => ex self.bearer_token = nil self.oauth_session_expires_at = nil self.current_error = ex.message case ex.message when "Forbidden" self.current_error = "The user associated to OAuth credential, '#{self.oauth_client_id}', set has been deactivated." self.status = 'Deactivated' else self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint" self.status = 'Invalid Login' end return self.status rescue ZuoraAPI::Exceptions::ZuoraAPIError, ZuoraAPI::Exceptions::ZuoraAPIRequestLimit, ZuoraAPI::Exceptions::ZuoraAPILockCompetition => ex raise ex rescue *(CONNECTION_EXCEPTIONS + CONNECTION_READ_EXCEPTIONS) => ex if !tries.zero? tries -= 1 Rails.logger.info {"#{ex.class} Timed out will retry after 5 seconds"} sleep(self.timeout_sleep) retry else self.current_error = "Invalid login, please check client ID and Client Secret or URL endpoint" self.status = 'Timeout' return self.status end end def oauth_expired? return (self.oauth_session_expires_at.blank? || self.bearer_token.blank?) ? true : (self.oauth_session_expires_at.to_i < Time.now.to_i) end end end