Ir para o conteúdo

Aviso de espera entre tentativas de pagamento

Popup no checkout explicando o bloqueio de intervalo da VTEX, com contagem regressiva.

No ar desde 28/08/2026 (v6)

Validado com um bloqueio real de 429 na loja.

O problema que ele resolve

A VTEX tem um parâmetro chamado minimumPurchaseDowntimeSeconds — tempo mínimo entre uma compra e outra. Na useveggi ele está em 120 segundos. Foi subido para conter o card testing: limita quantas tentativas um bot consegue disparar por minuto.

O bloqueio funciona. O problema é que ele é mudo:

POST https://www.useveggi.com.br/api/checkout/pub/orderForm/<id>/transaction
     →  429 Too Many Requests

Sem corpo, sem mensagem. O checkout-ui apenas registra start-transaction-error e mostra um erro genérico. O cliente legítimo que tentou pagar duas vezes vê a compra falhar, não entende por quê e conclui que a loja está quebrada.

O script mostra isto:

Aguarde para finalizar a compra Por que preciso aguardar? — Uma tentativa de pagamento foi realizada recentemente — Por segurança, aguarde alguns instantes antes de tentar novamente — Você poderá finalizar a sua compra em 01:44

Ao fechar o popup, fica uma etiqueta no canto da tela com a mesma contagem, para o cliente não ficar sem referência.

A regra que sustenta tudo: só o 429 cria janela

O script só acredita em bloqueio que ele viu acontecer — resposta 429 do servidor. Nada de inferir espera a partir de sinal indireto.

Essa regra não é preciosismo: cada tentativa de inferir custou um alarme falso na cara de cliente que não estava bloqueado.

Versão O que inferia errado Sintoma
v1 Gravava a janela a cada POST, inclusive nos recusados Contador reiniciava em 02:00 e nunca chegava ao fim
v3 Tratava /api/payments/ como tentativa Quem logava recebia o popup sem nunca ter tentado pagar — e insistindo, a compra passava
v4 Gravava a janela no disparo da requisição A primeira tentativa legítima do cliente acendia o próprio popup
v5 Tratava transação aceita (2xx) como espera iniciada Escolher PicPay, não pagar e voltar já trazia o aviso na tela

O preço da regra é não avisar antes do primeiro 429. O ganho é nunca mais mostrar contador para quem não está bloqueado.

O que ele nunca faz

Não intercepta clique, não chama preventDefault, não desabilita botão

A v2 do Validador de E-mail quebrou PicPay, Pix e Pagaleve exatamente assim. Aqui o script só observa e avisa. Se ele parar de funcionar, o pior que acontece é o cliente voltar a ficar sem aviso — nunca uma compra travada.

Quem bloqueia continua sendo a VTEX, no servidor.

Configuração

No topo do arquivo:

Constante Valor Observação
INTERVALO_SEGUNDOS 120 Tem que bater com o minimumPurchaseDowntimeSeconds da VTEX. Se mudar lá, mude aqui
MOSTRAR_TEMPO true false troca "em 01:44" por "em instantes"
DEBUG false true loga no console o que o script vê

Sobre mostrar o tempo

Mostrar a contagem não entrega segredo: o intervalo já é medível por quem tentar duas vezes com um cronômetro, o popup só existe no navegador (bot na API nunca renderiza a tela), e o valor está no próprio checkout6-custom.js, que é público.

Saber o número também não ajuda a burlar — o 429 continua barrando igual, no servidor. Quem perde com o número escondido é o cliente de verdade, que era o motivo do script existir.

Testar no console

Abra o checkout, F12 → Console:

veggiEspera.ver()                 // mostra o popup com a contagem cheia
veggiEspera.testarReativo()       // simula o 429 sem gastar um pedido
veggiEspera.testarNaoReinicia()   // confere que uma recusa nao reinicia a contagem
veggiEspera.faltam()              // segundos restantes
veggiEspera.limpar()              // apaga a janela gravada no navegador
veggiEspera.debug(true)           // passa a logar tudo

Colando no console para testar

Recarregue a página antes de colar uma versão nova. O script substitui fetch e XMLHttpRequest, e colar por cima empilha um patch sobre o outro — além disso o CSS antigo permanece e você jura que o visual não mudou.

Arquivos

Arquivo Papel
aviso-intervalo-checkout.js Fonte comentada — é onde se edita
aviso-intervalo-checkout.PUBLICO.js Gerado sem comentários — é o que vai para a VTEX
gerar-producao.mjs Gera as versões públicas

Nunca cole o arquivo comentado no checkout

O checkout6-custom.js é servido publicamente. Os comentários do fonte contam histórico de bugs internos, a assinatura do 429 e o raciocínio sobre o ataque.

Depois de qualquer mudança:

cd "C:\Projetos\vtex-analise"
node gerar-producao.mjs

Depois cole o .PUBLICO.js no fim do checkout6-custom.js.

Ordem no checkout6-custom.js

  1. Validador de e-mail (trecho-para-checkout.PUBLICO.js)
  2. Blocklist de CPF (trecho-cpf-checkout.PUBLICO.js)
  3. Aviso de espera (aviso-intervalo-checkout.PUBLICO.js)

Nunca duas cópias do mesmo script

Dois validadores de e-mail no arquivo significam dois interceptadores de clique rodando juntos — exatamente o tipo de coisa que derrubou o pagamento na v2.