require 'rest-client' require 'json' module Invofox class << self def configuration @configuration ||= Configuration.new end def configure yield(configuration) end def api_call(clazz:, method:, path:, params: {}, &block) # Prepare the URL url = 'https://api.invofox.com' + path # Prepare headers & params request_headers = { accept: 'application/json', "x-api-key" => Invofox.configuration.api_key } request_params = { headers: request_headers, method: method, url: url, } if method == :post || method == :put request_params[:payload] = params else request_headers[:params] = params end # Do the request response = begin RestClient::Request.execute(request_params) rescue RestClient::BadRequest, RestClient::ExpectationFailed => bad_request bad_request.response end # Log it log_request( method: method, url: url, params: params ) # Deal with the response response_body = JSON.parse(response.body) # 1. First, we treat errors if any treat_errors_if_any(response_body: response_body) # 2. If all went fine, we locate the body result result_in_body = block.call(response_body) # 3. We build the resource result result = if result_in_body.is_a?(Array) Collection.new(result_in_body, clazz) else clazz.new(result_in_body) end # 4. And return everything together Invofox::Response.new( result: result ) end def log_request(method:, url:, params: {}) logger = Invofox.configuration.logger return if logger.nil? now = Time.now safe_params = {} params.each do |key, value| safe_value = value if safe_value.is_a?(Symbol) safe_value = safe_value.to_s end safe_params[key] = safe_value end logger.info( message: 'Invofox request', method: method.upcase.to_s, url: url, time: now.to_s, timestamp: now.to_i, params: safe_params ) end private def treat_errors_if_any(response_body:) code = response_body['code'] return if code.nil? additional_info = response_body['additionalInfo'] raise Invofox::Error.new( code: code, additional_info: additional_info ) end end end