Migrate your basic card integration
Migrate to an integration that can handle bank requests for card authentication.
If you followed the Card payments without bank authentication guide, your integration creates payments that decline when a bank asks the customer to authenticate the purchase.
If you start seeing many failed payments like the one in the Dashboard below or with an error code of requires_
in the API, upgrade your basic integration to handle, rather than decline, these payments.
Use this guide to learn how to upgrade the integration you built in the previous guide to add server and client code that prompts the customer to authenticate the payment by displaying a modal.
Note
See a full sample of this integration on GitHub.
Check if the payment requires authenticationServer-side
Make two changes to the endpoint on your server that creates the PaymentIntent:
- Remove the error_on_requires_action parameter to no longer fail payments that require authentication. Instead, the PaymentIntent status changes to
requires_
.action - Add the
confirmation_
parameter to indicate that you want to explicitly (manually) confirm the payment again on the server after handling authentication requests.method
Then update your “generate response” function to handle the requires_
state instead of erroring:
Ask the customer to authenticateClient-side
Next, update your client-side code to tell Stripe to show a modal if the customer needs to authenticate.
Use stripe.handleCardAction when a PaymentIntent has a status of requires_
. If successful, the PaymentIntent will have a status of requires_
and you need to confirm the PaymentIntent again on your server to finish the payment.
const handleServerResponse = async (responseJson) => { if (responseJson.error) { // Show error from server on payment form } else if (responseJson.requiresAction) { // Use Stripe.js to handle the required card action const { error: errorAction, paymentIntent } = await stripe.handleCardAction(responseJson.clientSecret); if (errorAction) { // Show error from Stripe.js in payment form } else { // The card action has been handled // The PaymentIntent can be confirmed again on the server const serverResponse = await fetch('/pay', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payment_intent_id: paymentIntent.id }) }); handleServerResponse(await serverResponse.json()); } } else { // Show success message } }
Confirm the PaymentIntent againServer-side
Using the same endpoint you set up earlier, confirm the PaymentIntent again to finalize the payment and fulfill the order. The payment attempt fails and transitions back to requires_
if it is not confirmed again within one hour.
Test the integration
Use our test cards in test mode to verify that your integration was properly updated. Stripe displays a fake authentication page inside the modal in test mode that lets you simulate a successful or failed authentication attempt. In live mode the bank controls the UI of what is displayed inside the modal.
Number | Description |
---|---|
Succeeds and immediately processes the payment. | |
Always fails with a decline code of insufficient_ . | |
Requires authentication, which in this integration will fail with a decline code of authentication_ . |