Integración · Money-path

GatewayQR → BeneficiosCenter

Cómo llama GatewayQR a BeneficiosCenter: los dos flujos —consulta de beneficios y notificación del resultado— con su ida y vuelta, y qué hay que configurar del lado de GatewayQR.

BeneficiosCenter en producción Cambios: solo configuración Auth: X-Api-Key Puerto único · API + consola

¿Hay que tocar la base de datos?

No. Del lado de GatewayQR es solo configuración (yaml/yml) — cero cambios de DB.

GatewayQR solo consume endpoints HTTP: alcanza con configurar la URL base de BeneficiosCenter y la X-Api-Key acordada. No hay esquema, tabla ni migración que tocar en GatewayQR.

Del lado de BeneficiosCenter, la base la administra Flyway automáticamente: al desplegar la versión nueva del jar, las migraciones se aplican solas en el arranque. No hay trabajo manual de DB en ningún lado.

Lo que cambia para GatewayQR

El contrato de la consulta (Flujo 1) ya está integrado y no cambia. Lo nuevo es el Flujo 2: notificar a BeneficiosCenter el resultado del pago, para que pueda medir el descuento realmente otorgado y la conversión.

Configuración en GatewayQR

Todo por yaml/config — sin cambios de código. El bloque app.beneficioscenter ya viene en el repo de GatewayQR; estos son los valores a ajustar.

QuéValorDetalle
URL basehttps://<host-beneficioscenter>Puerto único (p. ej. :8080, según despliegue). Todos los endpoints cuelgan de /api/v1/beneficios/.
Header *X-Api-Key: <clave-acordada>Obligatorio en ambos endpoints. Es un secreto compartido; sin él o con valor incorrecto → 401. Nunca lo pongan en la URL ni en logs.
Content-Typeapplication/jsonCuerpo JSON en las dos llamadas.
YAML GatewayQR · src/main/resources/config/application-prod.yml
app:
  beneficioscenter:
    enabled: true                # activar la integración
    base-url: http://beneficioscenter:8080  # host prod (dev: :8081)
    api-key: CHANGE_ME            # ← poner el secreto acordado
    connect-timeout-ms: 300       # timeouts cortos:
    read-timeout-ms: 800          # nunca cuelgan al POS (money-path)
    result-connect-timeout-ms: 300
    result-read-timeout-ms: 800
i
Este bloque ya viene en el repo de GatewayQR (application-prod.yml y application-dev.yml). Solo hay que ajustar api-key (hoy CHANGE_ME) con el secreto acordado y confirmar base-url. Es el mismo valor que BeneficiosCenter define en bc.gateway.api-key — un secreto compartido; si se rota, se coordina de los dos lados.

1 Consulta de beneficios

GatewayQR pregunta qué beneficios aplican a una transacción. Ruta caliente: BeneficiosCenter resuelve contra un snapshot en memoria y responde en milisegundos.

GatewayQR
// caller
POST /resolver
200 beneficios[]
BeneficiosCenter
// /api/v1/beneficios
POST /api/v1/beneficios/resolver request
// headers: X-Api-Key, Content-Type: application/json
{
  "requestId": "POS-2026-000123",   // único, correlación
  "transaction": {
    "datetime": "2026-09-13T22:47:56Z", // ISO-8601 c/offset
    "amount": 25000.00,
    "currency": "ARS"          // opcional
  },
  "merchant": {
    "branchId": "3",           // obligatorio (sucursal)
    "posId": 1,
    "salesPointId": 1
  },
  "invoice": {                  // opcional
    "type": "B",
    "taxIdKind": "CUIT",
    "taxId": "20304050607",
    "extraCustomerTypeId": null // código de segmento
  }
}
Respuesta 200 OK
{
  "requestId": "POS-2026-000123",
  "evaluatedAt": "2026-09-13T19:47:56-03:00",
  "benefits": [
    {
      "benefitId": 2,           // ← se devuelve en Flujo 2
      "customerTypeCode": "DINI_GIFTCARD",
      "paymentMethodId": "991",
      "type": "DISCOUNT",
      "percentage": 5.00,
      "discountAmount": 1250.00,
      "maxDiscountAmount": null,
      "description": "5% DINI Gift Card"
    }
  ],
  "elapsedMs": 2
}
Campo de respuestaSignificado
benefitIdId del beneficio ofrecido. Guardarlo: vuelve en la notificación de resultado.
paymentMethodIdMedio de pago al que aplica el beneficio (string).
percentage / discountAmount% y monto de descuento cotizado para esta transacción. maxDiscountAmount = tope, o null.
benefits: []Vacío = no hay beneficio para esta transacción (respuesta válida, no es error).
!
Errores: 401 si falta o es inválida la X-Api-Key · 400 si el cuerpo no valida (p. ej. falta transaction.datetime), con {"field":"…","message":"…"}.

2 Notificación de resultado

Al confirmarse o rechazarse el pago, GatewayQR avisa el desenlace. BeneficiosCenter lo encola y responde 202 al instante — así calcula el descuento realmente otorgado y la conversión, sin frenar al POS.

GatewayQR
// caller
POST /resultado
202 encolado
BeneficiosCenter
// async · idempotente
POST /api/v1/beneficios/resultado request
// headers: X-Api-Key, Content-Type: application/json
{
  "requestId": "POS-2026-000123", // = el de la consulta
  "estado": "APROBADO",        // APROBADO | RECHAZADO
  "paymentMethodId": 991,
  "benefitId": 2,             // ← el de la respuesta del Flujo 1
  "descuentoAplicado": 1250.00,
  "importeOriginal": 25000.00,
  "importeFinal": 23750.00,
  "motivoRechazo": null       // opcional, ≤200, para RECHAZADO
}
Respuesta 202 Accepted
{
  "requestId": "POS-2026-000123",
  "estado": "APROBADO",
  "encolado": true
}

// 202 = recibido y encolado.
// El procesamiento en la DB ocurre
// aparte, fuera de esta respuesta.
CampoRegla
requestId *Mismo requestId de la consulta. Es la clave de correlación e idempotencia (≤100).
estado *APROBADO o RECHAZADO.
benefitIdEl benefitId devuelto por la consulta. Correlaciona oferta ↔ pago.
importes / descuentoAplicadoMontos del pago (≥ 0). descuentoAplicado = lo realmente otorgado.
motivoRechazoOpcional, ≤200. Útil cuando estado = RECHAZADO.
Idempotente por requestId: un reintento del gateway con el mismo requestId actualiza la misma fila, nunca duplica. Seguro para reenviar.
!
Money-path: la imputación del resultado no debe frenar en ningún caso la respuesta al POS. Enviá esta notificación de forma asincrónica / fire-and-forget; el 202 es inmediato y el trabajo pesado corre aparte.

Checklist de puesta en marcha