# Set up your integration Set up a Stripe Terminal SDK or server-driven integration to accept in-person payments. # iOS If you’re looking for a more detailed reference with all available methods, objects, and errors, consult our [full SDK reference](https://stripe.dev/stripe-terminal-ios). Getting started with the iOS SDK requires four steps: 1. [Install the SDK](https://docs.stripe.com/terminal/payments/setup-integration.md#install) in your app. 2. [Configure](https://docs.stripe.com/terminal/payments/setup-integration.md#configure) your app. 3. [Set up the connection token endpoint](https://docs.stripe.com/terminal/payments/setup-integration.md#connection-token) in your app and back end. 4. [Initialise the SDK](https://docs.stripe.com/terminal/payments/setup-integration.md#initialize) in your app. ## Install the SDK [Client-side] The Stripe Terminal iOS SDK is compatible with apps that: - Support iOS 13 and above - Are installed with CocoaPods, Swift Package Manager, or by manually integrating the framework #### Cocoapods 1. If you haven’t already done so, install a recent version of [CocoaPods](https://guides.cocoapods.org/using/getting-started.html). 2. If you don’t have an existing [Podfile](https://guides.cocoapods.org/syntax/podfile.html), run the following command to create one: ```bash pod init ``` 3. Add this line to your Podfile: ```podfile pod 'StripeTerminal', '~> 5.0' ``` 4. Run the following command: ```bash pod install ``` 5. From now on, use the `.xcworkspace` file to open your project in Xcode, instead of the `.xcodeproj` file. #### Swift Package Manager 1. In Xcode, select **File** > **Add Packages…** from the menu bar 2. Enter the Stripe Terminal iOS SDK’s GitHub URL: `https://github.com/stripe/stripe-terminal-ios` 3. Enter the SDK version you’d like to install in your project. The default value, “Up to Next Major”, helps you keep up-to-date with security and feature updates without taking on breaking changes unexpectedly. #### Manual 1. Visit the Stripe Terminal iOS repository on GitHub and go to the [latest release](https://github.com/stripe/stripe-terminal-ios/releases). 2. Download the `StripeTerminal.xcframework.zip` file attached to the GitHub release. 3. Unzip the file, then drag and drop the XCFramework into your Xcode project. 4. If the framework’s symbols can’t be loaded, go to the “General” pane of your target and find the “Frameworks, Libraries, and Embedded Content” dropdown. Switch `StripeTerminal.xcframework` from “Don’t Embed” to “Embed and Sign”. > For details on the latest SDK release and past versions, see the [Releases](https://github.com/stripe/stripe-terminal-ios/releases) page on GitHub. To receive notifications when a new release is published, [watch releases for the repository](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) or [subscribe to the GitHub Releases RSS feed](https://github.com/stripe/stripe-terminal-ios/releases.atom). > > For information on migrating from previous versions of the iOS SDK, see the [Stripe Terminal SDK Migration Guide](https://docs.stripe.com/terminal/references/sdk-migration-guide.md). ## Configure your app [Client-side] To prepare your app to work with the Stripe Terminal SDK, make a few changes to your **Info.plist** file in Xcode. 1. Enable location services with the following key-value pair. | Privacy – Location When In Use Usage Description | | ------------------------------------------------ | | **Key** | [NSLocationWhenInUseUsageDescription](https://developer.apple.com/documentation/bundleresources/information_property_list/nslocationwheninuseusagedescription) | | **Value** | **Location access is required to accept payments.** | To reduce fraud risks associated with payments, and to minimize disputes, Stripe must know where payments occur. If the SDK can’t determine the location of the iOS device, payments are disabled until location access is restored. 2. Make sure that your app runs in the background and remains connected to Bluetooth readers. | Required background modes for Bluetooth readers | | ----------------------------------------------- | | **Key** | [UIBackgroundModes](https://developer.apple.com/documentation/bundleresources/information_property_list/uibackgroundmodes) | | **Value** | **bluetooth-central** (Uses Bluetooth LE accessories) | Setting the [bluetooth-central](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html#//apple_ref/doc/uid/TP40013257-CH7-SW6) background mode lets the reader remain in standby mode when your app is running in the background, or when the iOS device is locked. Without this value, standby fails. When your app is running in the background, the reader can turn off automatically to conserve power. 3. Allow your app to display a Bluetooth permission window. The app store requires including this, even if your app doesn’t support connecting to Bluetooth readers. | Privacy - Bluetooth Always Usage Description | | -------------------------------------------- | | **Key** | [NSBluetoothAlwaysUsageDescription](https://developer.apple.com/documentation/bundleresources/information_property_list/NSBluetoothAlwaysUsageDescription) | | **Value** | **This app uses Bluetooth to connect to supported card readers.** | iOS 13 introduced more specific permissions concerning an app’s use of Bluetooth peripherals. Apps that link with Core Bluetooth must include this key in their Info.plist file to prevent the app from crashing on its first launch. 4. Pass app validation checks when you submit it to the App Store. As of SDK version 3.4.0, this permission requirement is removed. | Privacy – Bluetooth Peripheral Usage Description | | ------------------------------------------------ | | **Key** | [NSBluetoothPeripheralUsageDescription](https://developer.apple.com/documentation/bundleresources/information_property_list/nsbluetoothperipheralusagedescription) | | **Value** | **Connecting to supported card readers requires Bluetooth access.** | This is an example—you can rephrase the prompt for user permission in your app. 5. Save your app’s **Info.plist**. Now it’s configured correctly and ready for use with the Stripe Terminal SDK. > If you’re using Tap to Pay on iPhone, you must [request and configure](https://developer.apple.com/documentation/proximityreader/setting-up-the-entitlement-for-tap-to-pay-on-iphone) the Tap to Pay on iPhone development entitlement from your Apple Developer account. ## Set up the ConnectionToken endpoint [Server-side] [Client-side] ### Server-side To connect to a reader, your back end needs to give the SDK permission to use the reader with your Stripe account, by providing it with the [secret](https://docs.stripe.com/api/terminal/connection_tokens/object.md#terminal_connection_token_object-secret) from a [ConnectionToken](https://docs.stripe.com/api/terminal/connection_tokens.md). Your back end needs to only create connection tokens for clients that it trusts. #### curl ```bash curl https://api.stripe.com/v1/terminal/connection_tokens \ -u <>: \ -X "POST" ``` Obtain the secret from the `ConnectionToken` on your server and pass it to the client side. #### Ruby ```ruby post '/connection_token' do token = # ... Create or retrieve the ConnectionToken {secret: token.secret}.to_json end ``` > The `secret` from the `ConnectionToken` lets you connect to any Stripe Terminal reader and take payments with your Stripe account. Make sure you authenticate the endpoint for creating connection tokens and protect it from cross-site request forgery (CSRF). ### Client-side To give the SDK access to this endpoint, implement the [ConnectionTokenProvider](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPConnectionTokenProvider.html) protocol in your app, which defines a single function that requests a `ConnectionToken` from your back end. ```swift import StripeTerminal // Example API client class for communicating with your backend class APIClient: ConnectionTokenProvider { // For simplicity, this example class is a singleton static let shared = APIClient() // Fetches a ConnectionToken from your backend func fetchConnectionToken(_ completion: @escaping ConnectionTokenCompletionBlock) { let config = URLSessionConfiguration.default let session = URLSession(configuration: config) guard let url = URL(string: "https://{{YOUR_BACKEND_URL}}/connection_token") else { fatalError("Invalid backend URL") } var request = URLRequest(url: url) request.httpMethod = "POST" let task = session.dataTask(with: request) { (data, response, error) in if let data = data { do { // Warning: casting using `as? [String: String]` looks simpler, but isn't safe: let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] if let secret = json?["secret"] as? String { completion(secret, nil) } else { let error = NSError(domain: "com.stripe-terminal-ios.example", code: 2000, userInfo: [NSLocalizedDescriptionKey: "Missing `secret` in ConnectionToken JSON response"]) completion(nil, error) } } catch { completion(nil, error) } } else { let error = NSError(domain: "com.stripe-terminal-ios.example", code: 1000, userInfo: [NSLocalizedDescriptionKey: "No data in response from ConnectionToken endpoint"]) completion(nil, error) } } task.resume() } } ``` This function is called whenever the SDK needs to authenticate with Stripe or the Reader. It’s also called when a new connection token is needed to connect to a reader (for example, when your app disconnects from a reader). If the SDK can’t retrieve a new connection token from your backend, connecting to a reader fails with the error from your server. > Don’t cache or hardcode the connection token. The SDK manages the connection token’s lifecycle. > #### Certificate pinning > > In most cases, you shouldn’t configure your application with certificate pinning. If your application does require it, see the [certificate pinning](https://docs.stripe.com/tls-certificates.md#certificate-pinning) docs. ## Initialize the SDK [Client-side] The [Terminal](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html) class made available by the Stripe Terminal SDK exposes a generic interface for discovering readers, connecting to a reader, and performing operations on the reader, such as displaying cart details, collecting payments, and saving cards for future use. Provide the `ConnectionTokenProvider` you implemented while [setting up the connection token](https://docs.stripe.com/terminal/payments/setup-integration.md#connection-token). Call `initWithTokenProvider` only once in your app before accessing `Terminal.shared`, typically in the `AppDelegate` method `application:didFinishLaunchingWithOptions` or in the `init()` of your SwiftUI `App` type. Alternatively, use `dispatch_once` in Objective-C or a `static` initialiser in Swift. ```swift import UIKit import StripeTerminal @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { Terminal.initWithTokenProvider(APIClient.shared) // ... return true } // ... } ``` ## SDK updates Stripe periodically releases updates that can include new functionality, bug fixes, and security updates. Update your SDK as soon as a new version is available. The currently available SDKs are: - [Stripe Terminal Android SDK](https://github.com/stripe/stripe-terminal-android/releases) - [Stripe Terminal iOS SDK](https://github.com/stripe/stripe-terminal-ios/releases) - [Stripe Terminal JavaScript SDK](https://docs.stripe.com/terminal/references/api/js-sdk.md#changelog) - [Stripe Terminal React Native SDK](https://github.com/stripe/stripe-terminal-react-native) ## Next steps - [Connect to a reader](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=ios&reader-type=internet)