up
This commit is contained in:
@@ -149,3 +149,15 @@ func GetDlocalPaymentLogs(limit int) ([]DlocalPaymentLog, error) {
|
|||||||
}
|
}
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDlocalPaymentLogsByRef devuelve todos los registros que coinciden con una referencia/order_id.
|
||||||
|
func GetDlocalPaymentLogsByRef(ref string) ([]DlocalPaymentLog, error) {
|
||||||
|
var logs []DlocalPaymentLog
|
||||||
|
if err := app.Http.Database.DB.
|
||||||
|
Where("referencia = ? OR order_id = ?", ref, ref).
|
||||||
|
Order("id DESC").
|
||||||
|
Find(&logs).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return logs, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
||||||
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PagoExitosoPage renderiza la página pública de confirmación de pago.
|
// PagoExitosoPage renderiza la página pública de confirmación de pago.
|
||||||
@@ -16,6 +18,12 @@ func PagoExitosoPage(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
// PagoEstadoAPI devuelve el estado de pago de un contrato para polling desde el frontend.
|
// PagoEstadoAPI devuelve el estado de pago de un contrato para polling desde el frontend.
|
||||||
// GET /api/pago-estado?ref=contrato-{id}
|
// GET /api/pago-estado?ref=contrato-{id}
|
||||||
|
//
|
||||||
|
// Flujo de verificación (en orden):
|
||||||
|
// 1. Lee pago_confirmado de la DB → si ya confirmado, retorna ok.
|
||||||
|
// 2. Si no confirmado, revisa dlocal_payment_log buscando ref con estado PAID.
|
||||||
|
// 3. Si aún no confirmado, consulta Bold API directamente usando enlace_pago_link_id.
|
||||||
|
// 4. Si la pasarela confirma el pago, marca el contrato y retorna confirmado.
|
||||||
func PagoEstadoAPI(c *fiber.Ctx) error {
|
func PagoEstadoAPI(c *fiber.Ctx) error {
|
||||||
ref := c.Query("ref", "")
|
ref := c.Query("ref", "")
|
||||||
if ref == "" {
|
if ref == "" {
|
||||||
@@ -27,14 +35,93 @@ func PagoEstadoAPI(c *fiber.Ctx) error {
|
|||||||
return c.JSON(fiber.Map{"confirmado": false, "error": "ref inválido"})
|
return c.JSON(fiber.Map{"confirmado": false, "error": "ref inválido"})
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmado, fechaPago, err := models.GetEstadoPago(contratoID)
|
// ─── 1. Consultar DB ──────────────────────────────────────────────────────
|
||||||
|
contrato, err := models.GetContratoParaVerificacion(contratoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(fiber.Map{"confirmado": false, "error": "contrato no encontrado"})
|
return c.JSON(fiber.Map{"confirmado": false, "error": "contrato no encontrado"})
|
||||||
}
|
}
|
||||||
|
if contrato.PagoConfirmado {
|
||||||
resp := fiber.Map{"confirmado": confirmado}
|
resp := fiber.Map{"confirmado": true, "fuente": "db"}
|
||||||
if confirmado && fechaPago != nil {
|
if contrato.FechaPago != nil {
|
||||||
resp["fecha_pago"] = fechaPago.Format("02/01/2006 15:04")
|
resp["fecha_pago"] = contrato.FechaPago.Format("02/01/2006 15:04")
|
||||||
|
}
|
||||||
|
return c.JSON(resp)
|
||||||
}
|
}
|
||||||
return c.JSON(resp)
|
|
||||||
|
// ─── 2. Revisar log de dLocal (puede haber llegado antes que el webhook) ──
|
||||||
|
dlocalLogs, err := models.GetDlocalPaymentLogsByRef(ref)
|
||||||
|
if err == nil {
|
||||||
|
for _, l := range dlocalLogs {
|
||||||
|
if l.Estado == "PAID" || l.Estado == "AUTHORIZED" {
|
||||||
|
log.Printf("[PAGO-ESTADO] Contrato %d confirmado via dlocal_payment_log (id=%d)", contratoID, l.ID)
|
||||||
|
_ = models.MarcarContratoPagado(contratoID)
|
||||||
|
now := l.CreatedAt
|
||||||
|
return c.JSON(fiber.Map{
|
||||||
|
"confirmado": true,
|
||||||
|
"fuente": "dlocal_log",
|
||||||
|
"fecha_pago": now.Format("02/01/2006 15:04"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── 3. Consultar Bold API directamente si hay link_id almacenado ─────────
|
||||||
|
if contrato.EnlacePagoLinkID != "" {
|
||||||
|
boldCfg, boldErr := models.GetBoldConfig()
|
||||||
|
if boldErr == nil {
|
||||||
|
paid, paymentID, boldApiErr := services.CheckBoldLinkPaid(boldCfg, contrato.EnlacePagoLinkID)
|
||||||
|
if boldApiErr != nil {
|
||||||
|
log.Printf("[PAGO-ESTADO] Bold API error para link %s: %v", contrato.EnlacePagoLinkID, boldApiErr)
|
||||||
|
} else if paid {
|
||||||
|
log.Printf("[PAGO-ESTADO] Contrato %d confirmado via Bold API (payment_id=%s)", contratoID, paymentID)
|
||||||
|
_ = models.MarcarContratoPagado(contratoID)
|
||||||
|
// Guardar en bold_webhook_log como registro de esta verificación activa
|
||||||
|
if paymentID != "" && !models.IsBoldNotificationDuplicate("api-check-"+paymentID) {
|
||||||
|
_ = models.SaveBoldWebhookLog(models.BoldWebhookLog{
|
||||||
|
NotificationID: "api-check-" + paymentID,
|
||||||
|
Tipo: "API_CHECK",
|
||||||
|
PaymentID: paymentID,
|
||||||
|
Referencia: ref,
|
||||||
|
Procesado: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return c.JSON(fiber.Map{
|
||||||
|
"confirmado": true,
|
||||||
|
"fuente": "bold_api",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── 4. Consultar dLocal API directamente por order_id ────────────────────
|
||||||
|
dlocalCfg, dlocalErr := models.GetLastActiveDlocalApi()
|
||||||
|
if dlocalErr == nil {
|
||||||
|
paid, paymentID, dlocalApiErr := services.CheckDlocalPaymentByOrderID(*dlocalCfg, ref)
|
||||||
|
if dlocalApiErr != nil {
|
||||||
|
log.Printf("[PAGO-ESTADO] dLocal API error para order_id %s: %v", ref, dlocalApiErr)
|
||||||
|
} else if paid {
|
||||||
|
log.Printf("[PAGO-ESTADO] Contrato %d confirmado via dLocal API (payment_id=%s)", contratoID, paymentID)
|
||||||
|
_ = models.MarcarContratoPagado(contratoID)
|
||||||
|
// Guardar en dlocal_payment_log como registro de esta verificación activa
|
||||||
|
notifID := "api-check-" + ref
|
||||||
|
if !models.IsDlocalNotificationDuplicate(notifID) {
|
||||||
|
_ = models.SaveDlocalPaymentLog(models.DlocalPaymentLog{
|
||||||
|
NotificationID: notifID,
|
||||||
|
Fuente: "api_check",
|
||||||
|
Tipo: "API_CHECK",
|
||||||
|
Estado: "PAID",
|
||||||
|
PaymentID: paymentID,
|
||||||
|
Referencia: ref,
|
||||||
|
Procesado: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return c.JSON(fiber.Map{
|
||||||
|
"confirmado": true,
|
||||||
|
"fuente": "dlocal_api",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Sin confirmación aún ─────────────────────────────────────────────────
|
||||||
|
return c.JSON(fiber.Map{"confirmado": false})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user