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.
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.
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.
/resultado con el estado y los importes.benefitId: el benefitId que devuelve la consulta se vuelve a enviar en la notificación, para correlacionar oferta ↔ pago.202 al instante y procesa asincrónico. Nunca debe frenar la respuesta al POS.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é | Valor | Detalle |
|---|---|---|
| URL base | https://<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-Type | application/json | Cuerpo JSON en las dos llamadas. |
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
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.GatewayQR pregunta qué beneficios aplican a una transacción. Ruta caliente: BeneficiosCenter resuelve contra un snapshot en memoria y responde en milisegundos.
// 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 } }
{
"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 respuesta | Significado |
|---|---|
| benefitId | Id del beneficio ofrecido. Guardarlo: vuelve en la notificación de resultado. |
| paymentMethodId | Medio 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). |
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":"…"}.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.
// 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 }
{
"requestId": "POS-2026-000123",
"estado": "APROBADO",
"encolado": true
}
// 202 = recibido y encolado.
// El procesamiento en la DB ocurre
// aparte, fuera de esta respuesta.
| Campo | Regla |
|---|---|
| requestId * | Mismo requestId de la consulta. Es la clave de correlación e idempotencia (≤100). |
| estado * | APROBADO o RECHAZADO. |
| benefitId | El benefitId devuelto por la consulta. Correlaciona oferta ↔ pago. |
| importes / descuentoAplicado | Montos del pago (≥ 0). descuentoAplicado = lo realmente otorgado. |
| motivoRechazo | Opcional, ≤200. Útil cuando estado = RECHAZADO. |
requestId: un reintento del gateway con el mismo requestId actualiza la misma fila, nunca duplica. Seguro para reenviar.202 es inmediato y el trabajo pesado corre aparte.benefitId.202 como éxito y con reintento seguro ante error de red.X-Api-Key ni datos personales (CUIT).