diff --git a/app/controllers/api/v1/invoice_generator/invoice_generator_controller.rb b/app/controllers/api/v1/invoice_generator/invoice_generator_controller.rb index ee5c88b..b7c1fd5 100644 --- a/app/controllers/api/v1/invoice_generator/invoice_generator_controller.rb +++ b/app/controllers/api/v1/invoice_generator/invoice_generator_controller.rb @@ -31,12 +31,27 @@ class InvoiceGeneratorController < ApplicationController param :invoice_number, String, required: true def create - InvoiceInstanceGenerator.create(params:) + Rails.logger.info( + "[BILLING-GENERATE] start invoice_number=#{params[:invoice_number].inspect} " \ + "initiator=#{params[:custom_field2].inspect} amount=#{params[:transaction_amount].inspect} " \ + "request_id=#{request.request_id}" + ) + + invoice = InvoiceInstanceGenerator.create(params:) link = EverypayLinkGenerator.create(params:) + Rails.logger.info( + "[BILLING-GENERATE] saved id=#{invoice&.id} invoice_number=#{invoice&.invoice_number} " \ + "request_id=#{request.request_id}" + ) + render json: { 'message' => 'Link created', 'everypay_link' => link }, status: :created rescue StandardError => e - Rails.logger.info e + Rails.logger.error( + "[BILLING-GENERATE] FAILED invoice_number=#{params[:invoice_number].inspect} " \ + "request_id=#{request.request_id} -> #{e.class}: #{e.message}" + ) + Rails.logger.error(e.backtrace.join("\n")) if e.backtrace end end end diff --git a/app/controllers/api/v1/invoice_generator/invoice_number_generator_controller.rb b/app/controllers/api/v1/invoice_generator/invoice_number_generator_controller.rb index 4b0f4a9..fc373c3 100644 --- a/app/controllers/api/v1/invoice_generator/invoice_number_generator_controller.rb +++ b/app/controllers/api/v1/invoice_generator/invoice_number_generator_controller.rb @@ -4,6 +4,12 @@ class Api::V1::InvoiceGenerator::InvoiceNumberGeneratorController < Api::V1::Inv def create invoice_number = InvoiceNumberService.call + Rails.logger.info( + "[BILLING-NUMBER] generated=#{invoice_number.inspect} " \ + "min=#{InvoiceNumberService::INVOICE_NUMBER_MIN} max=#{InvoiceNumberService::INVOICE_NUMBER_MAX} " \ + "db_max=#{Invoice.maximum(:invoice_number).inspect} request_id=#{request.request_id}" + ) + if invoice_number == 'out of range' return render json: { 'message' => "Number create failed. #{invoice_number}", 'error' => invoice_number }, status: :not_implemented diff --git a/app/controllers/api/v1/invoice_generator/oneoff_controller.rb b/app/controllers/api/v1/invoice_generator/oneoff_controller.rb index abbca5e..95d6a83 100644 --- a/app/controllers/api/v1/invoice_generator/oneoff_controller.rb +++ b/app/controllers/api/v1/invoice_generator/oneoff_controller.rb @@ -11,14 +11,23 @@ class OneoffController < Api::V1::InvoiceGenerator::BaseController param :reference_number, String, required: false def create + Rails.logger.info( + "[BILLING-ONEOFF] start invoice_number=#{params[:invoice_number].inspect} " \ + "customer_url=#{params[:customer_url].inspect} " \ + "found_in_db=#{Invoice.exists?(invoice_number: params[:invoice_number])} " \ + "request_id=#{request.request_id}" + ) + response = Oneoff.call(invoice_number: params[:invoice_number], customer_url: params[:customer_url], reference_number: params[:reference_number]) if response.result? + Rails.logger.info("[BILLING-ONEOFF] ok invoice_number=#{params[:invoice_number].inspect} request_id=#{request.request_id}") render json: { 'message' => 'Link created', 'oneoff_redirect_link' => response.instance['payment_link'] }, status: :created else + Rails.logger.warn("[BILLING-ONEOFF] rejected invoice_number=#{params[:invoice_number].inspect} errors=#{response.errors.inspect} request_id=#{request.request_id}") render json: { error: response.errors }, status: :unprocessable_entity end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 612c927..91557c9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,16 @@ class ApplicationController < ActionController::API + prepend_before_action :log_api_request before_action :authorized + def log_api_request + Rails.logger.info( + "[BILLING-API] #{request.request_method} #{request.original_fullpath} " \ + "host=#{request.host} request_id=#{request.request_id} " \ + "initiator=#{(decoded_token && decoded_token[0]['initiator']).inspect} " \ + "params=#{request.filtered_parameters.except('controller', 'action', 'format').inspect}" + ) + end + def encode_token(payload) JWT.encode(payload, ENV['secret_word']) end diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index 32c3853..3f5e9e6 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -7,11 +7,39 @@ def show ActionDispatch::ExceptionWrapper.new( request.env, @exception ).status_code - render view_for_code(@status_code), status: @status_code + + log_exception + + respond_to do |format| + format.html { render view_for_code(@status_code), status: @status_code } + format.json { render json: error_payload, status: @status_code } + format.any { render json: error_payload, status: @status_code, content_type: 'application/json' } + end end private + def log_exception + return if @exception.nil? + + wrapped = @exception.cause || @exception + + Rails.logger.error( + "[ErrorsController] #{@status_code} on #{request.method} " \ + "#{request.original_fullpath} (format=#{request.format.try(:ref).inspect}) " \ + "request_id=#{request.request_id} -> " \ + "#{wrapped.class}: #{wrapped.message}" + ) + Rails.logger.error(wrapped.backtrace.join("\n")) if wrapped.backtrace + end + + def error_payload + { + error: Rack::Utils::HTTP_STATUS_CODES.fetch(@status_code, 'Error'), + status: @status_code + } + end + def view_for_code(code) supported_error_codes.fetch(code, '404') end diff --git a/app/views/errors/401.html.erb b/app/views/errors/401.html.erb new file mode 100644 index 0000000..c1c8286 --- /dev/null +++ b/app/views/errors/401.html.erb @@ -0,0 +1,3 @@ +