feat: rota + controller esqueleto PublicReservations com token auth

This commit is contained in:
Rodribm10 2026-04-13 23:49:11 -03:00
parent 17f1c8165e
commit e9a5e734ff
3 changed files with 52 additions and 7 deletions

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
# Endpoint público para criação de reservas via React app externo (Reserva 1001).
# Autenticado por token estático via header X-Reserva-Token.
class Public::Api::V1::Captain::PublicReservationsController < ActionController::API
before_action :authenticate_reserva_token!
def create
render json: { error: 'not_implemented' }, status: :not_implemented
end
def status
render json: { error: 'not_implemented' }, status: :not_implemented
end
private
def authenticate_reserva_token!
expected = ENV.fetch('RESERVA_1001_API_TOKEN', nil)
provided = request.headers['X-Reserva-Token']
if expected.blank?
Rails.logger.error('[PublicReservations] RESERVA_1001_API_TOKEN not configured')
render json: { error: 'service_unavailable' }, status: :service_unavailable and return
end
return if provided.present? && ActiveSupport::SecurityUtils.secure_compare(provided, expected)
render json: { error: 'unauthorized' }, status: :unauthorized
end
end

View File

@ -692,6 +692,14 @@ Rails.application.routes.draw do
# Página pública de pagamento PIX (link curto gerado via SGID pela IA)
get '/r/:token', to: 'public/api/v1/captain/payments#show', as: :short_payment_link
# API pública de reservas (Reserva 1001)
post '/public/api/v1/captain/public_reservations',
to: 'public/api/v1/captain/public_reservations#create',
defaults: { format: 'json' }
get '/public/api/v1/captain/public_reservations/:id/status',
to: 'public/api/v1/captain/public_reservations#status',
defaults: { format: 'json' }
# Webhook do Banco Inter para notificações de PIX pago
post '/api/v1/captain/webhooks/inter_pix',
to: 'public/api/v1/captain/inter_webhooks#create',

View File

@ -6,7 +6,12 @@ RSpec.describe 'Public Captain Reservations API', type: :request do
let(:valid_token) { 'test-token-abc' }
let(:account) { create(:account) }
let(:inbox) { create(:inbox, account: account) }
let(:unit) { create(:captain_unit, account: account, inbox: inbox) }
let(:brand) { create(:captain_brand, account: account) }
let(:unit) do
Captain::Unit.create!(account: account, brand: brand, inbox_id: inbox.id,
name: 'Hotel Teste', inter_pix_key: 'pix@test.com',
inter_account_number: '12345678')
end
before do
allow(ENV).to receive(:fetch).and_call_original
@ -39,9 +44,13 @@ RSpec.describe 'Public Captain Reservations API', type: :request do
context 'with valid token and valid payload' do
let(:unit) do
create(:captain_unit, account: account, inbox: inbox,
inter_client_id: 'fake-id',
inter_pix_key: 'fake-key@test.com')
Captain::Unit.create!(
account: account, brand: brand, inbox_id: inbox.id,
name: 'Hotel Teste Com Inter', inter_pix_key: 'fake-key@test.com',
inter_account_number: '1234567', inter_client_id: 'fake-id',
inter_client_secret: 'fake-secret', inter_cert_content: 'FAKE-CERT',
inter_key_content: 'FAKE-KEY'
)
end
let(:valid_payload) do
@ -108,11 +117,8 @@ RSpec.describe 'Public Captain Reservations API', type: :request do
end
describe 'GET /public/api/v1/captain/public_reservations/:id/status' do
let(:account) { create(:account) }
let(:inbox) { create(:inbox, account: account) }
let(:contact) { create(:contact, account: account) }
let(:contact_inbox) { create(:contact_inbox, inbox: inbox, contact: contact) }
let(:unit) { create(:captain_unit, account: account, inbox: inbox) }
let(:reservation) do
Captain::Reservation.create!(
account: account, inbox: inbox, contact: contact, contact_inbox: contact_inbox,