Guia webhook Mercado Pago em PHP 8.4 no AlmaLinux 10 é o fluxo de endpoint HTTPS que recebe notificações IPN/Webhooks, consulta a API oficial com access token e atualiza pedidos sem depender só do retorno do checkout. Para implementar com segurança no servidor, siga estes passos:
- Instale PHP 8.4, extensões cURL/JSON e Nginx com TLS no AlmaLinux 10
- Crie o script PHP que aceita POST e responde HTTP 200 rápido
- Valide o recurso na API do Mercado Pago antes de mudar status no banco
- Cadastre a URL pública HTTPS no painel de Webhooks
- Teste com payload simulado e confira logs do Nginx e do PHP-FPM
- Trate reenvios, assinatura e filas para evitar processamento duplicado
Pré-requisitos
- Servidor AlmaLinux 10 com acesso root ou sudo e firewall controlado
- PHP 8.4 com módulos php-curl, php-json, php-mbstring e PHP-FPM ativos
- Nginx (ou Apache) com certificado TLS válido e redirecionamento HTTP→HTTPS
- Conta Mercado Pago com Access Token de produção ou teste e permissão para Webhooks
- Domínio público apontando para o servidor (ex.: seudominio.com.br) e porta 443 aberta
- Banco (MariaDB/MySQL) ou fila para registrar IDs de pagamento já processados
- Ferramentas de diagnóstico:
curl,ss,journalctl, editor de texto
Se ainda estiver montando o ambiente web, o material sobre Acessando servidores VPS Linux da AviraHost ajuda no primeiro acesso SSH antes de subir o endpoint.
Guia webhook Mercado Pago em PHP 8.4: endpoint e validação na API
O núcleo do guia webhook Mercado Pago em PHP 8.4 no AlmaLinux 10 é nunca confiar só no corpo bruto do POST. O Mercado Pago envia um aviso (topic/type e id); sua aplicação deve buscar o pagamento ou a merchant order na API REST com o access token e só então marcar o pedido como aprovado, pendente ou cancelado.
Crie o diretório da aplicação e o arquivo do receptor:
sudo mkdir -p /var/www/seudominio.com.br/webhooks
sudo chown -R nginx:nginx /var/www/seudominio.com.br
sudo nano /var/www/seudominio.com.br/webhooks/mercadopago.php
Conteúdo mínimo seguro (ajuste token e gravação no banco conforme seu schema):
<?php
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');
$log = '/var/log/mercadopago-webhook.log';
$token = getenv('MP_ACCESS_TOKEN') ?: '';
if ($token === '') {
http_response_code(500);
echo json_encode(['error' => 'token ausente']);
exit;
}
$raw = file_get_contents('php://input') ?: '';
$data = json_decode($raw, true);
$id = $_GET['data.id'] ?? ($data['data']['id'] ?? null);
$type = $_GET['type'] ?? ($data['type'] ?? ($data['topic'] ?? ''));
file_put_contents($log, date('c') . " type={$type} id={$id} raw={$raw}\n", FILE_APPEND | LOCK_EX);
if (!$id) {
http_response_code(400);
echo json_encode(['error' => 'id ausente']);
exit;
}
// Responda 200 cedo se for enfileirar; aqui consultamos de forma síncrona e curta
$resource = match (true) {
str_contains((string)$type, 'payment') => "https://api.mercadopago.com/v1/payments/{$id}",
str_contains((string)$type, 'merchant_order') => "https://api.mercadopago.com/merchant_orders/{$id}",
default => "https://api.mercadopago.com/v1/payments/{$id}",
};
$ch = curl_init($resource);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_TIMEOUT => 8,
]);
$body = curl_exec($ch);
$code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = curl_error($ch);
curl_close($ch);
if ($body === false || $code >= 400) {
file_put_contents($log, date('c') . " api_fail code={$code} err={$err}\n", FILE_APPEND | LOCK_EX);
http_response_code(502);
echo json_encode(['error' => 'falha na API']);
exit;
}
$payment = json_decode($body, true);
$status = $payment['status'] ?? 'unknown';
// TODO: UPDATE pedidos SET status=? WHERE mp_payment_id=? (idempotente)
file_put_contents($log, date('c') . " ok id={$id} status={$status}\n", FILE_APPEND | LOCK_EX);
http_response_code(200);
echo json_encode(['ok' => true, 'id' => $id, 'status' => $status]);
Defina o token fora do código-fonte, via ambiente do PHP-FPM ou arquivo protegido:
sudo mkdir -p /etc/php-fpm.d/env
echo 'env[MP_ACCESS_TOKEN] = APP_USR-seu-token-aqui' | sudo tee /etc/php-fpm.d/env/mp.conf
sudo systemctl restart php-fpm
Output esperado ao simular um POST local com id de teste (após o virtual host estar no ar):
{"ok":true,"id":"1234567890","status":"approved"}
Mantenha o handler idempotente: o mesmo data.id pode chegar mais de uma vez. Grave o ID processado e ignore duplicatas. Em catálogos grandes, enfileire a consulta à API e responda 200 imediatamente após validar o JSON mínimo.
Configurar Nginx, TLS e PHP-FPM no AlmaLinux 10 para notificações IPN
Notificações IPN e webhooks exigem HTTPS público estável. No AlmaLinux 10, instale a stack e libere apenas o necessário no firewalld:
sudo dnf install -y nginx php84 php84-php-fpm php84-php-curl php84-php-json php84-php-mbstring curl
sudo systemctl enable --now nginx php84-php-fpm
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reload
Exemplo de server block (ajuste caminhos do socket PHP 8.4 conforme o pacote instalado):
server {
listen 443 ssl http2;
server_name seudominio.com.br;
root /var/www/seudominio.com.br;
index index.php;
ssl_certificate /etc/letsencrypt/live/seudominio.com.br/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/seudominio.com.br/privkey.pem;
location /webhooks/ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/www.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 15s;
limit_except GET POST { deny all; }
}
access_log /var/log/nginx/mp-webhook.access.log;
error_log /var/log/nginx/mp-webhook.error.log;
}
sudo nginx -t && sudo systemctl reload nginx
sudo touch /var/log/mercadopago-webhook.log
sudo chown nginx:nginx /var/log/mercadopago-webhook.log
sudo chmod 640 /var/log/mercadopago-webhook.log
Output esperado do teste de sintaxe:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Garanta redirecionamento HTTP para HTTPS no mesmo host. Se precisar do fluxo clássico de redirecionamento, veja Como redirecionar um site http para https?. Confirme que a rota responde na internet:
curl -sS -o /dev/null -w "%{http_code}\n" -X POST \
"https://seudominio.com.br/webhooks/mercadopago.php" \
-H "Content-Type: application/json" \
-d '{"type":"payment","data":{"id":"1234567890"}}'
Códigos 200 ou 400 (id inválido na API) indicam que o PHP executou; 502/504 apontam para socket FPM, timeout ou TLS. Use ss -lntp | grep -E '443|php' para ver listeners. Em hospedagem compartilhada o caminho muda, mas a regra é a mesma: POST público, TLS válido e cURL saindo para api.mercadopago.com.
Cadastro da URL no painel e teste de pagamento aprovado
Integração de pagamentos online só fica confiável depois que a URL de produção está cadastrada e um pagamento de teste gera linha de log. No painel do Mercado Pago, abra Webhooks / Notificações e informe:
https://seudominio.com.br/webhooks/mercadopago.php
Selecione eventos de Pagamentos e, se usar checkout pro/orders, também merchant_order. Salve e dispare o teste nativo do painel, se disponível. Em paralelo, acompanhe:
sudo tail -f /var/log/nginx/mp-webhook.access.log /var/log/mercadopago-webhook.log
Output esperado no access log após o POST do Mercado Pago:
203.0.113.40 - - [10/Apr/2026:14:22:01 -0300] "POST /webhooks/mercadopago.php HTTP/2.0" 200 48 "-" "MercadoPago"
No log da aplicação, confira type, id e o status retornado pela API (approved, pending, rejected, cancelled). Atualize o pedido no banco somente com o status oficial. Para lojas em PHP puro ou frameworks, isole a lógica de domínio (estoque, e-mail, nota fiscal) depois da confirmação na API, nunca antes da resposta 200 se o processamento for pesado.
Long-tails úteis neste fluxo: webhook Mercado Pago PHP, notificação IPN AlmaLinux, validar payment API Mercado Pago, endpoint HTTPS PHP-FPM, reenvio de webhook pagamento. Documente o access token de teste separado do de produção e rotacione se vazar em log.
Quem opera vários sites no mesmo servidor deve isolar o pool PHP-FPM do webhook (usuário e socket próprios) para não misturar permissões com o front. Em ambientes AviraHost com painel, combine com boas práticas de Comparativo: Hospedagem de sites vs. VPS conforme o volume de notificações.
Problemas comuns e como resolver
Sintoma: painel do Mercado Pago mostra falha ou reenvios infinitos
Causa: o endpoint devolve 4xx/5xx, demora além do timeout ou não é alcançável (DNS, firewall, certificado inválido).
Solução: responda 200 assim que o payload mínimo for aceito; verifique curl -vI https://seudominio.com.br, certificado e regras firewalld; leia error.log do Nginx e o log do PHP-FPM com journalctl -u php84-php-fpm -e.
Sintoma: log local grava o POST, mas o pedido nunca muda de status
Causa: o script não consulta a API, o token está errado/expirado ou a atualização no banco falha por constraint/duplicidade.
Solução: confira HTTP da API no log (api_fail); teste o mesmo GET com curl -H "Authorization: Bearer TOKEN" https://api.mercadopago.com/v1/payments/ID; torne o UPDATE idempotente pela coluna do ID do pagamento.
Sintoma: funciona no notebook e falha só no AlmaLinux 10
Causa: SELinux bloqueando escrita no log, cURL sem CA bundle, socket PHP-FPM incorreto ou allow de POST ausente no virtual host.
Solução: sudo ausearch -m avc -ts recent e ajuste contexto/fcontext do diretório de log; instale ca-certificates; alinhe fastcgi_pass ao socket real em /run; confirme com POST externo, não só localhost.
Sintoma: status aprovado processado duas vezes (e-mail/estoque duplicado)
Causa: reentrega legítima do webhook sem chave de idempotência.
Solução: tabela de eventos com unique em mp_payment_id + status aplicado; ignore se já processado; mova efeitos colaterais para fila após o commit.
Perguntas frequentes sobre guia webhook Mercado Pago em PHP 8.4 no AlmaLinux 10
O que é o webhook do Mercado Pago e para que serve?
O webhook (notificações IPN/Webhooks) é um endpoint HTTPS na sua aplicação que o Mercado Pago chama quando o status de um pagamento ou pedido muda. Assim você atualiza o pedido no banco sem depender só do retorno do checkout no navegador do cliente. Isso cobre aprovações, pendências, estornos e cancelamentos mesmo se o usuário fechar a aba.
Qual URL devo cadastrar no painel do Mercado Pago?
Cadastre a URL pública HTTPS do seu script PHP, por exemplo https://seudominio.com.br/webhooks/mercadopago.php. A rota precisa responder 200 rapidamente, aceitar POST e estar acessível na internet, sem autenticação de sessão de usuário. Evite IPs residenciais instáveis e prefira domínio com certificado válido.
Como validar se a notificação do Mercado Pago é legítima?
Trate o ID recebido no POST, consulte a API oficial do Mercado Pago com seu access token para obter o pagamento ou merchant order e só então altere o status no seu sistema. Nunca confie apenas no corpo bruto sem confirmar na API e registre tentativas inválidas em log. Tokens de teste e produção não devem ser misturados no mesmo ambiente.
Por que o webhook funciona no local e falha no servidor Linux?
Em produção costumam faltar HTTPS válido, liberação de POST no firewall/Nginx, permissão de escrita nos logs ou PHP-FPM com allow_url_fopen/cURL desabilitados. Confira o virtual host, o certificado TLS e os logs de acesso e erro do Nginx e do PHP-FPM. No AlmaLinux 10, revise também SELinux e o socket do pool PHP 8.4.
Preciso responder qual código HTTP ao Mercado Pago?
Responda HTTP 200 assim que validar o payload mínimo e enfileirar ou processar a consulta à API. Códigos 4xx/5xx ou timeouts longos fazem o Mercado Pago reenviar a notificação; evite processamentos pesados síncronos antes da resposta. Use filas ou jobs curtos para e-mail, ERP e estoque.
Conclusão
- Publique o endpoint PHP 8.4 em HTTPS no AlmaLinux 10, com log e resposta 200 rápida.
- Sempre revalide o pagamento na API do Mercado Pago com access token antes de alterar o pedido.
- Monitore access/error logs e torne o processamento idempotente contra reenvios.
Leia também
- Otimizar cache Redis para aplicações PHP no Ubuntu 22.04
- Otimizar PHP 8.3 no Debian 12: OPcache, JIT e pool FPM
- Configurar MariaDB 11.4 no AlmaLinux 9: do padrão ao máximo
Precisa de ajuda com webhook Mercado Pago em PHP?
Um ambiente com PHP atualizado, TLS e rede estável reduz falhas de notificação e retrabalho em produção. Se preferir infraestrutura pronta para aplicações PHP e lojas com checkout integrado, avalie um plano adequado ao seu tráfego.