241 lines
6.4 KiB
Go
241 lines
6.4 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"api-soap-facturacion/internal/config"
|
|
"api-soap-facturacion/internal/database"
|
|
"api-soap-facturacion/internal/logger"
|
|
"api-soap-facturacion/internal/soap"
|
|
"api-soap-facturacion/internal/soap/api2"
|
|
//"api-soap-facturacion/pkg/errors"
|
|
soapPkg "api-soap-facturacion/pkg/soap"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/jmoiron/sqlx"
|
|
)
|
|
|
|
// Handler maneja las solicitudes HTTP
|
|
type Handler struct {
|
|
config *config.Config
|
|
logger logger.Logger
|
|
db *sqlx.DB
|
|
soapClients *soap.Clients
|
|
}
|
|
|
|
// NewHandler crea un nuevo handler
|
|
func NewHandler(cfg *config.Config, log logger.Logger, db *sqlx.DB, soapClients *soap.Clients) *Handler {
|
|
return &Handler{
|
|
config: cfg,
|
|
logger: log,
|
|
db: db,
|
|
soapClients: soapClients,
|
|
}
|
|
}
|
|
|
|
// HealthCheck verifica el estado de la aplicación
|
|
func (h *Handler) HealthCheck(c *gin.Context) {
|
|
// Verificar conexión a la base de datos
|
|
dbErr := h.db.Ping()
|
|
|
|
status := "ok"
|
|
statusCode := http.StatusOK
|
|
if dbErr != nil {
|
|
status = "degraded"
|
|
statusCode = http.StatusServiceUnavailable
|
|
}
|
|
|
|
c.JSON(statusCode, gin.H{
|
|
"status": status,
|
|
"timestamp": time.Now().Format(time.RFC3339),
|
|
"version": "1.0.0",
|
|
"services": gin.H{
|
|
"database": dbErr == nil,
|
|
},
|
|
})
|
|
}
|
|
|
|
// API2ProcessTransaction maneja solicitudes de transacción para API2
|
|
func (h *Handler) API2ProcessTransaction(c *gin.Context) {
|
|
// Obtener logger
|
|
log := getLogger(c)
|
|
|
|
// Obtener contexto con timeout
|
|
ctx, cancel := context.WithTimeout(c.Request.Context(), h.config.App.RequestTimeout*time.Second)
|
|
defer cancel()
|
|
|
|
// Agregar ID de solicitud al contexto
|
|
requestID := c.GetHeader("X-Request-ID")
|
|
ctx = context.WithValue(ctx, soapPkg.RequestIDKey{}, requestID)
|
|
|
|
// Parsear solicitud
|
|
var requestData struct {
|
|
TransactionID string `json:"transactionId" binding:"required"`
|
|
AccountID string `json:"accountId" binding:"required"`
|
|
Amount float64 `json:"amount" binding:"required"`
|
|
Currency string `json:"currency" binding:"required"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&requestData); err != nil {
|
|
log.Error("Error al parsear solicitud", logger.NewField("error", err))
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"error": "Error al parsear solicitud",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Crear solicitud SOAP
|
|
request := api2.TransactionRequest{
|
|
Namespace: "http://api2.example.com/soap",
|
|
TransactionID: requestData.TransactionID,
|
|
AccountID: requestData.AccountID,
|
|
Amount: requestData.Amount,
|
|
Currency: requestData.Currency,
|
|
Description: requestData.Description,
|
|
}
|
|
|
|
// Llamar a API2
|
|
response, err := h.soapClients.API2.ProcessTransaction(ctx, request)
|
|
if err != nil {
|
|
log.Error("Error al llamar a API2", logger.NewField("error", err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"error": "Error al realizar solicitud a API2",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Retornar respuesta
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"resultCode": response.ResultCode,
|
|
"resultMessage": response.ResultMessage,
|
|
"transactionId": response.TransactionID,
|
|
"confirmationCode": response.ConfirmationCode,
|
|
"timestamp": response.Timestamp,
|
|
})
|
|
}
|
|
|
|
// GetAllParameters retorna todos los parámetros
|
|
func (h *Handler) GetAllParameters(c *gin.Context) {
|
|
// Obtener logger
|
|
log := getLogger(c)
|
|
|
|
// Consultar parámetros
|
|
var params []database.Parameter
|
|
query := `SELECT id, key, value, description, active, created_at, updated_at FROM parameters`
|
|
|
|
err := h.db.Select(¶ms, query)
|
|
if err != nil {
|
|
log.Error("Error al obtener parámetros", logger.NewField("error", err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"error": "Error al obtener parámetros",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Retornar parámetros
|
|
c.JSON(http.StatusOK, params)
|
|
}
|
|
|
|
// GetParameter retorna un parámetro por clave
|
|
func (h *Handler) GetParameter(c *gin.Context) {
|
|
// Obtener logger
|
|
log := getLogger(c)
|
|
|
|
// Obtener clave
|
|
key := c.Param("key")
|
|
|
|
// Consultar parámetro
|
|
var param database.Parameter
|
|
query := `SELECT id, key, value, description, active, created_at, updated_at FROM parameters WHERE key = $1`
|
|
|
|
err := h.db.Get(¶m, query, key)
|
|
if err != nil {
|
|
log.Error("Error al obtener parámetro",
|
|
logger.NewField("error", err),
|
|
logger.NewField("key", key),
|
|
)
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
"error": "Parámetro no encontrado",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Retornar parámetro
|
|
c.JSON(http.StatusOK, param)
|
|
}
|
|
|
|
// UpdateParameter actualiza un parámetro
|
|
func (h *Handler) UpdateParameter(c *gin.Context) {
|
|
// Obtener logger
|
|
log := getLogger(c)
|
|
|
|
// Obtener clave
|
|
key := c.Param("key")
|
|
|
|
// Parsear solicitud
|
|
var requestData struct {
|
|
Value string `json:"value" binding:"required"`
|
|
Description string `json:"description"`
|
|
Active bool `json:"active"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&requestData); err != nil {
|
|
log.Error("Error al parsear solicitud", logger.NewField("error", err))
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"error": "Error al parsear solicitud",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Actualizar parámetro
|
|
query := `
|
|
UPDATE parameters
|
|
SET value = $1, description = $2, active = $3, updated_at = NOW()
|
|
WHERE key = $4
|
|
RETURNING id, key, value, description, active, created_at, updated_at
|
|
`
|
|
|
|
var param database.Parameter
|
|
err := h.db.Get(¶m, query,
|
|
requestData.Value,
|
|
requestData.Description,
|
|
requestData.Active,
|
|
key,
|
|
)
|
|
|
|
if err != nil {
|
|
log.Error("Error al actualizar parámetro",
|
|
logger.NewField("error", err),
|
|
logger.NewField("key", key),
|
|
)
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"error": "Error al actualizar parámetro",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Retornar parámetro actualizado
|
|
c.JSON(http.StatusOK, param)
|
|
}
|
|
|
|
// getLogger obtiene el logger del contexto
|
|
func getLogger(c *gin.Context) logger.Logger {
|
|
if log, exists := c.Get("logger"); exists {
|
|
return log.(logger.Logger)
|
|
}
|
|
// Si no hay logger en el contexto, retornar un logger por defecto
|
|
return &defaultLogger{}
|
|
}
|
|
|
|
// defaultLogger es un logger por defecto
|
|
type defaultLogger struct{}
|
|
|
|
func (l *defaultLogger) Debug(msg string, fields ...logger.Field) {}
|
|
func (l *defaultLogger) Info(msg string, fields ...logger.Field) {}
|
|
func (l *defaultLogger) Warn(msg string, fields ...logger.Field) {}
|
|
func (l *defaultLogger) Error(msg string, fields ...logger.Field) {}
|
|
func (l *defaultLogger) Fatal(msg string, fields ...logger.Field) {}
|
|
func (l *defaultLogger) With(fields ...logger.Field) logger.Logger { return l }
|