feat: implement CORS and externalize payments config

This commit is contained in:
Tiago Yamamoto 2025-12-18 08:07:45 -03:00
parent 42f72f5f43
commit fc4e3df02d
6 changed files with 62 additions and 17 deletions

7
backend/.env.example Normal file
View file

@ -0,0 +1,7 @@
DATABASE_URL=postgres://user:password@host:port/dbname?sslmode=disable
PORT=8080
DB_MAX_OPEN_CONNS=25
DB_MAX_IDLE_CONNS=25
DB_CONN_MAX_IDLE=15m
MERCADOPAGO_BASE_URL=https://api.mercadopago.com
MARKETPLACE_COMMISSION=2.5

View file

@ -9,24 +9,28 @@ import (
// Config centralizes runtime configuration loaded from the environment.
type Config struct {
AppName string
Port string
DatabaseURL string
MaxOpenConns int
MaxIdleConns int
ConnMaxIdle time.Duration
AppName string
Port string
DatabaseURL string
MaxOpenConns int
MaxIdleConns int
ConnMaxIdle time.Duration
MercadoPagoBaseURL string
MarketplaceCommission float64
}
// Load reads configuration from environment variables and applies sane defaults
// for local development.
func Load() Config {
cfg := Config{
AppName: getEnv("APP_NAME", "saveinmed-performance-core"),
Port: getEnv("PORT", "8080"),
DatabaseURL: getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/saveinmed?sslmode=disable"),
MaxOpenConns: getEnvInt("DB_MAX_OPEN_CONNS", 15),
MaxIdleConns: getEnvInt("DB_MAX_IDLE_CONNS", 5),
ConnMaxIdle: getEnvDuration("DB_CONN_MAX_IDLE", 5*time.Minute),
AppName: getEnv("APP_NAME", "saveinmed-performance-core"),
Port: getEnv("PORT", "8080"),
DatabaseURL: getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/saveinmed?sslmode=disable"),
MaxOpenConns: getEnvInt("DB_MAX_OPEN_CONNS", 15),
MaxIdleConns: getEnvInt("DB_MAX_IDLE_CONNS", 5),
ConnMaxIdle: getEnvDuration("DB_CONN_MAX_IDLE", 5*time.Minute),
MercadoPagoBaseURL: getEnv("MERCADOPAGO_BASE_URL", "https://api.mercadopago.com"),
MarketplaceCommission: getEnvFloat("MARKETPLACE_COMMISSION", 2.5),
}
return cfg
@ -61,3 +65,12 @@ func getEnvDuration(key string, fallback time.Duration) time.Duration {
}
return fallback
}
func getEnvFloat(key string, fallback float64) float64 {
if value := os.Getenv(key); value != "" {
if parsed, err := strconv.ParseFloat(value, 64); err == nil {
return parsed
}
}
return fallback
}

View file

@ -0,0 +1,22 @@
package middleware
import "net/http"
// CORS adds Cross-Origin Resource Sharing headers to the response.
// For now, it allows all origins (*).
func CORS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.Header().Set("Access-Control-Max-Age", "86400")
// Handle preflight requests
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}

View file

@ -14,10 +14,10 @@ type MercadoPagoGateway struct {
BaseURL string
}
func NewMercadoPagoGateway() *MercadoPagoGateway {
func NewMercadoPagoGateway(baseURL string, commission float64) *MercadoPagoGateway {
return &MercadoPagoGateway{
MarketplaceCommission: 2.5,
BaseURL: "https://api.mercadopago.com",
MarketplaceCommission: commission,
BaseURL: baseURL,
}
}

View file

@ -36,7 +36,7 @@ func New(cfg config.Config) (*Server, error) {
db.SetConnMaxIdleTime(cfg.ConnMaxIdle)
repo := postgres.New(db)
gateway := payments.NewMercadoPagoGateway()
gateway := payments.NewMercadoPagoGateway(cfg.MercadoPagoBaseURL, cfg.MarketplaceCommission)
svc := usecase.NewService(repo, gateway)
h := handler.New(svc)
@ -76,7 +76,7 @@ func (s *Server) Start(ctx context.Context) error {
srv := &http.Server{
Addr: s.cfg.Addr(),
Handler: s.mux,
Handler: middleware.CORS(s.mux),
ReadHeaderTimeout: 5 * time.Second,
}

3
backoffice/.env.example Normal file
View file

@ -0,0 +1,3 @@
DATABASE_URL=postgresql://user:password@host:port/dbname?schema=public
JWT_SECRET=secret-key
PORT=3000