Stripe | Financial Infrastructure to Grow Your Revenue

Stripe | Financial Infrastructure to Grow Your Revenue

4466 articles

Save a card without bank authentication


Save a card without bank authentication

Collect card details in your mobile app and charge your customer at a later time.

​​Stripe allows you to collect card details and charge your customer at a later time. ​​In some regions, banks require a second form of authentication such as entering a code sent to a phone. ​​The extra step decreases conversion if your customer isn’t actively using your website or application because they aren’t available to authenticate the purchase.

​​If you primarily do business in the US and Canada, banks don’t require authentication, so you can follow this simpler integration. This integration will be non-compliant in countries that require authentication for saving cards (for example, India) so building this integration means that expanding to other countries or adding other payment methods will require significant changes. Learn how to save cards that require authentication.

Compliance

You’re responsible for your compliance with all applicable laws, regulations, and network rules when saving a customer’s payment details. For instance, if you want to save their payment method for future use, such as charging them when they’re not actively using your website or app. Add terms to your website or app that state how you plan to save payment method details and allow customers to opt in. If you want to charge them when they’re offline, make sure your terms include the following:

  • The customer’s agreement to your initiating a payment or a series of payments on their behalf for specified transactions.
  • The anticipated timing and frequency of payments (for example, if the charges are for scheduled installments, subscription payments, or unscheduled top-ups).
  • How you determine the payment amount.
  • Your cancellation policy, if the payment method is for a subscription service.

Make sure you keep a record of your customer’s written agreement to these terms.

Set up Stripe Server-side Client-side

First, you need a Stripe account. Register now.

Set up the iOS and server Stripe SDKs before starting your integration.

Server-side

This integration requires endpoints on your server that talk to the Stripe API. Use our official libraries:

Command Line

Select a language

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

# Available as a gem
sudo gem install stripe

Gemfile

Select a language

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

# If you use bundler, you can add this line to your Gemfile
gem 'stripe'

Client-side

The Stripe iOS SDK is open source, fully documented, and compatible with apps supporting iOS 13 or above.

To install the SDK, follow these steps:

  1. In Xcode, select File > Add Package Dependencies… and enter https://github. the relevant part of the product as the repository URL.
  2. Select the latest version number from our releases page .
  3. Add the StripePaymentsUI product to the target of your app .

Note

For details on the latest SDK release and past versions, see the Releases page on GitHub. To receive notifications when a new release is published, watch releases for the repository.

Configure the SDK with your Stripe publishable key on app start. This enables your app to make requests to the Stripe API.

AppDelegate.swift

Select a language

Swift

Objective-C

No results

import UIKit
import StripePaymentsUI

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
 StripeAPI.defaultPublishableKey = "pk_test_TYooMQauvdEDq54NiTphI7jx"
 // do any other necessary launch configuration
 return true
 }
}

Note

Use your test keys while you test and develop, and your live mode keys when you publish your app.

Collect card details Client-side

Start by displaying a payment form to your customer. Collect card details from the customer using STPPaymentCardTextField, a drop-in UI component provided by the SDK that collects the card number, expiration date, CVC, and postal code.

STPPaymentCardTextField performs on-the-fly validation and formatting.

Pass the card details to createPaymentMethod to create a PaymentMethod.

CheckoutViewController.swift

Select a language

Swift

Objective C

No results

class CheckoutViewController: UIViewController {
 lazy var cardTextField: STPPaymentCardTextField = {
 let cardTextField = STPPaymentCardTextField()
 return cardTextField
 }()

 @objc
 func pay() {
 // Collect card details on the client
 STPAPIClient.shared.createPaymentMethod(with: cardTextField.paymentMethodParams) { [weak self] paymentMethod, error in
 guard let paymentMethod = paymentMethod else {
 // Display the error to the user
 return
 }
 let paymentMethodId = paymentMethod.stripeId
 // Send paymentMethodId to your server for the next steps
 }
 }
}

Send the resulting PaymentMethod ID to your server and follow the remaining steps to save the card to a customer and charge the card in the future.

Save the card Server-side

Save the card by attaching the PaymentMethod to a Customer. You can use the Customer object to store other information about your customer, such as shipping details and email address.

Command Line

Select a language

cURL

Stripe CLI

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

If you have an existing Customer, you can attach the PaymentMethod to that object instead.

Command Line

Select a language

cURL

Stripe CLI

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

At this point, associate the ID of the Customer object and the ID of the PaymentMethod with your own internal representation of a customer, if you have one.

Charge the saved card Server-side

When you’re ready to charge the Customer, look up the PaymentMethod ID to charge. You can do this by either storing the IDs of both in your database, or by using the Customer ID to look up all the Customer’s available PaymentMethods.

Command Line

Select a language

cURL

Stripe CLI

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

Use the PaymentMethod ID and the Customer ID to create a new PaymentIntent. Set error_on_requires_action to true to decline payments that require any actions from your customer, such as two-factor authentication.

Command Line

Select a language

cURL

Stripe CLI

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

When a payment attempt fails, the request also fails with a 402 HTTP status code and Stripe throws an error. You need to notify your customer to return to your application (for example, by sending an in-app notification) to complete the payment. Check the code of the Error raised by the Stripe API library or check the last_payment_error.decline_code on the PaymentIntent to inspect why the card issuer declined the payment.

Handle any card errors

Notify your customer that the payment failed and direct them to the payment form you made in step 1 where they can enter new card details. Send that new PaymentMethod ID to your server to attach to the Customer object and make the payment again.

Alternatively, you can create a PaymentIntent and save a card in one API call if you already created a Customer.

Command Line

Select a language

cURL

Stripe CLI

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

Setting setup_future_usage to on_session indicates to Stripe that you want to save the card for later, without triggering unnecessary authentication.

Test the integration

Stripe provides test cards you can use in a sandbox to simulate the behavior of different cards. Use these cards with any CVC, postal code, and expiration date in the future.

NumberDescription
Succeeds and immediately processes the payment.
Always fails with a decline code of insufficient_funds.
Requires authentication, which in this integration declines with a code of authentication_required.

Optional Re-collect a CVC

Upgrade your integration to handle card authentication

This integration declines cards that require authentication during payment. If you start seeing many 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.

Last verified 2026-09-24

Is this helpful?