iOS basic integrationDeprecated
Accept cards and Apple Pay with the iOS SDK's prebuilt UI.
Note
We created an improved payments UI for mobile apps with features such as additional payment methods and SwiftUI support. We recommend using it for your integration instead of this one.
If you want to migrate but are unable to, please let us know.
Use this integration if you want a prebuilt UI that:
- Accepts credit cards and Apple Pay
- Saves and displays cards for reuse
- Supports limited customization of fonts and colors
- Displays full-screen view controllers to collect payment details, shipping address, and shipping method:
These view controllers are also available to use individually—see the steps below for more details. This integration requires both server and client-side steps to implement.
Note
Check out the example Basic Integration app and backend for a full implementation of this guide.
Set up StripeClient-sideServer-side
First, you need a Stripe account. Register now.
Server-side
This integration requires endpoints on your server that talk to the Stripe API. Use our official libraries for access to the Stripe API from your server:
Client-side
The Stripe iOS SDK is open source, fully documented, and compatible with apps supporting iOS 13 or above.
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.
Set up an ephemeral keyClient-sideServer-side
In order for the SDK to save and retrieve credit cards for later use, create a single Stripe Customer object for each of your users. When you create a new user or account on your server, create a corresponding Customer object at the same time, even if you don’t collect payment information from your users when they sign up. This ensures that your application has a matching Customer for each user.
For security, the Customer API is not directly accessible from the client. Instead, your server provides the SDK with an ephemeral key—a short-lived API key with restricted access to the Customer API. You can think of an ephemeral key as a session, authorizing the SDK to retrieve and update a specific Customer object for the duration of the session.
Server-side
To provide an ephemeral key to the SDK, you’ll need to expose a new API endpoint on your backend. This endpoint should create an ephemeral key for the current Stripe customer, and return the key’s unmodified response as JSON. When the SDK requests an ephemeral key, it will specify the version of the Stripe API that it expects the response to come from. Your endpoint must accept an api_
parameter, and use the specified API version when creating the ephemeral key. This ensures that the SDK always receives the correct ephemeral key response from your backend. Consult our Example Backend to see this in practice.
Client-side
In your app, conform to the STPCustomerEphemeralKeyProvider protocol by implementing its createCustomerKeyWithAPIVersion method. This method requests an ephemeral key from the endpoint you created on the backend.
When implementing this method, be sure to pass the apiVersion
parameter along to your ephemeral keys endpoint. Consult the API client in our example app to see this in practice.
Set up an STPCustomerContextClient-side
Next, initialize an STPCustomerContext with the STPCustomerEphemeralKeyProvider
you created in the previous step.
A CustomerSession
talks to your backend to retrieve an ephemeral key for your Customer with its STPCustomerEphemeralKeyProvider
, and uses that key to manage retrieving and updating the Customer’s payment methods on your behalf.
To reduce load times, preload your customer’s information by initializing STPCustomerContext
before they enter your payment flow.
If your current user logs out of the app and a new user logs in, create a new instance of STPCustomerContext
or clear the cached customer using the provided clearCachedCustomer method. On your backend, create and return a new ephemeral key for the Customer object associated with the new user.
Set up an STPPaymentContextClient-side
Once you’ve set up your customer context, you can use it to initialize STPPaymentContext, the core class of the integration. Conform a class to STPPaymentContextDelegate and assign it to the payment context’s delegate
and hostViewController
properties. We recommend using your app’s checkout screen UIViewController
. In the next steps, you will implement the STPPaymentContext
delegate methods.
You should also set the payment context’s paymentAmount
property, which will be displayed to your user in the Apple Pay dialog (you can change this later, if the amount of the user’s purchase changes).
Handle the user's payment methodClient-side
In your checkout screen, add a button to let the customer enter or change their payment method. When tapped, use STPPaymentContext
to push or present an STPPaymentOptionsViewController on the payment context’s hostViewController
.
STPPaymentOptionsViewController
uses STPCustomerContext
to display a Customer’s payment methods. If there are no stored payment methods or the Add New Card button is tapped, STPAddCardViewController
is displayed. You can also initialize and display these view controllers without using STPPaymentContext
.
- paymentContextDidChange:
This STPPaymentContext delegate method triggers when the content of the payment context changes, like when the user selects a new payment method or enters shipping information. This is a good place to update your UI:
Handle the user's shipping infoClient-side
If your user needs to enter or change their shipping address and shipping method, STPPaymentContext
can do this for you automatically. STPPaymentContext
will save shipping info to the Stripe customer when your user updates their information, and automatically prefill the shipping view controller for future purchases. Note that you should not rely on the shipping information stored on the Stripe customer for order fulfillment, as your user may change this information if they make multiple purchases. We recommend adding shipping information when you create a PaymentIntent object (which can also help prevent fraud), or when saving it to your own database. When presenting the shipping view controller, you can specify whether you’d like it presented modally, or pushed onto a UINavigationController
stack:
This sets up and presents an STPShippingAddressViewController on the payment context’s hostViewController
. Once the user enters a valid shipping address, they’re taken to an STPShippingMethodsViewController. After they select a shipping method, both view controllers are dismissed or popped off the hostViewController
’s stack.
- paymentContext:didUpdateShippingAddress:completion:
This method is called after your user enters a shipping address. Validate the returned address
and determine the shipping methods available for that address.
If the address is valid, call the provided completion
block with a status of STPShippingStatusValid
, nil
for the error argument, an array of shipping methods, and a selected shipping method. If you don’t need to collect a shipping method, pass nil
for the shipping methods and selected shipping method. If the address is invalid, call the completion
block with a status of STPShippingStatusInvalid
, an error object describing the issue with the address, and nil
for the shipping methods and selected shipping method. Note that providing an error object is optional—if you omit it, the user sees an alert with the message “Invalid Shipping Address.”
Submit the paymentClient-sideServer-side
When your user is ready to pay (for example, they tap the Buy button) call requestPayment
on your payment context. It displays any required UI (such as the Apple Pay dialog) and calls the appropriate methods on its delegate as your user finishes their payment.
- paymentContext:didCreatePaymentResult:completion:
This method is called when the customer has successfully selected a payment method. Submit the payment to Stripe using a Payment Intent. Stripe uses this payment object to track and handle all the states of the payment until the payment completes.
Server-side
On your server, make an endpoint that creates a PaymentIntent
with an amount and currency and returns its client secret to your client.
Always decide how much to charge on the server side, a trusted environment, as opposed to the client. This prevents malicious customers from being able to choose their own prices.
Client-side
On the client, implement this delegate method to:
- Request a
PaymentIntent
from your server. - Assemble a STPPaymentIntentParams object with the
PaymentIntent
client secret from your server and the paymentMethod provided by the delegate method. - Call the STPPaymentHandler confirmPayment method to confirm the payment, passing the
STPPaymentContext
as the authenticationContext.
You must call the provided completion
block with the appropriate STPPaymentStatus
(.
, .
, or .userCancellation
) when the customer’s payment is finished.
- paymentContext:didFinishWithStatus:error:
This method is called after the previous method, when any auxiliary UI that has been displayed (such as the Apple Pay dialog) has been dismissed. You should inspect the returned status
and show an appropriate message to your user. For example:
- paymentContext:didFailToLoadWithError:
This method is called in the rare case that the payment context’s initial loading call fails, usually due to lack of internet connectivity. You should dismiss your checkout page when this occurs and invite the user to try again. You can also optionally attempt to try again by calling retryLoading
on the payment context.
Test the integration
Several test cards are available for you to use in test mode to make sure this integration is ready. Use them with any CVC and an expiration date in the future.
Number | Description |
---|---|
Succeeds and immediately processes the payment. | |
Requires authentication. Stripe triggers a modal asking for the customer to authenticate. | |
Always fails with a decline code of insufficient_ . |
For the full list of test cards see our guide on testing.