Comunidade
WebHook não esta batendo os tokens.
22 hours ago by Igor Tomás
Tenho um sistema de assinatura(php laravel) e após a assinatura recebo o payload do pagbank com o x-payload-signature (apenas na producao, não conseguir testar na homologaçao).
Fiz todo sistema de webhooks porem os tokens NUNCA batem, sempre ocorre Signature mismatch.
Ja tentei variad formas e na documentação esta MUITO confusa (https://developer.pagbank.com.br/reference/webhooks).
Meu codigo de validação esta assim, nao tenho nem ideia do que esta ocorrendo:
public function notification(Request $request)
{
// =============================
// 1. PAYLOAD CRU (CRÍTICO)
// =============================
$payload = $request->getContent();
$headers = $request->headers->all();
$sigPayload = $request->header('x-payload-signature');
// =============================
// 2. LOG / AUDITORIA
// =============================
$capture = [
'received_at' => now()->toIso8601String(),
'ip' => $request->ip(),
'method' => $request->method(),
'path' => $request->path(),
'headers' => $headers,
'body_raw' => $payload,
'body_json' => json_decode($payload, true),
'sha256' => hash('sha256', $payload),
];
$fname = 'pagbank/webhooks/' . now()->format('Ymd_His_u') . '-' . Str::random(6) . '.json';
Storage::disk('local')->put(
$fname,
json_encode($capture, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
);
Log::channel('pagbank')->info('Webhook capture saved', [
'file' => storage_path('app/' . $fname)
]);
// =============================
// 3. VALIDAÇÃO DA ASSINATURA
// =============================
if (app()->environment('production')) {
if (!$sigPayload) {
Log::channel('pagbank')->warning('Missing x-payload-signature');
return response('Missing signature', 400);
}
// 🔑 BUSCA DA PUBLIC KEY DO PAGBANK
$resp = json_decode($this->pagseguro->getPublicKey(), true);
$publicKeyB64 = $resp['public_key'] ?? null;
if (!$publicKeyB64) {
Log::channel('pagbank')->error('Public key não retornada pelo PagBank');
return response('Server misconfigured', 500);
}
$pubPem =
"-----BEGIN PUBLIC KEY-----\n" .
chunk_split($publicKeyB64, 64, "\n") .
"-----END PUBLIC KEY-----\n";
$pubKey = openssl_pkey_get_public($pubPem);
if (!$pubKey) {
Log::channel('pagbank')->error('openssl_pkey_get_public falhou', [
'openssl_error' => openssl_error_string()
]);
return response('Invalid public key', 500);
}
$sigBin = base64_decode($sigPayload, true);
if ($sigBin === false) {
Log::channel('pagbank')->warning('x-payload-signature inválido (base64)');
return response('Invalid signature', 401);
}
$ok = openssl_verify(
$payload,
$sigBin,
$pubKey,
OPENSSL_ALGO_SHA256
) === 1;
if (!$ok) {
Log::channel('pagbank')->warning('Signature mismatch (x-payload-signature)', [
'payload_sha256' => hash('sha256', $payload),
'sig_base64' => $sigPayload,
'sig_hex' => bin2hex($sigBin),
]);
return response('Invalid signature', 401);
}
Log::channel('pagbank')->info('Signature OK (x-payload-signature)');
}
// =============================
// 4. JSON VÁLIDO
// =============================
$data = json_decode($payload, true);
if (json_last_error() !== JSON_ERROR_NONE) {
Log::channel('pagbank')->warning('Invalid JSON payload');
return response('Invalid JSON', 400);
}
// =============================
// 5. PROCESSAMENTO
// =============================
\App\Jobs\ProcessaPagamento::dispatch($data)
->onQueue('webhooks');
return response()->noContent(); // 204
}
a public-key esta vindo de uma requisição API /public-keys usando o token no header (recebo ela normal).
