fix: show why a card payment failed instead of leaving the form spinning
All checks were successful
Build and deploy / Validate source (push) Successful in 7s
Build and deploy / Integration suite on a real stack (push) Successful in 3m0s
Build and deploy / Secret scan and release gate (push) Successful in 6s
Build and deploy / Publish images (push) Successful in 56s

When creating the card payment failed, the form's onSubmit rejected with no
message and Mercado Pago's button kept spinning. The page now shows the
reason above the form. A payment Mercado Pago refuses is logged with its
status, message and cause codes (payment_intent_refused) and answered 422
with that reason; other failures log their type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cauê Faleiros
2026-09-29 11:58:56 -03:00
parent 8bc57195e8
commit 4437232d27
2 changed files with 35 additions and 6 deletions

View File

@@ -415,10 +415,18 @@
onSubmit:async data=>{
if (!cartOk()) { await refresh(); throw new Error('cart changed'); }
message('');
const result=await api('/payments/intent',{quote_id:draftId,method:{
type:'card', token:data.token, payment_method_id:data.payment_method_id,
installments:Number(data.installments)||1,
issuer_id:data.issuer_id==null?null:String(data.issuer_id)}});
let result;
try {
result=await api('/payments/intent',{quote_id:draftId,method:{
type:'card', token:data.token, payment_method_id:data.payment_method_id,
installments:Number(data.installments)||1,
issuer_id:data.issuer_id==null?null:String(data.issuer_id)}});
} catch(error) {
// Rejecting stops the form's spinner; the reason is shown above it.
message(error.message || 'Não foi possível concluir o pagamento. Tente de novo.');
status.scrollIntoView({behavior:'smooth',block:'center'});
throw error;
}
if (result.challenge) { showChallenge(result.challenge, into); waitForOrder(); return; }
if (result.status==='approved' || result.status==='pending') {
unmountCard();