Stripe | Financial Infrastructure to Grow Your Revenue

Stripe | Financial Infrastructure to Grow Your Revenue

4466 articles

Terminal SDK migration guide


Terminal SDK migration guide

Learn how to migrate to version 5.0.0 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.

Before you migrate, review the Terminal SDK versioning and support policy to understand supported SDK versions, patch support timelines, and end-of-life enforcement.

Migrate to version 5.0.0

Here’s what you need to know about the version 5.0.0 Stripe Terminal iOS and Android SDKs:

  • Simplified payment integration
  • Process payments, setup intents, and refunds with a single method call combining collect and confirm steps.
  • Supports modern Swift async variants and Kotlin Coroutines for simplifying complex asynchronous flows
  • Swift concurrency (async/await) for iOS and Kotlin Coroutines for Android.
  • Customer cancellation enabled by default
  • On supported readers, customers can now cancel transactions by default during payment, setup, refund, and data collection flows.
  • Improved mobile reader and Tap to Pay reader auto reconnection observability
  • Enhanced reader auto-reconnection handling with more connection status states for mobile readers (Bluetooth and USB) and Tap to Pay readers.
  • Discover card acceptance support for Tap to Pay on Android Public preview
  • Accept Discover card payments with Tap to Pay on Android.
  • Updates to minimum supported platform versions from iOS 14.0 to iOS 15.0

If your application currently uses a Terminal iOS SDK version earlier than 5.0.0, there are several changes you need to make to upgrade. For a detailed list of the changes from version 4.x to 5.0.0, see the SDK changelog.

Update your minimum supported version to iOS 15 or higher

We regularly update the minimum supported version of our SDKs to streamline our developer support efforts.

Existing 4.X versions of the Terminal iOS SDK will continue to support devices running iOS 14 and higher.

Simplified payment integration

Update to unified payment processing

The v5 SDK includes methods that combine the collect and confirm steps into a single operation. While the existing collectPaymentMethod and confirmPaymentIntent methods continue to work, we recommend using the unified methods for simpler integrations.

Processing payments with processPaymentIntent

Replace two-step collect and confirm with a single processPaymentIntent method call.

Before

Select a language

Swift

Objective-C

No results

// Step 1: Collect payment method
Terminal.shared.collectPaymentMethod(paymentIntent, collectConfig: collectConfig) { collectedPaymentIntent, collectError in
 guard let collectedPaymentIntent = collectedPaymentIntent else {
 // Payment method collection failed
 return
 }
 // Step 2: Confirm the payment
 Terminal.shared.confirmPaymentIntent(collectedPaymentIntent) { confirmedPaymentIntent, confirmError in
 if let confirmedPaymentIntent = confirmedPaymentIntent {
 // Payment successful
 } else {
 // Payment confirmation failed
 }
 }
}

After

Select a language

Swift

Objective-C

No results

// Process and confirm the payment in one step
Terminal.shared.processPaymentIntent(paymentIntent, collectConfig: collectConfig) { processedPaymentIntent, processError in
 if let processedPaymentIntent = processedPaymentIntent {
 // Payment successful
 } else {
 // Payment failed
 }
}

Processing refunds with processRefund

The collectRefundPaymentMethod and confirmRefund methods are now deprecated. Use processRefund instead.

Before

Select a language

Swift

Objective-C

No results

// Step 1: Collect refund payment method
Terminal.shared.collectRefundPaymentMethod(refundParams) { collectError in
 guard collectError == nil else {
 // Refund collection failed
 return
 }
 // Step 2: Confirm the refund
 Terminal.shared.confirmRefund { refund, confirmError in
 if let refund = refund {
 // Refund successful
 } else {
 // Refund confirmation failed
 }
 }
}

After

Select a language

Swift

Objective-C

No results

// Process the refund in one step
Terminal.shared.processRefund(refundParams) { refund, refundError in
 if let refund = refund {
 // Refund successful
 } else {
 // Refund failed
 }
}

