Accept a payment
STPPaymentCardTextField performs real-time validation and formatting.
This integration uses a prebuilt card form to securely collect card details and manually submit the details to Stripe to make a payment.
Stripe uses a payment object, called a PaymentIntent
, to track and handle all the states of the payment until it’s completed, including situations like two-factor authentication when the bank requires customer intervention.
Note
The steps in this guide are fully implemented on GitHub in the custom-payment-flow
directory. Clone the repo and follow the instructions to run the demo app.
Set up StripeServer-sideClient-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 the 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.
Create your checkout pageClient-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.
Create an instance of the card component and a Pay button with the following code:
Run your app, and make sure your checkout page shows the card component and pay button.
Create a PaymentIntentServer-sideClient-side
Stripe uses a PaymentIntent object to represent your intent to collect payment from a customer, tracking your charge attempts and payment state changes throughout the process.
Server-side
On your server, make an endpoint that creates a PaymentIntent with an amount and currency. 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.
Instead of passing the entire PaymentIntent object to your app, only return its client secret. The PaymentIntent’s client secret is a unique key that lets you confirm the payment and update card details on the client, without allowing manipulation of sensitive information, like payment amount.
Client-side
On the client, request a PaymentIntent from your server and store its client secret.
Submit the payment to StripeClient-side
When the customer taps the Pay button, confirm the PaymentIntent
to complete the payment.
First, assemble a STPPaymentIntentParams object with:
- The card text field’s payment method details
- The
PaymentIntent
client secret from your server
Rather than sending the entire PaymentIntent object to the client, use its client secret. This is different from your API keys that authenticate Stripe API requests. The client secret is a string that lets your app access important fields from the PaymentIntent (for example, status
) while hiding sensitive ones (for example, customer
).
The client secret should still be handled carefully because it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer.
Next, complete the payment by calling the STPPaymentHandler confirmPayment method.
If authentication is required by regulation such as Strong Customer Authentication, STPPaymentHandler
presents view controllers using the STPAuthenticationContext passed in and walks the customer through that process. See Supporting 3D Secure Authentication on iOS to learn more.
If the payment succeeds, the completion handler is called with a status of .succeeded
. If it fails, the status is .failed
and you can display the error.localizedDescription
to the user.
You can also check the status of a PaymentIntent in the Dashboard or by inspecting the status property on the object.
Test the integration
By this point you should have a basic card integration that collects card details and makes a payment.
There are several test cards you can use in test mode 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. | |
Requires authentication. Stripe will trigger a modal asking for the customer to authenticate. | |
Always fails with a decline code of insufficient_funds . |
For the full list of test cards see our guide on testing.
Handle post-payment events
Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard, a custom webhook, or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.
Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events also makes it easier to accept more payment methods in the future. Check out our guide to payment methods to see the differences between all supported payment methods.
Manually
Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments.
Custom code
Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.
Prebuilt apps
Handle common business events, like shipping and inventory management, by integrating a partner application.