up
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -9,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/helpers"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
||||
)
|
||||
|
||||
@@ -103,6 +107,7 @@ func CreateSaasApiConfig(c *fiber.Ctx) error {
|
||||
PayloadTemplate: req.PayloadTemplate,
|
||||
TimeoutSeg: timeout,
|
||||
Activo: req.Activo,
|
||||
WebhookToken: helpers.RandomString(32),
|
||||
}
|
||||
if err := models.CreateSaasApiConfig(&item); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
@@ -298,3 +303,55 @@ func GetSaasDispatchLogs(c *fiber.Ctx) error {
|
||||
"limit": limit,
|
||||
})
|
||||
}
|
||||
|
||||
// ─── Webhook entrante por token ───────────────────────────────────────────────
|
||||
|
||||
// SaasWebhookInHandler recibe llamadas entrantes del SaaS externo identificadas
|
||||
// por el WebhookToken único de la integración. No requiere autenticación.
|
||||
// Ruta pública: POST /webhooks/saas-in/:token
|
||||
func SaasWebhookInHandler(c *fiber.Ctx) error {
|
||||
token := strings.TrimSpace(c.Params("token"))
|
||||
if token == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "token requerido"})
|
||||
}
|
||||
|
||||
cfg, err := models.GetSaasApiConfigByWebhookToken(token)
|
||||
if err != nil {
|
||||
// Responder 200 para evitar reintentos agresivos de sistemas externos
|
||||
log.Printf("[SaasWebhookIn] Token desconocido: %s", token)
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{"ok": false, "msg": "token no reconocido"})
|
||||
}
|
||||
|
||||
// Capturar headers relevantes como JSON
|
||||
headersMap := map[string]string{}
|
||||
c.Request().Header.VisitAll(func(k, v []byte) {
|
||||
key := string(k)
|
||||
// Solo guardar headers informativos, excluir cookies/auth
|
||||
if key != "Cookie" && key != "Authorization" {
|
||||
headersMap[key] = string(v)
|
||||
}
|
||||
})
|
||||
headersJSON, _ := json.Marshal(headersMap)
|
||||
|
||||
rawBody := string(c.Body())
|
||||
|
||||
entry := models.SaasWebhookInLog{
|
||||
SaasApiConfigID: cfg.ID,
|
||||
Token: token,
|
||||
Metodo: c.Method(),
|
||||
IP: c.IP(),
|
||||
Body: rawBody,
|
||||
Headers: string(headersJSON),
|
||||
}
|
||||
_ = models.SaveSaasWebhookInLog(&entry)
|
||||
|
||||
log.Printf("[SaasWebhookIn] Integración '%s' (ID=%d) recibió callback desde IP=%s method=%s",
|
||||
cfg.Nombre, cfg.ID, c.IP(), c.Method())
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"ok": true,
|
||||
"integracion": cfg.Nombre,
|
||||
"saas_api_id": cfg.ID,
|
||||
"message": fmt.Sprintf("Webhook recibido para integración: %s", cfg.Nombre),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user