API NestJS que recibe el Webhook Messenger de SAP Business One (CloudEvents), valida HMAC opcional y guarda cada notificacion local (data/events/) e inserta en Postgres (webhook_events). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.9 KiB
Cómo ejecutar la API (con y sin HMAC)
Guía rápida para levantar sap-webhook-api en los dos modos soportados:
sin autenticación (AuthenticationType: None, el modo actual de la
suscripción real en SAP) y con firma HMAC.
0. Una sola vez: preparar el entorno
cd sap-webhook-api
npm install
cp .env.example .env # si todavía no existe .env
Revisá que .env tenga los datos correctos de tu Service Layer
(SERVICE_LAYER_URL, COMPANY_DB, SL_USER, SL_PASS, WEBHOOK_ID). El
certificado HTTPS (certs/key.pem / certs/cert.pem) ya debería existir —
si no, ver PASOS-REALIZADOS.md, sección 9.
Importante: el modo con el que arranca la API (.env →
HMAC_SECRET_KEY) tiene que coincidir con el AuthenticationType
configurado en la suscripción real de SAP. Si no coinciden, SAP manda
notificaciones que la API rechaza (o al revés, la API acepta sin validar
nada aunque SAP crea que está firmando). Los scripts de la sección 2 se
encargan de mantenerlos sincronizados.
1. Modo sin autenticación (AuthenticationType: None)
Es el modo por defecto — no requiere ningún paso extra.
# confirmá que HMAC_SECRET_KEY esté vacío en .env
npm run start
La API queda escuchando en https://<tu-ip>:3000/webhooks/sap, acepta
cualquier notificación sin validar firma. Prueba local:
curl -sk -i -X POST https://localhost:3000/webhooks/sap \
-H "Content-Type: application/json" \
-d '[{"id":"test-1","type":"sap.b1.Orders.Created.v1","subject":"1","data":{"DocEntry":"1"}}]'
# -> 200 OK
2. Modo con HMAC (AuthenticationType: HMAC)
2.1 Activar
npm run auth:hmac:on
Esto:
- Genera un
HMAC_SECRET_KEY(si.envno tenía uno) y lo guarda en.env. - Hace
Loginen el Service Layer, lee la configuración actual de la suscripción (WEBHOOK_IDde.env), la pausa, la elimina y la vuelve a crear conAuthenticationType: "HMAC"— el Service Layer no permite cambiarAuthenticationTypeconPATCHsobre una suscripción existente, así que este es el único camino soportado (se conservaWebhookURL,HandshakeyEventCollectionoriginales).AuthenticationCredno es el secreto pelado: va como un string con JSON embebido,{"Key": "<secreto>", "Algorithm": "hmacsha256"}.
Después, reiniciá la API para que tome el HMAC_SECRET_KEY nuevo:
npm run start
A partir de este momento, todo POST /webhooks/sap sin la firma correcta
en el header X-B1-Webhook-Signature (HMAC-SHA256 del body, en base64)
devuelve 401 Unauthorized.
2.2 Probar manualmente (simulando lo que hace SAP)
SECRET=$(grep '^HMAC_SECRET_KEY=' .env | cut -d= -f2)
BODY='[{"id":"test-2","type":"sap.b1.Orders.Created.v1","subject":"2","data":{"DocEntry":"2"}}]'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -binary | openssl base64)
curl -sk -i -X POST https://localhost:3000/webhooks/sap \
-H "Content-Type: application/json" \
-H "X-B1-Webhook-Signature: $SIG" \
-d "$BODY"
# -> 200 OK
# sin firma o con una firma incorrecta -> 401
curl -sk -i -X POST https://localhost:3000/webhooks/sap \
-H "Content-Type: application/json" -d "$BODY"
2.3 Desactivar (volver a None)
npm run auth:hmac:off
npm run start # reiniciar para que la API deje de exigir la firma
Esto revierte la suscripción en SAP a AuthenticationType: "None" y vacía
HMAC_SECRET_KEY en .env, en un solo paso.
Referencia rápida
| Acción | Comando |
|---|---|
| Instalar dependencias | npm install |
| Levantar la API | npm run start |
| Activar HMAC (API + SAP) | npm run auth:hmac:on |
| Desactivar HMAC (API + SAP) | npm run auth:hmac:off |
| Ver estado actual de la suscripción | curl -sk -b cookies.txt "$SERVICE_LAYER_URL/EventSubscriptions('$WEBHOOK_ID')" (después de un Login) |
Detalle de la implementación (cómo se valida la firma, por qué se usa el
body crudo, etc.) en CLAUDE.md.