1

Se alguém chegar aqui com o mesmo problema atente-se para isso:
Ao validar a assinatura de um webhook do Mercado Pago, é importante observar que, embora o parâmetro data.id possa ser recebido com caracteres alfanuméricos em maiúsculo na notificação (ex: ORD01JQ4S...), ele deve ser obrigatoriamente convertido para minúsculo (lowercase) durante o processo de verificação da assinatura para o cálculo do HMAC coincidir.

Isso não está claro na documentação, mas é assim e pode ser o seu caso.

Ex em node:

async function verifyMpSignature(
  xSignature: string,
  xRequestId: string | null,
  dataId: string | null,
  secret: string,
): Promise<boolean> {

  let ts: string | null = null;
  let v1: string | null = null;
  for (const part of xSignature.split(',')) {
    const [k, v] = part.trim().split('=');
    if (k === 'ts') ts = v;
    else if (k === 'v1') v1 = v;
  }
  if (!ts || !v1) return false;

  const parts: string[] = [];
  if (dataId) parts.push(`id:${dataId.toLowerCase()}`);
  if (xRequestId) parts.push(`request-id:${xRequestId}`);
  parts.push(`ts:${ts}`);
  const manifest = parts.join(';') + ';';


  const encoder = new TextEncoder();
  const key = await crypto.subtle.importKey(
    'raw',
    encoder.encode(secret),
    { name: 'HMAC', hash: 'SHA-256' },
    false,
    ['sign'],
  );
  const signature = await crypto.subtle.sign('HMAC', key, encoder.encode(manifest));
  const hex = Array.from(new Uint8Array(signature))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');

  return hex === v1;
}
Carregando publicação patrocinada...