Automatizar Pasaportes Digitales de Producto con Webhooks

Un Pasaporte Digital de Producto no es una página estática: cada escaneo es un evento sobre el que puedes construir. Reacciona a qr.scanned para analítica, reposiciones y avisos de retirada, mantén actualizados los datos del pasaporte desde tu ERP y verifica cada payload con HMAC-SHA256. Una guía de nivel desarrollador con código.

por QR3 Redaktion

Automatizar Pasaportes Digitales de Producto con Webhooks

La mayoría de los equipos tratan un Pasaporte Digital de Producto como una página: lo creas, imprimes el código QR y te olvidas de él. Eso deja sin aprovechar la señal más útil. Cada vez que alguien escanea el QR de un producto, eso es un evento: una persona real, en un país real, sosteniendo una unidad real, en un momento real. Conecta esos eventos a tu stack y el pasaporte deja de ser una página estática para convertirse en el front-end de una canalización de automatización. Esta guía muestra cómo suscribirse a qr.scanned, verificar cada payload y convertir escaneos y actualizaciones en flujos de trabajo reales con el SDK de qr3.

Por qué un DPP es una fuente de eventos, no una página estática

El valor de un pasaporte no es la página que un consumidor ve una sola vez. Es el flujo de interacciones a su alrededor: escaneos sobre el terreno, cambios de datos desde tu ERP, transiciones de ciclo de vida. Cada uno es algo a lo que tus sistemas pueden reaccionar en tiempo real.

Los Webhooks invierten el modelo habitual de sondeo. En lugar de preguntar "¿ha pasado algo?" con un temporizador, qr3 te llama a ti en el momento en que ocurre. Los tipos de evento que la plataforma emite incluyen qr.scanned, además de qr.created, qr.updated y qr.deleted para los cambios de ciclo de vida. El que la mayoría de los equipos infrautiliza es qr.scanned: se dispara cuando un consumidor, un técnico o un agente de aduanas escanea realmente un producto en el mundo real.

Un payload de qr.scanned lleva el contexto que necesitas para actuar, incluido el país del escaneo y el dpp/code id que identifica qué unidad se escaneó. Eso es suficiente para impulsar la analítica, la reposición y la lógica de retirada sin intervención humana.

Suscribirse a qr.scanned

Apunta un endpoint de webhook a tu servicio y gestiona el evento. El SDK de qr3 incluye un verificador para que no tengas que analizar los cuerpos en bruto a mano:

import express from "express";
import { verifyWebhook } from "@qr3/sdk";

const app = express();
const secret = process.env.QR3_WEBHOOK_SECRET!;

// Use the raw body so the signature matches the exact bytes qr3 signed.
app.post("/webhooks/qr3", express.raw({ type: "application/json" }), (req, res) => {
  const event = verifyWebhook(req.body, req.headers["qr3-signature"], secret);

  if (event.type === "qr.scanned") {
    // event payload includes fields like the scan country and the dpp/code id
    handleScan(event);
  }

  res.sendStatus(200);
});

El handler es deliberadamente ligero: verifica, ramifica según event.type y confirma rápido con un 200. Realiza el trabajo pesado (escrituras de analítica, llamadas al ERP) de forma asíncrona para que un servicio downstream lento nunca bloquee la confirmación.

Verificar firmas (verifyWebhook, HMAC-SHA256): hazlo siempre

Un endpoint de webhook es una URL pública. Cualquiera que lo encuentre puede hacer un POST contra él. Si confías en el cuerpo sin comprobar quién lo envió, un atacante puede falsificar "escaneos", desencadenar reposiciones falsas o disparar avisos de retirada inexistentes. Verifica siempre la firma antes de actuar sobre un payload.

qr3 firma cada webhook con HMAC-SHA256 sobre el cuerpo de la petición, usando el secreto de tu endpoint. La firma llega en la cabecera de petición qr3-signature. verifyWebhook(body, signature, secret) recalcula el HMAC y lo compara; si no coincide, lanza una excepción y rechazas la petición:

import { verifyWebhook } from "@qr3/sdk";

app.post("/webhooks/qr3", express.raw({ type: "application/json" }), (req, res) => {
  try {
    const event = verifyWebhook(req.body, req.headers["qr3-signature"], secret);
    process(event);
    res.sendStatus(200);
  } catch {
    // signature mismatch → not from qr3 (or body was altered in transit)
    res.sendStatus(401);
  }
});

Tres reglas que mantienen esto honesto:

  • Verifica contra los bytes en bruto. Re-serializar JSON puede reordenar claves y cambiar los espacios en blanco, lo que rompe el HMAC. Captura el cuerpo en bruto (arriba, express.raw).
  • Mantén el secreto en secreto. Vive en tu entorno, nunca en el código del cliente ni en un repositorio.
  • Falla cerrado. Sin firma válida → 401, sin efectos secundarios. Nunca "procesar de todos modos" ante una discrepancia.