Processing setup intents with processSetupIntent

Replace two-step collect and confirm with a single processSetupIntent method call.

Before

Select a language

Swift

Objective-C

No results

// Step 1: Collect setup intent payment method
Terminal.shared.collectSetupIntentPaymentMethod(setupIntent, customerConsentCollected: true) { collectedSetupIntent, collectError in
 guard let collectedSetupIntent = collectedSetupIntent else {
 // Setup intent collection failed
 return
 }
 // Step 2: Confirm the setup intent
 Terminal.shared.confirmSetupIntent(collectedSetupIntent) { confirmedSetupIntent, confirmError in
 if let confirmedSetupIntent = confirmedSetupIntent {
 // Setup intent successful
 } else {
 // Setup intent confirmation failed
 }
 }
}

After

Select a language

Swift

Objective-C

No results

// Configure with allowRedisplay
let config = try CollectSetupIntentConfigurationBuilder()
 .setAllowRedisplay(.always)
 .build()

// Process the setup intent in one step
Terminal.shared.processSetupIntent(setupIntent, collectConfig: config) { processedSetupIntent, setupError in
 if let processedSetupIntent = processedSetupIntent {
 // Setup intent successful
 } else {
 // Setup intent failed
 }
}

Swift async variant support

The SDK now provides async variants for Terminal methods. You can write cleaner, sequential code instead of nesting completion handlers.

Before

let cancelable = Terminal.shared.collectPaymentMethod(paymentIntent, collectConfig: collectConfig) { collectedPaymentIntent, collectError in
 guard let collectedPaymentIntent = collectedPaymentIntent else {
 // Payment method collection failed
 return
 }
 Terminal.shared.confirmPaymentIntent(collectedPaymentIntent) { confirmedPaymentIntent, confirmError in
 // Handle confirmation
 }
}

After

let collectTask = Task {
 do {
 let collectedIntent = try await Terminal.shared.collectPaymentMethod(paymentIntent, collectConfig: collectConfig)
 let confirmedIntent = try await Terminal.shared.confirmPaymentIntent(collectedIntent)
 // Payment successful
 } catch {
 // Handle error
 }
}
// Use collectTask.cancel() to cancel the operation when needed

Platform and initialization

Update Terminal initialization

The setTokenProvider method has been removed. You must now initialize the SDK with the static Terminal.initWithTokenProvider(_tokenProvider:) method before accessing the Terminal.shared singleton.

Before

Select a language

Swift

Objective-C

No results

// In your AppDelegate or scene delegate
Terminal.setTokenProvider(yourTokenProvider)

After

Select a language

Swift

Objective-C

No results

// In your AppDelegate or scene delegate, at app launch
Terminal.initWithTokenProvider(yourTokenProvider)

Reader discovery and connection

Update DiscoveryConfiguration initialization

You can no longer initialize DiscoveryConfiguration objects directly with init or new. You must now use their associated builder classes.

Before

Select a language

Swift

Objective-C

No results

let config = SCPInternetDiscoveryConfiguration(isSimulated: true)

After

Select a language

Swift

Objective-C

No results

let config = InternetDiscoveryConfiguration.Builder()
 .setSimulated(true)
 .build()

Handle reconnection status changes

A new .reconnecting value has been added to the ConnectionStatus enum. During a reconnect, Terminal.shared.connectedReader will now be nil until the reconnection is successful.

Before

Select a language

Swift

Objective-C

No results

func terminal(_ terminal: Terminal, didChange connectionStatus: ConnectionStatus) {
 switch connectionStatus {
 case .notConnected:
 // Handle not connected
 case .connected:
 // Handle connected
 @unknown default:
 break
 }
}

After

Select a language

Swift

Objective-C

No results

func terminal(_ terminal: Terminal, didChange connectionStatus: ConnectionStatus) {
 switch connectionStatus {
 case .notConnected:
 // Handle not connected
 case .connected:
 // Handle connected
 case .reconnecting:
 // Handle reconnection in progress
 @unknown default:
 break
 }
}

