# Connect to a reader Connect your application to a Stripe Terminal reader. > If you haven’t chosen a reader yet, compare the available [Terminal readers](https://docs.stripe.com/terminal/payments/setup-reader.md) and choose one that best suits your needs. # Tap to Pay on iPhone Tap to Pay on iPhone lets users accept in-person contactless payments with a [compatible iPhone](https://docs.stripe.com/terminal/payments/setup-reader/tap-to-pay.md?platform=ios#supported-devices) and the [Stripe Terminal SDK](https://docs.stripe.com/terminal/payments/setup-integration.md?terminal-sdk-platform=ios). Tap to Pay on iPhone supports Visa, Mastercard, American Express, and Discover contactless cards and NFC-based mobile wallets (Apple Pay, Google Pay, and Samsung Pay). Tap to Pay on iPhone is included in the Terminal iOS SDK and enables payments directly in your iOS mobile app. ## Discover readers - [discoverReaders (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)discoverReaders:delegate:completion:) - [TapToPayDiscoveryConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Reader%20Discovery%20%26%20Connection.html#/c:objc\(cs\)SCPTapToPayDiscoveryConfiguration) Use the [discoverReaders](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)discoverReaders:delegate:completion:) method to determine whether your iPhone is supported for Tap to Pay. The `completion` handler invokes with an error if your application runs on a device that doesn’t meet the [supported device criteria](https://docs.stripe.com/terminal/payments/setup-reader/tap-to-pay.md?platform=ios#supported-devices). #### Swift ```swift import StripeTerminal class DiscoverReadersViewController: UIViewController, DiscoveryDelegate { var discoverCancelable: Cancelable? // ... // Action for a "Discover Readers" button func discoverReadersAction() throws { let config = try TapToPayDiscoveryConfigurationBuilder().build() // In addition to Terminal's completion block methods, Swift async alternatives are available. // See our Example app for usage examples: https://github.com/stripe/stripe-terminal-ios/tree/master/Example self.discoverCancelable = Terminal.shared.discoverReaders(config, delegate: self) { error in if let error = error { print("discoverReaders failed: \(error)") } else { print("discoverReaders succeeded") } } } // ... // MARK: DiscoveryDelegate func terminal(_ terminal: Terminal, didUpdateDiscoveredReaders readers: [Reader]) { // In your app, display the ability to use your phone as a reader // Call `connectReader` to initiate a session with the phone } } ``` ## Connect to a reader > In version `5.1.0` of the iOS SDK, you can use the `easyConnect` method to combine reader discovery and connection into a single API call to simplify integration. See the [SDK migration guide](https://docs.stripe.com/terminal/references/sdk-migration-guide.md#update-your-reader-connection-usage-ios) for details. - [connectReader (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)connectReader:connectionConfig:completion:) - [TapToPayConnectionConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTapToPayConnectionConfiguration.html) To begin accepting Tap to Pay on iPhone payments, provide the discovered reader to the `connectReader` method. You also need to [create a delegate](https://docs.stripe.com/terminal/payments/connect-reader.md#device-setup) to handle potential required updates to the reader. Tap to Pay readers don’t need to be registered in the Dashboard or API ahead of time. Instead, you associate your reader with a [location](https://docs.stripe.com/api/terminal/locations.md) at connection time. To do so, create and use a `SCPTapToPayConnectionConfiguration` with the `locationId` set to the relevant location ID when connecting. Set the `display_name` to represent the name of the business when creating a location. Your customer sees the location’s `display_name` on the device’s tap screen unless you explicitly provide the name of a business when you connect to a reader. You can edit existing locations as necessary to adjust this text. If you use [destination charges with on_behalf_of](https://docs.stripe.com/terminal/features/connect.md#destination-payment-intents), you must also provide the connected account ID in `SCPTapToPayConnectionConfiguration`. #### Swift ```swift // Call `connectReader` with the selected reader and a connection config // to register to a location as set by your app. let connectionConfig = try TapToPayConnectionConfigurationBuilder.init(locationId: ""{{LOCATION_ID}}"") .delegate(yourTapToPayReaderDelegate) .build() Terminal.shared.connectReader(selectedReader, connectionConfig: connectionConfig) { reader, error in if let reader = reader { print("Successfully connected to reader: \(reader)") } else if let error = error { print("connectReader failed: \(error)") } } ``` ### Handle device setup When connecting to a compatible Tap to Pay on iPhone reader, a configuration update might be required and can take up to a few minutes. We recommend connecting to the reader ahead of time in the background to reduce wait time for businesses. Make sure your application implements `SCPTapToPayReaderDelegate` to handle the configuration steps and display messaging to your business to stand by. You’ll see the configuration steps as a software update so you can display progress to your businesses as appropriate. #### Swift ```swift class APPReaderViewController: TapToPayReaderDelegate { // MARK: TapToPayReaderDelegate // ... func tapToPayReader(_ reader: Reader, didStartInstallingUpdate update: ReaderSoftwareUpdate, cancelable: Cancelable?) { // In your app, let the user know that an update is being installed on the reader } func tapToPayReader(_ reader: Reader, didReportReaderSoftwareUpdateProgress progress: Float) { // The update or configuration process has reached the specified progress (0.0 to 1.0) // If you are displaying a progress bar or percentage, this can be updated here } func tapToPayReader(_ reader: Reader, didFinishInstallingUpdate update: ReaderSoftwareUpdate?, error: Error?) { // The reader has finished installing an update // If `error` is nil, it is safe to proceed and start collecting payments // Otherwise, check the value of `error` for more information on what went wrong } func tapToPayReader(_ reader: Reader, didRequestReaderDisplayMesage displayMessage: ReaderDisplayMessage) { // This is called to request that a prompt be displayed in your app. // Use Terminal.stringFromReaderDisplayMessage(:) to get a user-facing string for the prompt } func tapToPayReader(_ reader: Reader, didRequestReaderInput inputOptions: ReaderInputOptions = []) { // This is called when the reader begins waiting for input // Use Terminal.stringFromReaderInputOptions(:) to get a user-facing string for the input options } // ... } ``` ### Account linking and Apple terms and conditions All users must accept Apple’s Tap to Pay on iPhone Terms and Conditions before accepting payment for the first time. For Connect users, each connected account must individually accept the Terms and Conditions when: - A Connect user creates direct charges - A Connect user creates a destination charge and specifies an `on_behalf_of` account - [isTapToPayAccountLinked (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)isTapToPayAccountLinked:completion:) To check if an account has already accepted Apple’s Tap to Pay on iPhone Terms and Conditions, users can use `isTapToPayAccountLinked` in their integration. Users can accept Apple’s Tap to Pay on iPhone Terms and Conditions on the web before connecting to the reader for the first time using [onboarding links](https://docs.stripe.com/api/terminal/onboarding-link.md). Alternatively, users will be presented with Apple’s Tap to Pay on iPhone Terms and Conditions the first time they connect to the reader within a mobile application. To accept Apple’s Terms and Conditions, the user must provide a valid Apple ID representing the business. After users accept Apple’s Tap to Pay on iPhone Terms and Conditions, they aren’t prompted again on subsequent connections using the same Stripe account, including on other mobile devices. ![Three-step process showing Apple ID sign in, terms acceptance, and success confirmation for Tap to Pay on iPhone](https://b.stripecdn.com/docs-statics-srv/assets/ttpoi-account-linking-steps.56bc5c0bb037a98f788a7e8d43d0c87e.png) Link your Apple ID account to accept Tap to Pay payments Any iPhone can use up to 3 unique Stripe accounts across apps within a rolling 24-hour period when calling `connectReader` for Tap to Pay on iPhone. If additional accounts are used for the device within the same 24-hour period, the `connectReader` method raises an [SCPErrorTapToPayReaderMerchantBlocked](https://stripe.dev/stripe-terminal-ios/docs/Enums/SCPError.html#/c:@E@SCPError@SCPErrorTapToPayReaderMerchantBlocked) error. Learn more about account linking in the Tap to Pay on iPhone Business Information section of the [Apple Tap to Pay on iPhone FAQ](https://register.apple.com/tap-to-pay-on-iphone/faq.html). ## Handle disconnects Your reader disconnects when your application enters the background or when your iPhone loses connectivity. There are two ways you can handle this: - [TapToPayReaderDelegate (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPTapToPayReaderDelegate.html) #### Handle the disconnect manually Your application must implement the [SCPTapToPayReaderDelegate reader:didDisconnect:](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPReaderDelegate.html#/c:objc\(pl\)SCPReaderDelegate\(im\)reader:didDisconnect:) delegate method to handle this disconnection. You can use this callback as an opportunity to notify your users that something went wrong and that you need internet connectivity to continue. Additionally, you can manually reconnect to the reader when your application re-enters the foreground. #### Swift ```swift import StripeTerminal class ReaderViewController: UIViewController, TapToPayReaderDelegate { override func viewDidLoad() { super.viewDidLoad() // Set the reader delegate when connecting to a reader } // ... func reader(_ reader: Reader, didDisconnect reason: DisconnectReason) { // Consider displaying a UI to notify the user and start rediscovering readers } } ``` #### Automatically attempt reconnection Implement the auto reconnect methods in the `SCPTapToPayReaderDelegate`. You must then pass the `SCPTapToPayReaderDelegate` to your `SCPTapToPayConnectionConfiguration`. #### Swift ```swift let connectionConfig = try TapToPayConnectionConfigurationBuilder(locationId: locationId) .delegate(yourTapToPayReaderDelegate) .build() Terminal.shared.connectReader( reader, connectionConfig: connectionConfig, completion: connectCompletion ) ``` If you automatically attempt reconnection, the following occurs: 1. When a disconnect occurs, the SDK automatically attempts to reconnect and notifies you through `onReaderReconnectStarted`. Make sure your app announces that the connection was lost and a reconnection is in progress. - You can use the `Cancelable` object to stop the reconnection attempt at any time. 1. If the SDK successfully reconnects to the reader, Stripe notifies you through `onReaderReconnectSucceeded`. Make sure your app announces that the connection was restored and to continue normal operations. 1. If the SDK can’t reconnect to the reader, Stripe notifies you through both `onReaderReconnectFailed` and `reader:didDisconnect:`. Make sure your app announces that an unexpected disconnect occurred. #### Swift ```swift import StripeTerminal extension ReaderViewController: TapToPayReaderDelegate { // MARK: ReconnectionDelegate func reader(_ reader: Reader, didStartReaderReconnect cancelable: Cancelable) { // 1. Notified at the start of a reconnection attempt // Use cancelable to stop reconnection at any time } func readerDidSucceedReaderReconnect(_ reader: Reader) { // 2. Notified when reader reconnection succeeds // App is now connected } func readerDidFailReaderReconnect(_ reader: Reader) { // 3. Notified when reader reconnection fails // App is now disconnected } } ``` ## Next steps You’ve connected your application to the reader. Next, [collect your first Stripe Terminal payment](https://docs.stripe.com/terminal/payments/collect-card-payment.md). The BBPOS and Chipper™ name and logo are trademarks or registered trademarks of BBPOS Limited in the United States or other countries. The Verifone® name and logo are either trademarks or registered trademarks of Verifone in the United States and/or other countries. Use of the trademarks doesn’t imply any endorsement by BBPOS or Verifone.