Stripe | Financial Infrastructure to Grow Your Revenue

Stripe | Financial Infrastructure to Grow Your Revenue

4466 articles

Card payments without bank authentication


Card payments without bank authentication

Build a simpler mobile integration with regional limitations.

This integration supports businesses accepting only US and Canadian cards. It’s simpler to build, but doesn’t scale to support a global customer base.

How this integration works

How it compares to the global integration

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.

Install the Stripe iOS SDK Client-side

First, you need a Stripe account. Register now.

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

Securely collect card information on the client with 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.

Create an instance of the card component and a Pay button with the following code:

CheckoutViewController.swift

Select a language

Swift

Objective-C

No results

import UIKit
import StripePaymentsUI

class CheckoutViewController: UIViewController {

 lazy var cardTextField: STPPaymentCardTextField = {
 let cardTextField = STPPaymentCardTextField()
 return cardTextField
 }()
 lazy var payButton: UIButton = {
 let button = UIButton(type: .custom)
 button.layer.cornerRadius = 5
 button.backgroundColor = .systemBlue
 button.titleLabel?.font = UIFont.systemFont(ofSize: 22)
 button.setTitle("Pay", for: .normal)
 button.addTarget(self, action: #selector(pay), for: .touchUpInside)
 return button
 }()

 override func viewDidLoad() {
 super.viewDidLoad()
 view.backgroundColor = .white
 let stackView = UIStackView(arrangedSubviews: [cardTextField, payButton])
 stackView.axis = .vertical
 stackView.spacing = 20
 stackView.translatesAutoresizingMaskIntoConstraints = false
 view.addSubview(stackView)
 NSLayoutConstraint.activate([
 stackView.leftAnchor.constraint(equalToSystemSpacingAfter: view.leftAnchor, multiplier: 2),
 view.rightAnchor.constraint(equalToSystemSpacingAfter: stackView.rightAnchor, multiplier: 2),
 stackView.topAnchor.constraint(equalToSystemSpacingBelow: view.safeAreaLayoutGuide.topAnchor, multiplier: 2),
 ])
 }

 @objc
 func pay() {
 // ...
 }
}

Run your app and make sure your checkout page shows the card component. When the customer taps Pay, call createPaymentMethod to collect the card details and create a PaymentMethod. Send the ID of the PaymentMethod to your server.

CheckoutViewController.swift

Select a language

Swift

Objective-C

No results

func pay() {
 // Create a PaymentMethod with the card text field's card details
 STPAPIClient.shared.createPaymentMethod(with: cardTextField.paymentMethodParams) { (paymentMethod, error) in
 guard let paymentMethod = paymentMethod else {
 // Display the error to the customer
 return
 }
 let paymentMethodID = paymentMethod.stripeId
 // Send paymentMethodID to your server for the next step
 }
}

Make a payment Server-side

Set up an endpoint on your server to receive the request from the client. Use the official libraries for access to the Stripe API from your server:

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'

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.

Create an HTTP endpoint to respond to the request from step 2. 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 2 with the following parameters:

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.

Command Line

Select a language

curl

Ruby

Python

PHP

Node.js

Java

Go

.NET

No results

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.

Test the integration

There are several test cards you can use in a testing environment to make sure this integration is ready. Use them with any CVC, postal code, and future expiration date.

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

See the full list of test cards.

Upgrade your integration to handle card authentication

At this point, the payments integration for basic card payments is complete. This integration declines cards that require authentication during payment.

If you start seeing payments in the Dashboard listed as Failed, you need to upgrade your integration. The Stripe global integration handles these payments instead of automatically declining them.

Last verified 2026-09-24

Is this helpful?