feat: PIX codes expire after 30 minutes, with a countdown
All checks were successful
Build and deploy / Validate source (push) Successful in 11s
Build and deploy / Integration suite on a real stack (push) Successful in 2m50s
Build and deploy / Secret scan and release gate (push) Successful in 8s
Build and deploy / Publish images (push) Successful in 1m54s
All checks were successful
Build and deploy / Validate source (push) Successful in 11s
Build and deploy / Integration suite on a real stack (push) Successful in 2m50s
Build and deploy / Secret scan and release gate (push) Successful in 8s
Build and deploy / Publish images (push) Successful in 1m54s
A PIX is created with a 30-minute date_of_expiration, and the PIX page counts down to it. When it runs out the page says the code expired and offers a new one. The API keeps one open code per quote: the same code until it expires, then exactly one new attempt (serialised per quote, with its own idempotency key), the old one marked expired. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
const naPagina = () => ['pagamento','pix'].includes(document.documentElement.dataset.rota);
|
||||
const naPix = () => document.documentElement.dataset.rota === 'pix';
|
||||
let shownCart = null;
|
||||
let pixClock = null;
|
||||
let busy = false;
|
||||
let draftId = localStorage.getItem('dtf-quote');
|
||||
let requestKey = localStorage.getItem('dtf-request-key');
|
||||
@@ -162,6 +163,7 @@
|
||||
if(version!==refreshVersion || draftId!==shownId) return;
|
||||
if (!naPagina()) { message(''); vaiPara(PAGAMENTO); return; }
|
||||
shownCart=cartSnapshot();
|
||||
clearInterval(pixClock);
|
||||
unmountCard();
|
||||
actions.replaceChildren();
|
||||
message('');
|
||||
@@ -319,9 +321,26 @@
|
||||
try{ await navigator.clipboard.writeText(intent.pix_qr_code); copiar.textContent='Código copiado'; }
|
||||
catch(_){ code.select(); }
|
||||
},linha);
|
||||
box.append(linha,node('p','Aguardando a confirmação do pagamento…','aguarda'));
|
||||
const prazo=node('p',null,'prazo');
|
||||
box.append(linha,prazo,node('p','Aguardando a confirmação do pagamento…','aguarda'));
|
||||
actions.append(box);
|
||||
waitForOrder();
|
||||
// The code stops working when it expires; a new one is a click away.
|
||||
const fim=Date.parse(intent.expires_at);
|
||||
if (!Number.isFinite(fim)) { prazo.remove(); return; }
|
||||
const tick=()=>{
|
||||
const s=Math.max(0,Math.ceil((fim-Date.now())/1000));
|
||||
prazo.textContent='Pague em '+String(Math.floor(s/60)).padStart(2,'0')+':'+String(s%60).padStart(2,'0');
|
||||
if (s>0) return;
|
||||
clearInterval(pixClock);
|
||||
const fimBox=node('div',null,'pixBox');
|
||||
fimBox.append(node('h4','O código PIX expirou'),
|
||||
node('p','Gere um novo código para pagar. O anterior não pode mais ser pago.','pagNota'));
|
||||
button('Gerar novo PIX',()=>refresh(),fimBox);
|
||||
actions.replaceChildren(fimBox);
|
||||
};
|
||||
tick();
|
||||
pixClock=setInterval(tick,1000);
|
||||
}
|
||||
|
||||
// Card: Mercado Pago's own form (Card Payment Brick). The card is typed into
|
||||
@@ -399,7 +418,7 @@
|
||||
// The cart page keeps only the sending progress and errors, never a payment.
|
||||
window.addEventListener('dtf-page-changed',()=>{
|
||||
if (naPagina()) refresh();
|
||||
else if (!busy) { refreshVersion++; message(''); actions.replaceChildren(); pintaResumo(null); }
|
||||
else if (!busy) { refreshVersion++; clearInterval(pixClock); message(''); actions.replaceChildren(); pintaResumo(null); }
|
||||
});
|
||||
refresh();
|
||||
})();
|
||||
|
||||
@@ -254,6 +254,7 @@ html:is([data-rota="pagamento"],[data-rota="pix"]) .pagGrid{display:grid;grid-te
|
||||
.pixBox .codigo{display:flex;gap:10px;width:100%}
|
||||
.pixBox .codigo input{flex:1;min-width:0;font-size:13px}
|
||||
.pixBox .aguarda{font-size:14px;color:var(--texto2)}
|
||||
.pixBox .prazo{font-family:"Inter",sans-serif;font-weight:800;font-size:18px;font-variant-numeric:tabular-nums}
|
||||
.confirmado{border:1px solid #BFE6CE;background:var(--verde-fundo);border-radius:16px;padding:24px}
|
||||
.confirmado h4{font-size:22px;color:#14532D;margin-bottom:8px}
|
||||
.confirmado p{font-size:15px;color:#14532D;margin-bottom:18px;line-height:1.5}
|
||||
|
||||
Reference in New Issue
Block a user