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, such as successful 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
)
{
}
else
if
(
paymentIntent
&&
paymentIntent
.
status
===
'succeeded'
)
{
}
}
)
(
)
;
The following are the possible outcomes of using the
confirmCardPayment
function:
Event
| What Happened
| Expected Integration
|
---|
Resolves with a PaymentIntent
| The customer completed payment on your checkout page
| Inform the customer that their payment succeeded
|
Resolves with an error
| The customer’s payment failed on your checkout page
| Display an 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 such as 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 Happened
| Expected PaymentIntent Status
|
---|
The customer completed payment on your checkout page
| succeeded
|
The customer didn’t complete the checkout
| requires_action
|
The customer’s payment failed on your checkout page
| requires_payment_method
|
Read more about the PaymentIntent statuses
.
(
async
(
)
=>
{
const
{
paymentIntent
}
=
await
stripe
.
retrievePaymentIntent
(
clientSecret
)
;
if
(
paymentIntent
&&
paymentIntent
.
status
===
'succeeded'
)
{
}
else
{
}
}
)
(
)
;
Monitor a PaymentIntent with webhooks
Stripe can send
webhook
events to your server to notify you when the status of a PaymentIntent changes, which you can use for purposes such as determining when to fulfill goods and services.
Don’t attempt to handle order
fulfillment
on the client side because customers can 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.
Caution
It’s 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 doing so is much less reliable and might cause rate limiiting issues. 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 a payment succeeds, and the
payment_intent.payment_failed
event when a payment fails.
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
status
400
return
rescue
Stripe
:
:
SignatureVerificationError
=
>
e
status
400
return
end
case
event
[
'type'
]
when
'payment_intent.succeeded'
intent
=
event
[
'data'
]
[
'object'
]
puts
"Succeeded:"
,
intent
[
'id'
]
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
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:
Event
| Description
| Next steps
|
---|
processing
| The 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.
|
succeeded
| The customer’s payment succeeded
| Fulfill the purchased goods or services
|
amount_capturable_updated
| The customer’s payment is authorized and ready for capture
| Capture the funds that are available for payment
|
payment_failed
| The customer’s payment was declined by a card network or otherwise expired
| Reach 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:
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
. To get the ID of the most recent charge, inspect the PaymentIntent’s
latest_charge
property:
Stripe
.
api_key
=
'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
intent
=
Stripe
:
:
PaymentIntent
.
retrieve
(
'{{PAYMENT_INTENT_ID}}'
)
latest_charge
=
intent
.
latest_charge
To view all of the charges associated with a PaymentIntent, including any unsuccessful charges,
list all charges
and specify the
payment_intent?
parameter.
curl
-G
https://api.stripe.com/v1/charges
\
-u
"
sk_test_4eC39HqLyjWDarjtT1zdp7dc
:"
\
-d
payment_intent
=
Handling next actions
Some payment methods require additional steps, such as authentication, 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 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.