--- title: Terminal SDK migration guide subtitle: Learn how to migrate to the latest version of the Stripe Terminal SDK. route: /terminal/references/sdk-migration-guide --- # Terminal SDK migration guide Learn how to migrate to the latest version of the Stripe Terminal SDK. The Stripe Terminal iOS and Android SDKs have been updated with a number of breaking changes in APIs and behavior, some of which require you to update your integration with the Stripe Terminal SDK. To improve consistency between our SDKs and to simplify your application logic and integration, we regularly make changes in major version updates that might affect the way your integration works or behaves. This guide explains the latest changes to help you upgrade your integration. Building a new Stripe Terminal integration? Visit our [Design an integration](https://docs.stripe.com/terminal/designing-integration.md) page to learn how to get started. ## Migrate to version 4.0.0 Here are some things you need to know about the 4.0.0 Stripe Terminal iOS and Android SDKs: - [Save payment details after payment globally](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md) - Users can now save payment details after payment outside of the US by updating the customer consent collection process for saving payment details on point-of-sale devices. - Support for [Mail order and telephone order](https://docs.stripe.com/terminal/features/mail-telephone-orders/overview.md) (MOTO) payments on smart readers - This feature is in preview. To request access, email [stripe-terminal-betas@stripe.com](mailto:stripe-terminal-betas@stripe.com). - Updates to minimum supported iOS platform version - Enables [reader auto-reconnect on unexpected disconnects](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=ios&reader-type=tap-to-pay#automatically-attempt-reconnection) by default for mobile and Tap to Pay readers, enhancing reader resiliency - Consolidates reader connection functionality and disconnect callbacks for all reader types # iOS > This is a iOS for when terminal-sdk-platform is ios. View the original doc at https://docs.stripe.com/terminal/references/sdk-migration-guide?terminal-sdk-platform=ios. If your application currently uses an Terminal iOS SDK version prior to 4.0.0, there are a few changes you need to make to upgrade and accept card present payments globally. For a detailed list of the changes from version 3.9.1 to 4.0.0, please reference the [SDK changelog](https://github.com/stripe/stripe-terminal-ios/blob/master/CHANGELOG.md). ## Update your minimum supported version to iOS 14 or higher We regularly update the minimum supported version of our SDKs to streamline our developer support efforts. Existing 3.X versions of the Terminal iOS SDK will continue to support devices running **iOS 13** and higher. ## Update saving cards after PaymentIntents integration If you [save a payment method after a successful in-person PaymentIntent](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md), you need to make the following updates to your integration: - When creating Terminal PaymentIntents, pass the [setup_future_usage](https://stripe.dev/stripe-terminal-ios/docs/4.0.0/Classes/SCPPaymentIntent.html#/c:objc\(cs\)SCPPaymentIntent\(py\)setupFutureUsage) parameter, which informs Stripe that you want to make future payments with the same card. - You also need to pass [allow_redisplay](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectConfiguration.html#/c:objc\(cs\)SCPCollectConfiguration\(py\)allowRedisplay) as `always` or `limited` in `SCPCollectConfiguration`. Pass `always` if you want the customer’s saved card to be presented to them in all future checkout flows, and `limited` if it can only be used in the context of the initially scoped use, such as a subscription. Learn more about [saving payment details after a payment](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md). ## Update saving cards without payment with SetupIntents integration To ensure a consistent integration shape between SetupIntents and PaymentIntents, as well as in-person and online transactions, in `SCPTerminal`’s `collectSetupIntentPaymentMethod`, we removed the `customerConsentCollected` parameter that was previously required on all SetupIntent transactions, and replaced it with the `allowRedisplay` parameter. Learn more about [saving directly without charging](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md). ## Update your discoverReaders usage - We added a new enum value, `discovering`, to [SCPConnectionStatus](https://stripe.dev/stripe-terminal-ios/docs/Enums/SCPConnectionStatus.html) to represent when reader discovery is running. Make sure your integration can handle this new state and provide relevant information to your customers. - We improved the handling of multiple simultaneous reader discover operations. Previously, calling [discoverReaders](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)discoverReaders:delegate:completion:) multiple times would queue the operations. Now, when a new [discoverReaders](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)discoverReaders:delegate:completion:) is called while an existing one is already in progress, the SDK cancels the ongoing operation and returns a [SCPErrorCanceledDueToIntegrationError](https://stripe.dev/stripe-terminal-ios/docs/Errors.html#/c:@SCPErrorNewDiscoveryRequested) error. The new discoverReaders operation then starts immediately. - Discovering smart and Tap to Pay readers now calls the `discoverReaders` completion block when the operation ends. This change reflects the reality that reader discovery for these reader types isn’t a long-running operation. - We fixed a bug that strongly held a reference to the [SCPDiscoveryDelegate](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPDiscoveryDelegate.html) in the SDK. Make sure your application is holding a strong reference to your delegate to receive the discovery events. ## Update your reader connection usage - To ensure a consistent integration pattern across reader discovery and connection, we consolidated all previous reader connection methods (`connectBluetoothReader`, `connectInternetReader`, `connectLocalMobileReader`) into [connectReader](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)connectReader:delegate:connectionConfig:completion:). The exact connection type is still determined by the passed in connection configuration. - For mobile readers and Tap to Pay readers, the `ReaderDelegate` parameter has been removed from the `connectReader` method and instead moved into the `connectionConfig`, replacing `SCPReconnectionDelegate`. Consistent with other reader types, smart readers `InternetConnectionConfiguration` now also expects an `InternetReaderDelegate` to be passed in, which will alert your integration of events, including when a reader disconnects. | Reader Type | Connection Configuration | Reader Delegate | | ------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | Mobile Reader | SCPBluetoothConnectionConfiguration | [SCPMobileReaderDelegate](https://stripe.dev/stripe-terminal-ios/docs/4.0.0/Protocols/SCPMobileReaderDelegate.html) | | Smart Reader | SCPInternetConnectionConfiguration | [SCPInternetReaderDelegate](https://stripe.dev/stripe-terminal-ios/docs/4.0.0/Reader.html#/c:objc\(pl\)SCPInternetReaderDelegate) | | Tap to Pay | SCPTapToPayConnectionConfiguration | [SCPTapToPayReaderDelegate](https://stripe.dev/stripe-terminal-ios/docs/4.0.0/Protocols/SCPTapToPayReaderDelegate.html) | ### Before ### After For more details, refer our documentation about [connecting to a reader](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=ios&reader-type=bluetooth#connect-reader). ## Auto reconnection is now enabled by default for mobile and Tap to Pay readers - To increase the resiliency of your Terminal integration with mobile and Tap to Pay readers, we enabled [auto reconnection](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=ios&reader-type=bluetooth#handle-disconnects) by default when a reader unexpectedly disconnects. - We recommend displaying notifications in your app to inform the users about the reader status throughout the reconnection process. To handle reader reconnection methods, we removed the `SCPReconnectionDelegate`. Its responsibilities have been integrated into the respective ReaderDelegates. Use `MobileReaderDelegate` for mobile readers, and `TapToPayReaderDelegate` for Tap to Pay readers to handle reconnection events. - If you implemented your own reader reconnection logic and want to maintain this behavior, you can turn off auto reconnection by setting [setAutoReconnectOnUnexpectedDisconnect](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPBluetoothConnectionConfigurationBuilder.html#/c:objc\(cs\)SCPBluetoothConnectionConfigurationBuilder\(im\)setAutoReconnectOnUnexpectedDisconnect:) to `false`. ### Before ### After For more details and code snippets, refer to our documentation about [automatically attempting to reconnect](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=ios&reader-type=tap-to-pay#automatically-attempt-reconnection). ## Update your reader disconnect handling - To be informed when a reader disconnects, we consolidated the reader disconnect callbacks for all reader types by removing `terminal:didReportUnexpectedReaderDisconnect:` from the `SCPTerminalDelegate`. Use `reader:didDisconnect:` as part of the ReaderDelegates to be notified when a reader disconnects. For mobile readers, the [SCPDisconnectReason](https://stripe.dev/stripe-terminal-ios/docs/Enums/SCPDisconnectReason.html) can help identify the reason for the disconnection. With auto-reconnection enabled, both [`-readerDidFailReconnect:`](https://stripe.dev/stripe-terminal-ios/docs/4.0.0/Protocols/SCPReaderDelegate.html#/c:objc\(pl\)SCPReaderDelegate\(im\)readerDidFailReconnect:) and [`reader:didDisconnect:`](https://stripe.dev/stripe-terminal-ios/docs/4.0.0/Protocols/SCPReaderDelegate.html#/c:objc\(pl\)SCPReaderDelegate\(im\)reader:didDisconnect:) methods are called if the SDK fails to reconnect to the reader and it becomes disconnected. ### Before ### After For more details, refer to our documentation about [handling disconnects manually](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=ios&reader-type=tap-to-pay#handle-the-disconnect-manually). ## Update your payment acceptance integration - You can now cancel `confirmPaymentIntent` using the returned `Cancelable` object. This is useful for QR code payments, which have an asynchronous confirmation process. Similarly, `confirmSetupIntent` and `confirmRefund` are now cancelable as well. - We improved type safety and consistency between the mobile SDKs by updating the way `paymentMethodTypes` are specified in `SCPPaymentIntentParameters` and `SCPSetupIntentParameters`. Previously, this parameter was represented as an array of strings (for example, [“card_present”]). It now uses enum values from `SCPPaymentMethodType`. - To improve the cancelation flow for PaymentIntents and SetupIntents, calling `Terminal::cancelPaymentIntent` or `Terminal::cancelSetupIntent` now also cancels any ongoing payment processing, you no longer need to cancel payment operations such as `.collectPaymentMethod` separately before canceling the PaymentIntent. - `SCPSetupIntent.stripeId` is now nullable to be consistent with `SCPPaymentIntent.stripeId`. Although the `stripeId` value will continue to exist, make sure your code safely handles the case where `SCPSetupIntent.stripeId` might be `null` to avoid compiler errors. ## Update usage for renaming and deprecation - [`BluetoothReaderDelegate`](https://stripe.dev/stripe-terminal-ios/3.9.0/Protocols/SCPBluetoothReaderDelegate.html) has been renamed to [`MobileReaderDelegate`](https://stripe.dev/stripe-terminal-ios/Protocols/SCPMobileReaderDelegate.html). - In `SCPReaderSoftwareUpdate,` we renamed `SCPUpdateTimeEstimate` to `SCPUpdateDurationEstimate` and `estimatedUpdateTime` to `durationEstimate` to better represent their intent. - In `SCPOfflineDetails`, which represents payment details available when a payment is created or confirmed while offline, we renamed the time that the offline payment happened from `collectedAt` to `storedAt`, aligning with the naming conventions in the Terminal Android SDK. - We renamed “local mobile” and “apple built in” to “Tap To Pay” in all SDK function names and error codes. # Android > This is a Android for when terminal-sdk-platform is android. View the original doc at https://docs.stripe.com/terminal/references/sdk-migration-guide?terminal-sdk-platform=android. If your application currently uses an Terminal Android SDK version prior to 4.0.0, there are some changes you need to make to upgrade and accept card present payments globally. For a detailed list of the changes from version 3.10.0 to 4.0.0, reference the [SDK changelog](https://github.com/stripe/stripe-terminal-android/blob/master/CHANGELOG.md). ## Update your saving cards after PaymentIntents integration If you [save a payment method after a successful in-person PaymentIntent](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md), you need to make the following updates to your integration: - When creating Terminal PaymentIntents, pass the [setup_future_usage](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-payment-intent/index.html#-745150436%2FProperties%2F-1219334616) parameter, which informs Stripe that you want to make future payments with the same card. - You also need to pass [allow_redisplay](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-collect-configuration/index.html#-74877977%2FProperties%2F-1219334616) as `ALWAYS` or `LIMITED` in `CollectConfiguration`. Pass `ALWAYS` if you want the customer’s saved card to be presented to them in all future checkout flows, and `LIMITED` if it can only be used in the context of the initially scoped use, such as a subscription. Learn more about [saving cards after a payment](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md). ## Update your saving cards without payment with SetupIntents integration To ensure a consistent integration shape between SetupIntents and PaymentIntents, as well as in-person and online transactions, in `Terminal`’s [`collectSetupIntentPaymentMethod`](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/index.html#915185703%2FFunctions%2F-1814817128), we removed the `customerConsentCollected` parameter previously required on all SetupIntent transactions, and replaced it with the `allowRedisplay` parameter. Learn more about [saving directly without charging](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md). ## Update your discoverReaders usage - We added a new enum value, `DISCOVERING`, to [ConnectionStatus](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-connection-status/index.html) to represent when reader discovery is running. Make sure your integration can handle this new state and provide relevant information to your customers. - We improved the handling of multiple simultaneous reader discover operations. Previously, calling [Terminal::discoverReaders](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/index.html#-307737612%2FFunctions%2F-1814817128) multiple times would queue the operations, which we learned was undesirable. Now when a new `Terminal::discoverReaders` is called while an existing one is already in progress, the SDK will cancel the ongoing operation and returns a [CANCELED_DUE_TO_INTEGRATION_ERROR](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-terminal-error-code/-c-a-n-c-e-l-e-d_-d-u-e_-t-o_-i-n-t-e-g-r-a-t-i-o-n_-e-r-r-o-r/index.html) error. The new discoverReaders operation then starts immediately. - Discovering smart and Tap to Pay readers now calls the `Terminal::discoverReaders` completion callback when the operation ends. This change reflects the reality that reader discovery for these reader types isn’t a long-running operation. ## Update your reader connection usage - To ensure a consistent integration pattern across reader discovery and connection, we consolidated all reader connection methods (`connectBluetoothReader`, `connectUsbReader`, `connectInternetReader`, `connectLocalMobileReader`, `connectHandoffReader`) into [Terminal::connectReader](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/index.html#1656325082%2FFunctions%2F-1814817128). The specific connection type is still determined by the provided connection configuration. - For mobile readers, the `readerListener` parameter has been removed from the old `connectBluetoothReader`, `connectUsbReader` methods and moved into the respective `ConnectionConfiguration` object, replacing `ReaderReconnectionListener`. For Tap to Pay readers, the `TapToPayConnectionConfiguration` now takes in an `TapToPayReaderListener` parameter, replacing `ReaderReconnectionListener`. - Consistent with other reader types, smart readers’s `InternetConnectionConfiguration` now also expects an [`InternetReaderListener`](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-internet-reader-listener/index.html) to be passed in, which alerts your integration of events including reader disconnects. - For [Apps on devices](https://docs.stripe.com/terminal/features/apps-on-devices/overview.md#pos-stripe-device) in handoff mode, [`HandoffReaderListener`](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-handoff-reader-listener/index.html) has been removed from the old `connectHandoffReader` method as a parameter, and moved into the `HandoffConnectionConfiguration` object. | Reader Type | Connection Configuration | Reader Listener | | --------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Mobile Reader | `BluetoothConnectionConfiguration` | [MobileReaderListener](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-mobile-reader-listener/index.html) | | Smart Reader | `InternetConnectionConfiguration` | [InternetReaderListener](https://stripe.dev/stripe-terminal-android/com.stripe.stripeterminal.external.callable/-internet-reader-listener/index.html) | | Tap to Pay | `TapToPayConnectionConfiguration` | [TapToPayReaderListener](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-tap-to-pay-reader-listener/index.html) | | Apps on Devices | `HandoffConnectionConfiguration` | [HandoffReaderListener](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-handoff-reader-listener/index.html) | ### Before ### After For more details, refer to our documentation about [connecting to a reader](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=android&reader-type=bluetooth#connect-reader). ## Auto reconnection is now enabled by default for mobile and Tap to Pay readers - To increase the resiliency of your Terminal integration with mobile and Tap to Pay readers, we enabled [auto reconnection](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=android&reader-type=bluetooth#handle-disconnects) by default when the reader unexpectedly disconnects. - We recommend displaying notifications in your app to inform the users about the reader status throughout the reconnection process. To handle reader reconnection methods, the `ReaderReconnectionListener` has been inherited by the respective ReaderListeners. Use `MobileReaderListener` for mobile readers, and `TapToPayReaderListener` for Tap to Pay readers to handle reconnection events. - We removed the `ReaderReconnectionListener` parameter from the connection configurations: `LocalMobileConnectionConfiguration`, `BluetoothConnectionConfiguration`, and `UsbConnectionConfiguration`, and replaced by the appropriate `ReaderListener`. If you implemented your own reader reconnection logic and want to maintain this behavior, you can turn off auto reconnection by setting [autoReconnectOnUnexpectedDisconnect](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-connection-configuration/-bluetooth-connection-configuration/index.html#1748469061%2FProperties%2F-1219334616) to `false`. ### Before ### After For more details, refer to our documentation about [automatically attempting to reconnect](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=android&reader-type=tap-to-pay#automatically-attempt-reconnection). ## Update your reader disconnect handling - To be informed when a reader disconnects, we consolidated the reader disconnect callbacks for all reader types by removing `TerminalListener::onUnexpectedReaderDisconnect`. Going forward, implement `onDisconnect` on any of the following listeners to be informed of their corresponding reader disconnects: `InternetReaderListener`, `MobileReaderListener`, `TapToPayReaderListener`, or `HandoffReaderListener`. For mobile readers, the [`DisconnectReason`](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-disconnect-reason/index.html) can help identify the reason for the disconnection. When auto-reconnect is enabled, both `onDisconnect` and [`onReaderReconnectFailed`](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-reader-reconnection-listener/on-reader-reconnect-failed.html) methods are called if the SDK fails to reconnect to the reader and it becomes disconnected. ### Before ### After For more details, refer to our documentation about [handling disconnects manually](https://docs.stripe.com/terminal/payments/connect-reader.md?terminal-sdk-platform=android&reader-type=tap-to-pay#handle-the-disconnect-manually). ## Update your payment acceptance integration - You can now cancel `Terminal::confirmPaymentIntent` using the returned `Cancelable` object. This is useful for QR code payments, which have an asynchronous confirmation process. Similarly, `Terminal::confirmSetupIntent` and `Terminal::confirmRefund` are now cancelable as well. - To improve the cancellation flow for PaymentIntents and SetupIntents, calling `Terminal::cancelPaymentIntent` or `Terminal::cancelSetupIntent` now also cancels any ongoing payment processing. You no longer need to cancel payment operations such as `Terminal::collectPaymentMethod` separately before canceling the PaymentIntent. - `SetupIntent.id` is now nullable to be consistent with `PaymentIntent.id`. Although the `id` value is still present, make sure your code safely handles the case where `SetupIntent.id` might be `null` to avoid compiler error. ## Update error handling - We moved `TerminalException.TerminalErrorCode` to a standalone enum, `TerminalErrorCode`. Make sure to update the import statements and Terminal error code definition to maintain functionality. - We added a new Terminal error code `TerminalErrorCode.GENERIC_READER_ERROR`, which can happen when the SDK is out of date, and can’t recognize the error returned by back the smart reader. To remediate this error, update your Terminal SDK. - For Tap to Pay on Android, `Terminal::collectPaymentMethod` and `Terminal::collectSetupIntentPaymentMethod` now time out after 60 seconds for Tap to Pay on Android transactions. A `TerminalException` is raised with the error code `TerminalErrorCode.CARD_READ_TIMED_OUT`. - For Tap to Pay on Android, when PIN collection is requested for a payment, a `TerminalException` is raised with the error code `FEATURE_NOT_ENABLED_ON_ACCOUNT` instead of `DECLINED_BY_STRIPE_API` with an `ONLINE_OR_OFFLINE_PIN_REQUIRED` `ApiError`. ## Update usage for renaming and refactoring - `ReaderListener` has been renamed to [`MobileReaderListener`](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-mobile-reader-listener/index.html). - We renamed the `allowedPaymentMethodTypes` parameter to `paymentMethodTypes` in the `PaymentIntentParameters.Builder` and `SetupIntentParameter.Builder` constructors. - In `ReaderSoftwareUpdate,` we renamed `UpdateTimeEstimate` to `UpdateDurationEstimate` and `estimatedUpdateTime` to `durationEstimate` to better represent their intent. - We converted `java.util.Date` references to timestamps in milliseconds for the following fields: `ReaderSoftwareUpdate::requiredAt`, `OfflineDetails::storedAt` and `OfflineSetupIntentDetails::storedAt`. Make sure your application interprets these timestamps correctly. - Fields on the `Location` object are no longer mutable. ## Update your Tap to Pay on Android integration - The Maven coordinates for the Tap to Pay on Android feature have changed to `com.stripe:stripeterminal-taptopay:4.0.0`. Update your build dependencies to point to the new artifact name. The old one will no longer be updated. - We renamed all `LocalMobile` function and field names to `TapToPay`. For example, `LocalMobileDiscoveryConfiguration` has been renamed to `TapToPayDiscoveryConfiguration`. - `TapToPayConnectionConfiguration` now takes a `TapToPayReaderListener` parameter. This listener inherits events from both `ReaderReconnectionListener` and `ReaderDisconnectionListener`, providing a unified mechanism for handling reader events. - We renamed the background application process used for collecting Tap to Pay transactions to use your application’s id, suffixed with `:stripetaptopay`.