Checkout & Pagamentos

Botão de pagar não funciona? Pode ser o CSP do checkout do Magento

O sintoma engana: o site todo funciona, o antifraude carrega na home, e só o checkout fica morto. Não é o gateway, é uma diferença de configuração dentro do próprio Magento.

Por Roger Takemiya · Publicado em · 5 min de leitura

O cliente escolhe o pagamento, clica em finalizar e não acontece nada. Nenhum erro na tela, nenhum pedido no admin. O suporte do gateway jura que está tudo certo do lado deles — e está mesmo.

Abra o console do navegador nessa página. Se aparecer Refused to load the script com uma menção a Content Security Policy, achou. E o motivo de isso acontecer só no checkout está escrito no core do Magento.

Por que quebra só no checkout

O módulo Magento_Csp define o padrão da loja no etc/config.xml dele: csp/mode/storefront/report_only vale 1. Report-only quer dizer que o navegador anota a violação e deixa o script rodar. Ninguém percebe nada.

Só que o Magento_Checkout tem o config.xml dele, e lá está isto:

CaminhoValorEfeito
csp/mode/storefront/report_only1loja inteira só reporta
csp/mode/storefront_checkout_index_index/report_only0checkout bloqueia de verdade
csp/policies/storefront_checkout_index_index/scripts/inline0nada de script inline no checkout

O identificador storefront_checkout_index_index é a área (storefront) somada ao handle de layout da página de checkout (checkout_index_index). É por isso que a home, a categoria e o produto funcionam com o mesmo script que morre na hora de pagar — e por isso o teste do gateway numa página qualquer não reproduz o problema.

A decisão da Adobe faz sentido, aliás: é justamente no checkout que skimmer de cartão gosta de morar. O CSP restrito ali é proteção, não implicância.

Descobrir qual host foi barrado

O navegador entrega a resposta de graça. Abra o checkout com o console aberto e procure a mensagem de recusa: ela diz a diretiva violada (script-src, connect-src, frame-src) e o endereço exato que foi bloqueado.

Anote o host e a diretiva de cada linha. Gateway brasileiro costuma precisar de três ou quatro de uma vez: o domínio do SDK, o da API, o do CDN de imagem e às vezes um de iframe.

Para pegar violação de cliente real, e não só da sua máquina, existe o campo Report URI em Stores > Configuration > Security > Content Security Policy > Mode > Storefront Default. Apontando para um endpoint seu, o navegador manda um relatório JSON a cada violação. Em loja com muito módulo de terceiro, isso vale mais que meia hora de console.

Liberando no csp_whitelist.xml

A liberação vive num arquivo etc/csp_whitelist.xml dentro de um módulo. Não é configuração de admin, é código — e isso é proposital: liberar host no CSP é decisão que precisa passar por revisão e ir para o Git.

Este é o formato, com valores reais do módulo oficial do Mercado Pago:

<?xml version="1.0"?>
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
    <policies>
        <policy id="script-src">
            <values>
                <value id="mercado-pago-sdk" type="host">*.mercadopago.com</value>
                <value id="mercado-libre-static" type="host">*.mlstatic.com</value>
            </values>
        </policy>
    </policies>
</csp_whitelist>

Repita o bloco policy para cada diretiva que o console acusou. O atributo type aceita host, hash e nonce — no dia a dia você usa host.

Depois de criar o arquivo:

php bin/magento setup:upgrade
php bin/magento cache:flush

Antes de escrever o seu, confira se o módulo do gateway já não traz um. Os bons trazem: o do Mercado Pago tem sete políticas declaradas no etc/csp_whitelist.xml dele. Se o módulo tem o arquivo e o bloqueio continua, quase sempre é versão antiga do módulo ou um host novo que o gateway passou a usar.

Perguntas rápidas

Não dá para desligar o CSP do checkout e resolver logo?

Dá, sobrescrevendo o valor num módulo seu, mas é péssima ideia. O CSP restrito no checkout é o que dificulta a vida de skimmer de cartão, que é exatamente o ataque que rouba dado de pagamento em loja Magento.

Coloquei o host e continua bloqueado. O que falta?

Quase sempre é a diretiva errada. Um SDK que carrega o script e depois chama a API do gateway precisa aparecer em script-src e em connect-src. Releia a mensagem do console: ela nomeia a diretiva violada em cada linha.

O csp_whitelist.xml precisa ficar em etc/frontend?

Não. Ele fica direto em etc/ do módulo e vale para a loja inteira. O que é por área é a configuração de modo, no config.xml.

Pra conferir na fonte

  1. Content Security Policies — Adobe Developer
  2. Magento_Checkout etc/config.xml — GitHub
  3. Magento_Csp etc/csp_whitelist.xml — GitHub
  4. Mercado Pago adb-payment etc/csp_whitelist.xml — GitHub

csp checkout gateway

Precisa de um orçamento? Ficarei feliz em ajudar. Clique Aqui