A maioria das equipas trata um Passaporte Digital de Produto como uma página: criam-no, imprimem o código QR e esquecem-no. Isso deixa o sinal mais útil por aproveitar. Sempre que alguém faz a leitura do código QR num produto, isso é um evento — uma pessoa real, num país real, com uma unidade real nas mãos, num momento real. Ligue esses eventos à sua stack e o passaporte deixa de ser uma página estática para se tornar o front end de uma pipeline de automação. Este guia mostra como subscrever qr.scanned, verificar cada payload e transformar leituras e atualizações em fluxos de trabalho reais com o SDK da qr3.
Porque é que um DPP é uma fonte de eventos, e não uma página estática
O valor de um passaporte não está na página que um consumidor vê uma vez. Está no fluxo de interações à sua volta: leituras no terreno, alterações de dados a partir do seu ERP, transições de ciclo de vida. Cada uma é algo a que os seus sistemas podem reagir em tempo real.
Os webhooks invertem o habitual modelo de polling. Em vez de perguntar "aconteceu alguma coisa?" num temporizador, a qr3 chama-o a si no momento em que algo acontece. Os tipos de evento que a plataforma emite incluem qr.scanned, além de qr.created, qr.updated e qr.deleted para as alterações de ciclo de vida. O que a maioria das equipas subaproveita é qr.scanned: dispara quando um consumidor, técnico ou funcionário alfandegário faz efetivamente a leitura de um produto no mundo real.
Um payload qr.scanned transporta o contexto de que precisa para agir — incluindo o país da leitura e o dpp/code id que identifica qual a unidade lida. Isso é suficiente para impulsionar análises, reabastecimento e lógica de recolha sem intervenção humana.
Subscrever qr.scanned
Aponte um endpoint de webhook para o seu serviço e trate o evento. O SDK da qr3 inclui um verificador para que não tenha de analisar corpos de pedido em bruto manualmente:
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);
});
O handler é deliberadamente leve: verificar, ramificar com base em event.type, confirmar rapidamente com um 200. Faça o trabalho pesado (escritas de análises, chamadas ao ERP) de forma assíncrona, para que um sistema a jusante lento nunca bloqueie a confirmação.
Verificar assinaturas (verifyWebhook, HMAC-SHA256) — faça sempre isto
Um endpoint de webhook é um URL público. Qualquer pessoa que o encontre pode fazer-lhe POST. Se confiar no corpo do pedido sem verificar quem o enviou, um atacante pode forjar "leituras", desencadear reposições falsas ou disparar sinalizações de recolha falsas. Verifique sempre a assinatura antes de agir sobre um payload.
A qr3 assina cada webhook com HMAC-SHA256 sobre o corpo do pedido, usando o segredo do seu endpoint. A assinatura chega no cabeçalho de pedido qr3-signature. verifyWebhook(body, signature, secret) recalcula o HMAC e compara-o; se não corresponder, lança uma exceção e você rejeita o pedido:
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);
}
});
Três regras que mantêm isto honesto:
- Verifique contra os bytes em bruto. Voltar a serializar o JSON pode reordenar chaves e alterar espaços em branco, o que quebra o HMAC. Capture o corpo em bruto (acima,
express.raw). - Mantenha o segredo secreto. Vive no seu ambiente, nunca no código do cliente nem num repositório.
- Falhe de forma segura. Sem assinatura válida →
401, sem efeitos secundários. Nunca "processe na mesma" perante uma não correspondência.
Padrões: análises / reposição / recolha
Assim que confia no evento, um punhado de padrões cobre a maior parte do que as equipas querem:
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);
}
- Análises: agregue as leituras por país e por unidade para ver o envolvimento no mundo real — que mercados fazem efetivamente leituras e que SKUs registam mais interação pós-venda.
- Reposição / reabastecimento: um pico de leituras numa região pode alimentar sinais de procura ou desencadear fluxos de trabalho de reabastecimento no seu ERP.
- Recolha / segurança: se uma unidade estiver sujeita a recolha, uma leitura é uma oportunidade de chegar a quem a tem nas mãos — alerte a sua equipa ou mostre um aviso no próprio passaporte.
Nenhum destes precisa de polling nem de um lote noturno. Acontecem no instante em que o produto é lido.
Manter os dados atualizados via client.dpp.update
Reagir às leituras é metade do ciclo; a outra metade é manter o próprio passaporte rigoroso. Regulamentos como o ESPR (UE 2024/1781) e o Regulamento das Baterias (UE 2023/1542) esperam que os dados do passaporte reflitam a realidade ao longo da vida do produto — pegada de carbono recalculada, instruções de reparação atualizadas, metas de conteúdo reciclado atingidas.
Impulsione essas atualizações a partir do sistema de registo. Quando um valor muda no seu ERP, envie-o para o passaporte:
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 o código QR codifica um URL de resolução estável (https://qr3.app/dpp/{gtin}/{serial}, adicione ?format=jsonld para JSON-LD), nunca volta a imprimir uma etiqueta para alterar dados. A identidade mantém-se fixa; o conteúdo por trás dela mantém-se atualizado. Combine isto com qr.updated e pode disparar uma notificação sempre que um passaporte muda — fechando o ciclo entre o seu ERP, o passaporte e quem quer que esteja a observar a jusante.
Uma tabela de eventos: evento → o que automatizar
| Evento | Dispara quando | O que automatizar |
|---|---|---|
qr.scanned |
É feita a leitura do QR de um produto no terreno | Análises por país, sinais de reabastecimento, alertas de recolha |
qr.created |
É criado um novo passaporte | Indexá-lo, sincronizar com o PIM/ERP, notificar a equipa de catálogo |
qr.updated |
Os dados do passaporte mudam | Recriar a cache da página pública, disparar notificações de alteração |
qr.deleted |
Um passaporte é removido | Marcar registos internos como tombstone, revogar referências a jusante |
Comece com qr.scanned para envolvimento e sinais de terreno; acrescente os eventos de ciclo de vida à medida que sincroniza os passaportes nos seus sistemas mais amplos.
FAQ
Tenho de verificar a assinatura se o URL do meu endpoint for secreto?
Sim. Um URL não é um segredo — vaza em registos, proxies e no histórico do navegador. A verificação HMAC com verifyWebhook é a única coisa que prova que um payload veio efetivamente da qr3.
O que acontece se o meu endpoint estiver em baixo quando um evento dispara?
Confirme rapidamente com 200 assim que tiver verificado e faça o trabalho lento de forma assíncrona, para que problemas transitórios a jusante nunca travem a resposta. Mantenha a sua própria idempotência sobre o dpp/code id, para que uma entrega repetida não seja contada duas vezes.
Posso atualizar o GTIN ou o número de série via client.dpp.update? Não — o GTIN e o número de série são imutáveis; são a identidade estável do produto. Apenas os campos de dados são atualizáveis. É precisamente essa imutabilidade que permite que o código QR impresso permaneça válido para sempre.
Fontes
Comece gratuitamente e ligue o seu primeiro webhook de DPP: app.qr3.app/sign-up