# 🔧 Correção: Webhook HMAC retorna 401

## 🐛 Problema Reportado

- ✅ Webhook funciona SEM HMAC (retorna 200 OK)
- ❌ Webhook COM HMAC Secret retorna 401 Unauthorized

## 🔍 Causa Raiz

O OpenPIX pode usar diferentes formatos para o secret HMAC:
1. Secret direto como string
2. Secret com prefixo `openpix_` que precisa ser removido
3. Secret em formato Base64 que precisa ser decodificado
4. Combinação dos acima

## ✅ Solução Implementada

### 1. Suporte a Múltiplos Headers

O OpenPIX pode enviar a assinatura em diferentes headers:
- `x-webhook-signature`
- `x-openpix-signature`
- `X-OpenPix-Signature`

**Código atualizado:**
```php
$signature = $request->header('x-webhook-signature') 
    ?? $request->header('x-openpix-signature')
    ?? $request->header('X-OpenPix-Signature');
```

### 2. Validação HMAC com Múltiplos Métodos

O código agora tenta **4 métodos diferentes** de validação:

#### Método 1: Secret Direto
```php
$expected = hash_hmac('sha256', $payload, $secret);
```

#### Método 2: Secret sem Prefixo "openpix_"
```php
$secretWithoutPrefix = substr($secret, 8); // Remove "openpix_"
$expected = hash_hmac('sha256', $payload, $secretWithoutPrefix);
```

#### Método 3: Secret sem Prefixo, Decodificado Base64
```php
$secretWithoutPrefix = substr($secret, 8);
$secretDecoded = base64_decode($secretWithoutPrefix);
$expected = hash_hmac('sha256', $payload, $secretDecoded);
```

#### Método 4: Secret Completo Decodificado Base64
```php
$secretDecoded = base64_decode($secret);
$expected = hash_hmac('sha256', $payload, $secretDecoded);
```

### 3. Logs Detalhados para Debug

O código agora loga informações detalhadas quando a validação falha:
```php
Log::warning('OpenPIX Webhook: assinatura HMAC inválida', [
    'signature_received' => substr($signature, 0, 20) . '...',
    'expected_signature' => substr($expected, 0, 20) . '...',
    'payload_sample' => substr($rawPayload, 0, 100) . '...',
    'debug_info' => [...todos os métodos tentados...],
]);
```

## 🚀 Como Aplicar no Servidor

### Passo 1: Atualizar o Código

```bash
cd /var/www/gestorstream

# Backup
cp backend/app/Http/Controllers/Api/WebhookController.php \
   backend/app/Http/Controllers/Api/WebhookController.php.backup.hmac

# Atualizar
git pull origin main

# Limpar cache
cd backend
php artisan config:clear
php artisan cache:clear
php artisan route:clear
```

### Passo 2: Executar Script de Teste HMAC

```bash
cd /var/www/gestorstream
php test_hmac_validation.php
```

**O que este script faz:**
- ✅ Testa os 4 métodos diferentes de HMAC
- ✅ Mostra qual signature é gerada por cada método
- ✅ Tenta cada um no webhook real
- ✅ Identifica qual método funciona
- ✅ Fornece instruções específicas

**Resultado esperado:**
```
========================================
✅ MÉTODO CORRETO ENCONTRADO!
========================================

Método que funciona: Secret sem prefixo (Base64 decoded)
Signature gerada: a1b2c3d4e5f6...

Configure no painel do OpenPIX:
- URL: https://gestor.jf.eng.br/api/webhooks/openpix
- Webhook Secret: openpix_EtpEIRxeT+5yt4MM4E8Ern3/WVoLzuRDtlJx15jHrFc=
```

### Passo 3: Ver Logs Detalhados

```bash
# Ver logs em tempo real
tail -f /var/www/gestorstream/backend/storage/logs/laravel.log

# Ou buscar logs específicos de HMAC
tail -200 /var/www/gestorstream/backend/storage/logs/laravel.log | grep -A 10 'HMAC'
```

## 🧪 Testes Manuais

### Teste 1: Webhook SEM HMAC (deve funcionar)

```bash
curl -X POST https://gestor.jf.eng.br/api/webhooks/openpix \
  -H "Content-Type: application/json" \
  -d '{
    "event": "OPENPIX:CHARGE_COMPLETED",
    "charge": {
      "correlationID": "test123",
      "transactionID": "test456",
      "status": "COMPLETED"
    }
  }'
```

**Esperado:** `{"status":"ok"}` com HTTP 200 ✅

### Teste 2: Webhook COM HMAC (deve funcionar após correção)

```bash
# O script test_hmac_validation.php fará isso automaticamente
php test_hmac_validation.php
```

## 📊 Logs de Debug

Após a correção, os logs mostrarão:

