Files
soft_usite/rest/controllers/websms_controller.go
T

217 lines
6.2 KiB
Go

package controllers
import (
"strings"
"github.com/gofiber/fiber/v2"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
)
// ─── Vistas ──────────────────────────────────────────────────────────────────
func WebSmsConfigPage(c *fiber.Ctx) error {
cfg, _ := models.GetWebSmsConfig()
return c.Render("websms_config", fiber.Map{
"user": c.Locals("user"),
"modules": c.Locals("userModules"),
"cfg": cfg,
}, "layouts/main")
}
// ─── API ─────────────────────────────────────────────────────────────────────
func GetWebSmsConfig(c *fiber.Ctx) error {
cfg, err := models.GetWebSmsConfig()
if err != nil {
return c.JSON(fiber.Map{"data": nil})
}
return c.JSON(fiber.Map{"data": cfg})
}
func SaveWebSmsConfig(c *fiber.Ctx) error {
type body struct {
ID uint `json:"id"`
Username string `json:"username"`
ApiToken string `json:"api_token"`
Sender string `json:"sender"`
Notas string `json:"notas"`
}
var b body
if err := c.BodyParser(&b); err != nil {
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
}
if b.Username == "" {
return c.Status(400).JSON(fiber.Map{"error": "username es requerido"})
}
if b.ApiToken == "" {
return c.Status(400).JSON(fiber.Map{"error": "api_token es requerido"})
}
cfg := models.WebSmsConfig{
Username: b.Username,
ApiToken: b.ApiToken,
Sender: b.Sender,
Notas: b.Notas,
}
cfg.ID = b.ID
if err := models.SaveWebSmsConfig(cfg); err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"message": "Configuración WebSMS guardada"})
}
func TestWebSms(c *fiber.Ctx) error {
type body struct {
Para string `json:"para"`
Mensaje string `json:"mensaje"`
}
var b body
if err := c.BodyParser(&b); err != nil {
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
}
if b.Para == "" {
return c.Status(400).JSON(fiber.Map{"error": "número de destino requerido"})
}
if b.Mensaje == "" {
b.Mensaje = "[TEST] Notificación desde U-site vía WebSMS"
}
cfg, err := models.GetWebSmsConfig()
if err != nil {
return c.Status(400).JSON(fiber.Map{"error": "WebSMS no configurado"})
}
resp, err := services.SendWebSms(cfg, b.Para, b.Mensaje)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
models.CreateWebSmsLog(&models.WebSmsLog{
Para: b.Para,
Mensaje: b.Mensaje,
Status: resp.Code,
MsgID: resp.MsgID(),
})
return c.JSON(fiber.Map{"ok": true, "response": resp})
}
func GetWebSmsLogs(c *fiber.Ctx) error {
logs, err := models.GetWebSmsLogs(50)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(logs)
}
func GetWebSmsWebhookLogs(c *fiber.Ctx) error {
logs, err := models.GetWebSmsWebhookLogs(50)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(logs)
}
// ─── Webhooks entrantes ─────────────────────────────────────────────────────
func WebSmsDeliveryWebhook(c *fiber.Ctx) error {
var payload services.WebSmsAckPayload
if err := c.BodyParser(&payload); err != nil {
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
}
raw := c.Body()
models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
Tipo: "delivery",
MsgID: payload.ID,
Para: payload.Msisdn,
Status: payload.Status,
Raw: string(raw),
})
return c.SendStatus(200)
}
func WebSmsClickWebhook(c *fiber.Ctx) error {
var payload services.WebSmsClickPayload
if err := c.BodyParser(&payload); err != nil {
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
}
raw := c.Body()
models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
Tipo: "click",
MsgID: payload.ID,
Para: payload.Msisdn,
Status: "clicked",
Raw: string(raw),
})
return c.SendStatus(200)
}
// ─── API pública ────────────────────────────────────────────────────────────
// ApiSendSms envía un SMS. Requiere Authorization: Bearer <secret_key>.
// POST /api/sms/send { "numero": "573001234567", "mensaje": "Hola" }
func ApiSendSms(c *fiber.Ctx) error {
bearer := strings.TrimPrefix(c.Get("Authorization"), "Bearer ")
if bearer == "" {
return c.Status(401).JSON(fiber.Map{"error": "token requerido"})
}
cfg, err := models.GetWebSmsConfig()
if err != nil {
return c.Status(503).JSON(fiber.Map{"error": "WebSMS no configurado"})
}
if cfg.SecretKey == "" || cfg.SecretKey != bearer {
return c.Status(401).JSON(fiber.Map{"error": "token inválido"})
}
type body struct {
Numero string `json:"numero"`
Mensaje string `json:"mensaje"`
}
var b body
if err := c.BodyParser(&b); err != nil || b.Numero == "" || b.Mensaje == "" {
return c.Status(400).JSON(fiber.Map{"error": "numero y mensaje son requeridos"})
}
resp, err := services.SendWebSms(cfg, b.Numero, b.Mensaje)
errStr := ""
status := "ok"
if err != nil {
errStr = err.Error()
status = "error"
} else if resp != nil {
status = resp.Code
}
models.CreateWebSmsLog(&models.WebSmsLog{
Para: b.Numero,
Mensaje: b.Mensaje,
Status: status,
MsgID: func() string { if resp != nil { return resp.MsgID() }; return "" }(),
Error: errStr,
})
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": errStr})
}
return c.JSON(fiber.Map{"ok": true, "id": resp.MsgID()})
}
func WebSmsIncomingWebhook(c *fiber.Ctx) error {
var payload services.WebSmsIncomingPayload
if err := c.BodyParser(&payload); err != nil {
return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
}
raw := c.Body()
models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
Tipo: "incoming",
MsgID: payload.ID,
Para: payload.Msisdn,
Status: "received",
Raw: string(raw),
})
return c.SendStatus(200)
}