Sign in
An image of the Stripe logo
Create account
Sign in
Home
Payments
Business operations
Financial services
Developer tools
No-code
All products
Home
Payments
Business operations
Home
Payments
Business operations
Financial services
Developer tools
Support
Overview
Online payments
Products and prices
Invoicing
Subscriptions
Quotes
In-person payments
Multiparty payments
After the payment
Add payment methods
Payment Links
Stripe Checkout
Stripe Elements
About the APIs
    API tour
    Payment Intents
      How intents work
      Payment status updates
      Asynchronous Capture
      Compare to Charges
    Setup Intents
    Payment methods
    Older APIs
Regulation support
Implementation guides
Testing
HomePaymentsPayment Intents

Payment status updates

Monitor and verify payment status, so that you can respond to successful and failing payments.

PaymentIntents update in response to actions taken by the customer or payment method. Your integration can inspect the PaymentIntent to determine the status of the payment process, so that you can take business actions or respond to states that require further intervention.

You can also use the Stripe Dashboard to configure your account to email you about payment status, like when you successfully receive payments. Change your email notifications in your user settings.

Check PaymentIntent status on the client

When completing a payment on the client with the confirmCardPayment function, you can inspect the returned PaymentIntent to determine its current status:

(async () => { const {paymentIntent, error} = await stripe.confirmCardPayment(clientSecret); if (error) { // Handle error here } else if (paymentIntent && paymentIntent.status === 'succeeded') { // Handle successful payment here } })();

The following are the possible outcomes of using the confirmCardPayment function:

EventWhat HappenedExpected Integration
Resolves with a PaymentIntentCustomer completed payment on your checkout pageInform customer that their payment succeeded
Resolves with an errorCustomer’s payment failed on your checkout pageDisplay error message and prompt your customer to attempt payment again

The promise returned by confirmCardPayment resolves when the payment process has either completed or failed with an error. When it completes successfully and returns a PaymentIntent, the status is always succeeded (or requires_capture if capturing later). When the payment requires an additional step like authentication, the promise doesn’t resolve until that step is either complete or has timed out.

Check PaymentIntent status on the client without using confirmCardPayment

To check the status of a PaymentIntent without using the confirmCardPayment function, retrieve it independently by using the retrievePaymentIntent function and passing in the client secret.

The following are some possible statuses of the PaymentIntent following a confirmation:

What HappenedExpected PaymentIntent Status
Customer completed payment on your checkout pagesucceeded
Customer did not complete the checkoutrequires_action
Customer’s payment failed on your checkout pagerequires_payment_method

Read more about the payment statuses.

(async () => { const {paymentIntent} = await stripe.retrievePaymentIntent(clientSecret); if (paymentIntent && paymentIntent.status === 'succeeded') { // Handle successful payment here } else { // Handle unsuccessful, processing, or canceled payments and API errors here } })();

Monitor a PaymentIntent with webhooks

Stripe can send webhook events to your server to notify you when the status of a PaymentIntent changes. This is useful for purposes like determining when to fulfill the goods and services purchased by the customer.

Your integration shouldn’t attempt to handle order fulfillment on the client side because it is possible for customers to leave the page after payment is complete but before the fulfillment process initiates. Instead, use webhooks to monitor the payment_intent.succeeded event and handle its completion asynchronously instead of attempting to initiate fulfillment on the client side.

It is technically possible to use polling instead of webhooks to monitor for changes caused by asynchronous operations—repeatedly retrieving a PaymentIntent so that you can check its status—but this is markedly less reliable and may pose challenges if used at scale. Stripe enforces rate limiting on API requests, so exercise caution if you decide to use polling.

To handle a webhook event, create a route on your server and configure a corresponding webhook endpoint in the Dashboard. Stripe sends the payment_intent.succeeded event when payment is successful and the payment_intent.payment_failed event when payment isn’t successful.

The webhook payload includes the PaymentIntent object. The following example shows how to handle both events:

require 'sinatra' require 'stripe' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload status 400 return rescue Stripe::SignatureVerificationError => e # Invalid signature status 400 return end case event['type'] when 'payment_intent.succeeded' intent = event['data']['object'] puts "Succeeded:", intent['id'] # Fulfill the customer's purchase when 'payment_intent.payment_failed' intent = event['data']['object'] error_message = intent['last_payment_error'] && intent['last_payment_error']['message'] puts "Failed:", intent['id'], error_message # Notify the customer that payment failed end status 200 end

When payment is unsuccessful, you can find more details by inspecting the PaymentIntent’s last_payment_error property. You can notify the customer that their payment didn’t complete and encourage them to try again with a different payment method. Reuse the same PaymentIntent to continue tracking the customer’s purchase.

Handling specific webhook events

The following list describes how to handle webhook events:

EventDescriptionNext steps
processingThe customer’s payment was submitted to Stripe successfully. Only applicable to payment methods with delayed success confirmation.Wait for the initiated payment to succeed or fail.
succeededCustomer’s payment succeededFulfill the goods or services purchased by the customer
amount_capturable_updatedCustomer’s payment is authorized and ready for captureCapture the funds that are available for payment
payment_failedCustomer’s payment was declined by card network or otherwise expiredReach out to your customer through email or push notification and prompt them to provide another payment method

To test webhooks locally, you can use Stripe CLI. After you install it, you can forward events to your server:

Command Line
stripe listen --forward-to localhost:4242/webhook Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)

Learn more about setting up webhooks.

Identifying charges on a PaymentIntent

When you attempt to collect payment from a customer, the PaymentIntent creates a Charge. You can inspect the PaymentIntent’s latest_charge property to obtain the id of the latest charge:

# Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
intent = Stripe::PaymentIntent.retrieve('{{PAYMENT_INTENT_ID}}') latest_charge = intent.latest_charge

Users on API version 2022-08-01 or older:

When you attempt to collect payment from a customer, the PaymentIntent creates a Charge. You can inspect the PaymentIntent’s charges.data property to obtain the latest charge:

# Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
intent = Stripe::PaymentIntent.retrieve('{{PAYMENT_INTENT_ID}}') charges = intent.charges.data

A PaymentIntent’s Charge property only contains the most recent charge. To view all of the charges associated with a PaymentIntent, list all charges with the payment_intent​ parameter specified. Note that in addition to the final successful charge, the list includes any unsuccessful charges created during the payment process.

Handling next actions

Some payment methods require additional steps, such as authentication, in order to complete the payment process. Stripe.js handles these automatically when confirming the PaymentIntent, but if you have an advanced integration, you might want to handle these manually.

The PaymentIntent’s next_action property exposes the next step that your integration must handle in order to complete the payment. The type of possible next actions can differ between various payment methods. You can find a full list of possible next actions in the API documentation.

You can refer to the payment methods documentation for more details about how to handle their required next actions.

Was this page helpful?
Questions? Contact us.
Watch our developer tutorials.
Check out our product changelog.
Powered by Markdoc
You can unsubscribe at any time. Read our privacy policy.
On this page
Check PaymentIntent status on the client
Check PaymentIntent status on the client without using confirmCardPayment
Monitor a PaymentIntent with webhooks
Identifying charges on a PaymentIntent
Handling next actions
Stripe Shell
Test mode
Welcome to the Stripe Shell! Stripe Shell is a browser-based shell with the Stripe CLI pre-installed. Login to your Stripe account and press Control + Backtick on your keyboard to start managing your Stripe resources in test mode. - View supported Stripe commands: - Find webhook events: - Listen for webhook events: - Call Stripe APIs: stripe [api resource] [operation] (e.g. )
The Stripe Shell is best experienced on desktop.
$