Card payments without bank authentication
Build a simpler integration with regional limitations.
This integration supports businesses accepting only US and Canadian cards. It’s simpler up front, but doesn’t scale to support a global customer base.
How does this integration work?
Banks in regions like Europe and India often require two-factor authentication to confirm a purchase. If you primarily do business in the US and Canada, ignoring card authentication can simplify your integration, as banks rarely request it in these regions.
When a bank requires authentication, this basic integration immediately declines the payment (like a card decline), instead of handling authentication to complete the payment asynchronously. The benefit is that the payment succeeds or declines immediately and payment confirmation happens on the server, so you can handle immediate post-payment actions without a webhook.
How does it compare to the global integration?
Feature | This Integration | Global Integration |
---|---|---|
Custom payment form | ✔ | ✔ |
Sensitive data never touches your server | ✔ | ✔ |
Works for your US and Canada customers | ✔ | ✔ |
Declines payments with incorrect card details or no funds | ✔ | ✔ |
Declines payments with bank authentication requests | ✔ | |
Works for your global customers | ✔ | |
Automatically handles card payments that require bank authentication | ✔ | |
Webhooks recommended for post-payment tasks | ✔ | |
Easily scales to other payment methods (for example, bank debits) | ✔ |
Growing or global businesses should use Stripe’s global integration to support bank requests for two-factor authentication and allow customers to pay with more payment methods.
Build a checkout formClient-side
Elements, part of Stripe.js, provides drop-in UI components for collecting card information from customers. Stripe hosts them and places them into your payment form as an iframe so your customer’s card details never touch your code.
Set up StripeServer-side
Use an official library to make requests to the Stripe API from your application:
Make a paymentServer-side
Set up an endpoint on your server to receive the request from the client.
Stripe uses a PaymentIntent object to represent your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process.
Always decide how much to charge on the server, a trusted environment, as opposed to the client. This prevents malicious customers from being able to choose their own prices.
Create an HTTP endpoint to respond to the AJAX request from step 1. In that endpoint, you should decide how much to charge the customer. To create a payment, create a PaymentIntent using the PaymentMethod ID from step 1 with the following code:
Warning
If you set error_on_requires_action to true
when confirming a payment, Stripe automatically fails the payment if it requires two-factor authentication from the user.
Payment Intents API response
When you make a payment with the API, the response includes a status of the PaymentIntent. If the payment was successful, it will have a status of succeeded
.
{ "id": "pi_0FdpcX589O8KAxCGR6tGNyWj", "object": "payment_intent", "amount": 1099, "charges": { "object": "list", "data": [ { "id": "ch_GA9w4aF29fYajT", "object": "charge", "amount": 1099, "refunded": false, "status": "succeeded", } ] }, "client_secret": "pi_0FdpcX589O8KAxCGR6tGNyWj_secret_e00tjcVrSv2tjjufYqPNZBKZc", "currency": "usd", "last_payment_error": null, "status": "succeeded", }
If the payment is declined, the response includes the error code and error message. Here’s an example of a payment that failed because two-factor authentication was required for the card.
{ "error": { "code": "authentication_required", "decline_code": "authentication_not_handled", "doc_url": "https://docs.stripe.com/error-codes#authentication-required", "message": "This payment required an authentication action to complete, but `error_on_requires_action` was set. When you're ready, you can upgrade your integration to handle actions at https://stripe.com/docs/payments/payment-intents/upgrade-to-handle-actions.", "payment_intent": { "id": "pi_1G8JtxDpqHItWkFAnB32FhtI", "object": "payment_intent", "amount": 1099, "status": "requires_payment_method", "last_payment_error": { "code": "authentication_required", "decline_code": "authentication_not_handled", "doc_url": "https://docs.stripe.com/error-codes#authentication-required", "message": "This payment required an authentication action to complete, but `error_on_requires_action` was set. When you're ready, you can upgrade your integration to handle actions at https://stripe.com/docs/payments/payment-intents/upgrade-to-handle-actions.", "type": "card_error" }, }, "type": "card_error" } }
Test the integration
Stripe provides several test cards you can use in a sandbox to make sure this integration is ready. Use them with any CVC, postal code, and future expiration date.
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_ . |
See the full list of test cards.
Upgrade your integration to handle card authentication
Congratulations! You completed a payments integration for basic card payments. Note that this integration declines cards that require authentication during payment.
If you start seeing payments in the Dashboard listed as Failed
, then it’s time to upgrade your integration. Stripe’s global integration handles these payments instead of automatically declining them.