Streamlined connection with easyConnect

For smart readers and Tap to Pay integrations using iOS SDK 5.1 or newer, you can now use Terminal.shared.easyConnect, which combines discovery and connection into a single method call.

Before

Select a language

Swift

Objective-C

No results

// Step 1: Discover the reader
Terminal.shared.discoverReaders(config, delegate: discoveryDelegate) { error in
 if let error = error {
 // Handle discovery error
 }
}

// In your DiscoveryDelegate
func terminal(_ terminal: Terminal, didUpdateDiscoveredReaders readers: [Reader]) {
 guard let selectedReader = readers.first else { return }
 // Step 2: Connect to the reader
 Terminal.shared.connectReader(selectedReader, connectionConfig: connectionConfig) { reader, error in
 if let reader = reader {
 // Handle successful connection
 } else if let error = error {
 // Handle connection error
 }
 }
}

After

Select a language

Swift

Objective-C

No results

// Discover and connect in one step by providing discovery filter
let discoveryConfig = try InternetDiscoveryConfigurationBuilder()
 .setLocationId("tml_1234567890") // optional, specify your location ID
 .setDiscoveryFilter(.bySerial("YOUR-READER-SERIAL-NUMBER"))
 .build()

let connectionConfig = try InternetConnectionConfigurationBuilder()
 .setFailIfInUse(false)
 .build()

let easyConnectConfig = InternetEasyConnectConfiguration(
 discoveryConfiguration: discoveryConfig,
 connectionConfiguration: connectionConfig
)

Terminal.shared.easyConnect(
 easyConnectConfig,
 delegate: internetReaderDelegate
) { reader, error in
 if let reader = reader {
 // Handle successful connection
 } else if let error = error {
 // Handle failure
 }
}

Internet reader discovery filtering

Internet reader discovery now supports filtering by reader ID or serial number. Set the discoveryFilter property on InternetDiscoveryConfigurationBuilder to discover a specific reader.

Before

Select a language

Swift

Objective-C

No results

let config = InternetDiscoveryConfigurationBuilder()
 .setLocationId("tml_1234567890")
 .build()

After

Select a language

Swift

Objective-C

No results

let config = try InternetDiscoveryConfigurationBuilder()
 .setLocationId("tml_1234567890") // optional
 .setDiscoveryFilter(.bySerial("READER-SERIAL-NUMBER")) // or .byReaderId("tmr_YOUR-READER-STRIPE-ID") to filter by reader id
 .build()

Payment acceptance and data collection

Customer cancellation is now enabled by default

On supported readers, the ability for customers to cancel transactions is now enabled by default. The customerCancellation property has changed from a Bool to the new SCPCustomerCancellation enum.

Before

Select a language

Swift

Objective-C

No results

let collectConfig = try CollectConfigurationBuilder()
 .setEnableCustomerCancellation(false)
 .build()

After

Select a language

Swift

Objective-C

No results

let collectConfig = try CollectPaymentIntentConfigurationBuilder()
 .setCustomerCancellation(.disableIfAvailable)
 .build()

Interac refund parameter updates

If you create SCPRefundParameters for an Interac refund using a PaymentIntent ID, you must now also pass the PaymentIntent’s clientSecret. You can alternatively continue using the charge ID, which doesn’t require the clientSecret.

Before

Select a language

Swift

Objective-C

No results

let refundParams = try RefundParametersBuilder(
 paymentIntentId: "pi_123",
 amount: 1000,
 currency: "cad"
).build()

After

Select a language

Swift

Objective-C

No results

let refundParams = try RefundParametersBuilder(
 paymentIntentId: "pi_123",
 clientSecret: "pi_123_secret_abc",
 amount: 1000,
 currency: "cad"
).build()
Last verified 2026-09-24

Is this helpful?