### Quando HMAC é Válido:
```log
[2026-01-12 22:00:00] DEBUG: OpenPIX Webhook Headers Debug
  has_secret_config: true
  secret_length: 49
  signature_header: a1b2c3d4e5f6789...
  signature_length: 64
  payload_length: 245

[2026-01-12 22:00:01] INFO: OpenPIX Webhook: Assinatura HMAC validada com sucesso
  validation_method: secret_base64_decoded
```

### Quando HMAC é Inválido:
```log
[2026-01-12 22:00:00] WARNING: OpenPIX Webhook: assinatura HMAC inválida
  signature_received: a1b2c3d4e5f6789...
  expected_signature: x9y8z7w6v5u4t3s...
  payload_sample: {"event":"OPENPIX:CHARGE_COMPLETED","charge":{"correlationID":"test123"...
  debug_info:
    expected_direct: x9y8z7w6v5u4t3s...
    expected_without_prefix: p0q9r8s7t6u5v4w...
    expected_decoded: m3n4o5p6q7r8s9t...
    expected_full_decoded: k1l2m3n4o5p6q7r...
```

## 🔐 Configuração Final no OpenPIX

Depois que o teste identificar o método correto:

### URL de Webhook:
```
https://gestor.jf.eng.br/api/webhooks/openpix
```

### Webhook Secret (HMAC):
```
openpix_EtpEIRxeT+5yt4MM4E8Ern3/WVoLzuRDtlJx15jHrFc=
```

### Evento:
```
OPENPIX:CHARGE_COMPLETED
```

### Cabeçalhos HTTP:
- `Content-Type`: `application/json`
- `Accept`: `application/json`
- `X-OpenPix-Signature`: `Gerado por requisição` (o OpenPIX gera automaticamente)

⚠️ **IMPORTANTE:** 
- NÃO configure o header `Authorization` manualmente
- O header `X-OpenPix-Signature` será gerado automaticamente pelo OpenPIX baseado no secret

## 🐛 Troubleshooting

### Problema: Ainda retorna 401 após aplicar correção

**Solução 1: Verificar o Secret**
```bash
cd /var/www/gestorstream/backend
grep OPENPIX_WEBHOOK_SECRET .env

# Se estiver diferente do painel OpenPIX, atualizar:
nano .env
# OPENPIX_WEBHOOK_SECRET=openpix_EtpEIRxeT+5yt4MM4E8Ern3/WVoLzuRDtlJx15jHrFc=

php artisan config:clear
```

**Solução 2: Verificar Logs**
```bash
tail -200 /var/www/gestorstream/backend/storage/logs/laravel.log | grep -B 5 -A 10 'HMAC inválida'
```

Os logs mostrarão:
- Signature recebida
- Signature esperada (para cada método)
- Tamanho do payload
- Todas as tentativas de validação

**Solução 3: Testar Manualmente Cada Método**
```bash
php test_hmac_validation.php
```

Este script testará todos os 4 métodos e mostrará qual funciona.

### Problema: OpenPIX não está enviando X-OpenPix-Signature

**Causa:** O secret não está configurado no painel do OpenPIX

**Solução:**
1. Acesse o painel do OpenPIX
2. Vá em Configurações > Webhooks
3. Configure o "Webhook Secret (HMAC)"
4. Cole o valor: `openpix_EtpEIRxeT+5yt4MM4E8Ern3/WVoLzuRDtlJx15jHrFc=`
5. Salve

### Problema: Logs mostram "signature_header: none"

**Causa:** O OpenPIX não está enviando o header de assinatura

**Soluções:**
1. **Temporária**: Remover o secret do `.env` para desabilitar validação HMAC
   ```bash
   cd /var/www/gestorstream/backend
   nano .env
   # Comentar: #OPENPIX_WEBHOOK_SECRET=...
   php artisan config:clear
   ```

2. **Permanente**: Configurar corretamente o secret no painel OpenPIX

## ✅ Checklist de Validação

Antes de registrar no OpenPIX, certifique-se:

- [ ] `git pull` executado
- [ ] Cache limpo
- [ ] `php test_webhook.php` retorna 200 (sem HMAC)
- [ ] `php test_hmac_validation.php` identifica método correto
- [ ] Logs mostram "Assinatura HMAC validada com sucesso"
- [ ] Secret no `.env` é igual ao do painel OpenPIX

## 📚 Referências

- [OpenPIX Webhook Signature Documentation](https://developers.openpix.com.br/docs/webhook/webhook-signature)
- [HMAC-SHA256 em PHP](https://www.php.net/manual/en/function.hash-hmac.php)
- [Base64 Encoding em PHP](https://www.php.net/manual/en/function.base64-decode.php)

---

**Data:** 2026-01-12  
**Tipo:** Correção de Validação HMAC (401 Unauthorized)  
**Status:** Implementado, aguardando teste no servidor  
**Impacto:** Permite webhook com validação HMAC segura
