This commit is contained in:
Lizandro Guarnizo
2026-05-01 22:55:51 -05:00
parent ddbabea23f
commit 560359173b
8 changed files with 755 additions and 80 deletions
+19 -2
View File
@@ -83,9 +83,26 @@ func BoldWebhook(c *fiber.Ctx) error {
return c.Status(fiber.StatusOK).JSON(fiber.Map{"ok": true})
}
// ─── 6. Solo procesar SALE_APPROVED ─────────────────────────────────────
// ─── 6. Actualizar estado en callback_log para TODOS los eventos ─────────
if referencia != "" {
estimado := "pendiente"
switch tipo {
case "SALE_APPROVED":
estimado = "pagado"
case "SALE_REJECTED":
estimado = "fallido"
case "SALE_REVERSED", "CHARGEBACK":
estimado = "revertido"
}
models.UpdateBoldCallbackEstado(referencia, estimado)
if paymentID != "" {
models.UpdateBoldCallbackEstado(paymentID, estimado)
}
}
// Solo continuar lógica de negocio para SALE_APPROVED ─────────────────────
if tipo != "SALE_APPROVED" {
log.Printf("[BOLD] Webhook: tipo '%s' ignorado", tipo)
log.Printf("[BOLD] Webhook: tipo '%s' registrado", tipo)
return c.Status(fiber.StatusOK).JSON(fiber.Map{"ok": true})
}
+45 -2
View File
@@ -10,9 +10,52 @@ import (
)
// PagoExitosoPage renderiza la página pública de confirmación de pago.
// Bold redirige al cliente aquí tras el pago. La URL puede incluir ?ref=contrato-{id}.
// Bold redirige al cliente aquí tras el pago. Registra el intento en bold_callback_log.
func PagoExitosoPage(c *fiber.Ctx) error {
ref := c.Query("ref", "")
// Recolectar todos los parámetros posibles que Bold puede enviar
params := map[string]string{}
for _, k := range []string{"bold-order-id", "order_id", "payment_link", "reference", "id", "ref"} {
if v := c.Query(k, ""); v != "" {
params[k] = v
}
}
c.Request().URI().QueryArgs().VisitAll(func(k, v []byte) {
params[string(k)] = string(v)
})
// Resolver la referencia principal (orden de prioridad)
ref := ""
for _, k := range []string{"ref", "reference", "bold-order-id", "payment_link", "order_id", "id"} {
if v := params[k]; v != "" {
ref = v
break
}
}
paymentLink := params["payment_link"]
// Serializar todos los params para auditoría
paramsJSON := "{"
for k, v := range params {
paramsJSON += `"` + k + `":"` + v + `",`
}
if len(paramsJSON) > 1 {
paramsJSON = paramsJSON[:len(paramsJSON)-1]
}
paramsJSON += "}"
// Registrar el intento de pago en la tabla de callbacks
if ref != "" || paymentLink != "" {
entry := models.BoldCallbackLog{
Referencia: ref,
PaymentLink: paymentLink,
Params: paramsJSON,
Estado: "pendiente",
IP: c.IP(),
UserAgent: string(c.Request().Header.UserAgent()),
}
_ = models.SaveBoldCallbackLog(entry)
}
return c.Render("pago_exitoso", fiber.Map{"Ref": ref}, "layouts/landing")
}
+36 -3
View File
@@ -129,13 +129,46 @@ func GetDlocalConfigAPI(c *fiber.Ctx) error {
// ─── Logs Bold ────────────────────────────────────────────────────────────────
// BoldWebhookLogs devuelve los últimos 50 registros del log de webhooks de Bold.
// BoldWebhookLogs devuelve los logs de notificaciones con paginación y filtro por tipo.
// Query params: page (default 1), limit (default 25), tipo (SALE_APPROVED|SALE_REJECTED|...|TODOS)
func BoldWebhookLogs(c *fiber.Ctx) error {
logs, err := models.GetBoldWebhookLogs(50)
page := c.QueryInt("page", 1)
limit := c.QueryInt("limit", 25)
tipo := c.Query("tipo", "")
if page < 1 {
page = 1
}
logs, total, err := models.GetBoldWebhookLogsPaginated(page, limit, tipo)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"data": logs})
return c.JSON(fiber.Map{
"data": logs,
"total": total,
"page": page,
"limit": limit,
})
}
// BoldCallbackLogs devuelve los intentos de pago (visitas al callback) con paginación y filtro.
// Query params: page (default 1), limit (default 25), estado (pendiente|pagado|fallido|revertido|TODOS)
func BoldCallbackLogs(c *fiber.Ctx) error {
page := c.QueryInt("page", 1)
limit := c.QueryInt("limit", 25)
estado := c.Query("estado", "")
if page < 1 {
page = 1
}
logs, total, err := models.GetBoldCallbackLogsPaginated(page, limit, estado)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{
"data": logs,
"total": total,
"page": page,
"limit": limit,
})
}
// ─── Logs dLocal ──────────────────────────────────────────────────────────────
+1
View File
@@ -135,6 +135,7 @@ func UserRoutes(app fiber.Router) {
protected.Get("/pasarelas/bold/config", controllers.GetBoldConfigAPI)
protected.Post("/pasarelas/bold/save", controllers.SaveBoldConfig)
protected.Get("/pasarelas/bold/logs", controllers.BoldWebhookLogs)
protected.Get("/pasarelas/bold/callbacks", controllers.BoldCallbackLogs)
// dLocal
protected.Get("/pasarelas/dlocal/config", controllers.GetDlocalConfigAPI)
protected.Post("/pasarelas/dlocal/save", controllers.SaveDlocalConfigWeb)