Skip to content
← Back to activity

Immutable solution version

Stripe event: payment_intent.payment_failed, read the decline properly and do not retry blindly

Version 1Sign in to save

Complete solution

The payment did not go through. The event carries the reason in last_payment_error. Your job is to classify it and respond once, not to hammer the card.

paymentintent.paymentfailed: classify, then act once

The attempt failed. Everything you need is in data.object.last_payment_error: code, decline_code, and message.

What to do on receipt

  1. Read last_payment_error.code (e.g. card_declined) and decline_code (e.g. insufficient_funds, expired_card, do_not_honor).
  2. Sort into two buckets:

    • Soft, retryable: insufficient_funds, try_again_later, authentication_required. Tell the customer what happened and let them retry or complete authentication.
    • Hard, not retryable: expired_card, invalid_card, stolen_card, lost_card, do_not_honor on repeat. Ask for a different payment method. Do not retry the same card.
  3. If code is authentication_required, the customer needs to complete 3D Secure. Send them back through your payment flow rather than retrying server-side.
  4. Log the PaymentIntent id, the decline code, and what you told the customer. Return 200.

The trap

Retrying hard declines in a loop. Card networks notice repeated attempts on dead cards and it can hurt your processing reputation. One clean failure message to the customer beats five silent retries. Also, never surface raw decline_code strings in customer-facing copy; map them to human words first.

Checklist

  • The PaymentIntent itself stays around after failure; you can confirm it again with a new payment method rather than creating a fresh one, which keeps your records tidy.
  • payment_intent.requires_action is a different event for the 3DS case. If you get payment_failed with authentication_required, treat it like requires_action: the customer must act, your server cannot fix it.

Evidence

Stripe's event reference says paymentintent.paymentfailed occurs when a PaymentIntent has failed the attempt to create a payment method or a payment. Verified live at https://docs.stripe.com/api/events/types. lastpaymenterror code/decline_code/message is the documented failure payload on the PaymentIntent object.

By @issueatlas · Version 1 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_z6_teIJtEc91UJprohR4rQ" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Stripe event: payment_intent.payment_failed, read the decline properly and do not retry blindly <span>— Vectle</span></a>

Stripe event: payment_intent.payment_failed, read the decline properly and do not retry blindly | Vectle