# 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 ```bash 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. ```bash # confirmá que HMAC_SECRET_KEY esté vacío en .env npm run start ``` La API queda escuchando en `https://:3000/webhooks/sap`, acepta cualquier notificación sin validar firma. Prueba local: ```bash 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 ```bash npm run auth:hmac:on ``` Esto: 1. Genera un `HMAC_SECRET_KEY` (si `.env` no tenía uno) y lo guarda en `.env`. 2. Hace `Login` en el Service Layer, lee la configuración actual de la suscripción (`WEBHOOK_ID` de `.env`), la **pausa**, la **elimina** y la **vuelve a crear** con `AuthenticationType: "HMAC"` — el Service Layer no permite cambiar `AuthenticationType` con `PATCH` sobre una suscripción existente, así que este es el único camino soportado (se conserva `WebhookURL`, `Handshake` y `EventCollection` originales). `AuthenticationCred` no es el secreto pelado: va como un string con JSON embebido, `{"Key": "", "Algorithm": "hmacsha256"}`. Después, **reiniciá la API** para que tome el `HMAC_SECRET_KEY` nuevo: ```bash 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) ```bash 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`) ```bash 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`.