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:
Depois cole o .PUBLICO.js no fim do checkout6-custom.js.
Ordem no checkout6-custom.js¶
- Validador de e-mail (
trecho-para-checkout.PUBLICO.js) - Blocklist de CPF (
trecho-cpf-checkout.PUBLICO.js) - 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.