Patrones: analítica / reposición / retirada

Una vez que confías en el evento, un puñado de patrones cubre la mayoría de lo que los equipos quieren:

function handleScan(event: { type: string; data: { country?: string; dpp_id?: string } }) {
  // 1) Analytics — where and how often are products scanned?
  metrics.increment("dpp.scan", { country: event.data.country });

  // 2) Re-order — a scan can signal consumption or field activity
  if (event.data.country) maybeReplenish(event.data.dpp_id, event.data.country);

  // 3) Recall flag — scans of a flagged unit alert your team
  if (isRecalled(event.data.dpp_id)) alertRecall(event.data.dpp_id, event.data.country);
}
  • Analítica: agrega los escaneos por país y por unidad para ver la interacción en el mundo real: qué mercados escanean de verdad y qué SKU registran más interacción posventa.
  • Reposición / reabastecimiento: una ráfaga de escaneos en una región puede alimentar señales de demanda o desencadenar flujos de reabastecimiento en tu ERP.
  • Retirada / seguridad: si una unidad está en retirada, un escaneo es una oportunidad para llegar a quien la tenga: alerta a tu equipo o muestra un aviso en el propio pasaporte.

Ninguno de estos necesita sondeo ni un lote nocturno. Ocurren en el instante en que se escanea el producto.

Mantener los datos al día con client.dpp.update

Reaccionar a los escaneos es la mitad del bucle; la otra mitad es mantener el propio pasaporte exacto. Normativas como el ESPR (UE 2024/1781) y el Reglamento de Baterías (UE 2023/1542) esperan que los datos del pasaporte reflejen la realidad a lo largo de la vida del producto: huella de carbono recalculada, instrucciones de reparación actualizadas, objetivos de contenido reciclado alcanzados.

Impulsa esas actualizaciones desde el sistema de registro. Cuando un valor cambie en tu ERP, envíalo al pasaporte:

import { QR3 } from "@qr3/sdk";

const client = new QR3({ apiKey: process.env.QR3_API_KEY! });

// GTIN and serial are immutable; data fields are updatable.
await client.dpp.update(dppId, {
  battery_data: { carbon_footprint_kg: 58, recycled_content_pct: 16 },
});

Como el QR codifica una URL de resolución estable (https://qr3.app/dpp/{gtin}/{serial}, añade ?format=jsonld para JSON-LD), nunca vuelves a imprimir una etiqueta para cambiar datos. La identidad permanece fija; el contenido tras ella se mantiene actualizado. Combina esto con qr.updated y podrás difundir una notificación cada vez que un pasaporte cambie, cerrando el bucle entre tu ERP, el pasaporte y cualquiera que esté observando downstream.

Una tabla de eventos: evento → qué automatizar

Evento Se dispara cuando Qué automatizar
qr.scanned Se escanea el QR de un producto sobre el terreno Analítica por país, señales de reabastecimiento, alertas de retirada
qr.created Se crea un nuevo pasaporte Indexarlo, sincronizar con PIM/ERP, notificar al equipo de catálogo
qr.updated Cambian los datos del pasaporte Re-cachear la página pública, difundir notificaciones de cambio
qr.deleted Se elimina un pasaporte Marcar como baja los registros internos, revocar referencias downstream

Empieza con qr.scanned para la interacción y las señales sobre el terreno; añade los eventos de ciclo de vida a medida que sincronizas los pasaportes en tus sistemas más amplios.

Preguntas frecuentes

¿Tengo que verificar la firma si la URL de mi endpoint es secreta? Sí. Una URL no es un secreto: se filtra en registros, proxies e historial del navegador. La verificación HMAC con verifyWebhook es lo único que demuestra que un payload realmente provino de qr3.

¿Qué pasa si mi endpoint está caído cuando se dispara un evento? Confirma rápido con 200 una vez que hayas verificado, y haz el trabajo lento de forma asíncrona para que los problemas transitorios downstream nunca detengan la respuesta. Mantén tu propia idempotencia sobre el dpp/code id para que una entrega reintentada no se cuente dos veces.

¿Puedo actualizar el GTIN o el serial con client.dpp.update? No: el GTIN y el serial son inmutables; son la identidad estable del producto. Solo los campos de datos son actualizables. Esa inmutabilidad es precisamente lo que permite que el QR impreso siga siendo válido para siempre.

Fuentes

Empieza gratis y conecta tu primer webhook de DPP: app.qr3.app/sign-up

Artículos relacionados