Mobile SDK Migration: 3.x → 4

This guide outlines the changes required to migrate your mobile application from Mobile SDK 3.x to Mobile SDK 4.

Mobile SDK 4 introduces native 3-D Secure flows, updated transaction handling, a simplified styling model, and revised platform integrations for both iOS and Android.

General topics

Platform & build requirements

We have increased the minimum OS and build requirements:

  • iOS: Minimum version is now iOS 15. Building your app requires Xcode 26.0.1.
  • Android: Minimum version is now Android 6 (API 23). Building your app requires Gradle plugin 9.1.1.

mobileToken → transactionId

mobileToken has been replaced by transactionId. Consequently, when your app calls your backend to start a payment, a transactionId will be received instead of the mobileToken.

Transaction initialization in the app remains unchanged apart from the parameter name. For example:

  • Transaction(mobileToken: token)Transaction(transactionId: transactionId)

3-D Secure app-to-app switch

Mobile SDK 4 includes native 3-D Secure screens and can automatically switch between your app and supported banking apps for authentication.

To return from the banking app to your app, a universal link (iOS) or App Link (Android) must be configured and associated with your domain.

PostFinance Card → PostFinance Pay

The PostFinance Card payment method has been deprecated and replaced by PostFinance Pay, which is supported in Mobile SDK 4.

PostFinance Card is no longer available on the new platform and will not be supported going forward. Please migrate to PostFinance Pay if you have not already done so.


Removed options

The following TransactionOptions have been removed:

  • testing / isTesting: now automatically detected
  • useCertificatePinning: now always enabled

Styling

The SDK UI has been streamlined to improve clarity and visual balance. Customization options have been reduced to a single accent color for key interface elements. This results in a cleaner appearance that aligns with modern platform design trends, such as Apple’s Liquid Glass.

Previous theming options are no longer supported and have been replaced by a single accent color:

  • iOS: ThemeConfiguration.accentColor
  • Android: dtpl_accent_color in colors.xml

iOS topics

TransactionError redesign

TransactionError has been redesigned and now primarily contains:

  • code: Error code from the Datatrans JSON API
  • message: Optional error message

These correspond to the same transaction errors returned via webhooks or the status API.

The SDK may also return internal errors such as SDKConfigurationError and ThreeDsSDKError. These are defined in TransactionError.

The Mobile SDK 3 class BackendError, as well as the error categories technical, validation, authentication, and authorization, are no longer supported.


Apple Pay

SavedApplePay.token: SavedCard has been replaced by:

  • SavedApplePay.cardPaymentMethod: PaymentMethodType – indicates the card type used
  • SavedApplePay.cardInfo: CardInfo – provides additional card details

SavedApplePay.last4 remains available.

In addition, the following changes have been made:

  • DTApplePayDelegateApplePayDelegate
  • ApplePayDelegate.userDidAuthorizePayment now includes an additional parameter attemptId, which can be used to correlate the payment attempt with data from the status API or webhooks

Various

  • SavedPaymentMethod no longer supports legacy (non-JSON) deserialization. Only create(jsonString:) is supported.
  • Merchants using AppCallbackHandler must call handleUserActivity(userActivity:) to process universal link callbacks from 3-D Secure authentication.

Android topics

Package restructuring

Classes have been moved to new packages. The main changes are:

  • ch.datatrans.payment.apich.datatrans.api.payment
  • ch.datatrans.payment.paymentmethodsch.datatrans.paymentmethod.* and ch.datatrans.api.payment.saved
  • ch.datatrans.payment.exceptionch.datatrans.api.payment.exception
Full package migration table
Old PackageNew Package
ch.datatrans.payment.api.Transactionch.datatrans.api.payment.Transaction
ch.datatrans.payment.api.TransactionOptionsch.datatrans.api.payment.TransactionOptions
ch.datatrans.payment.api.TransactionSuccessch.datatrans.api.payment.TransactionResult.TransactionSuccess
ch.datatrans.payment.exception.TransactionExceptionch.datatrans.api.payment.exception.TransactionException
ch.datatrans.payment.ExternalProcessRelayActivitych.datatrans.api.payment.relay.ExternalProcessRelayActivity
ch.datatrans.payment.paymentmethods.PaymentMethodTypech.datatrans.api.PaymentMethodType
ch.datatrans.payment.paymentmethods.SavedPaymentMethodch.datatrans.api.payment.saved.SavedPaymentMethod
ch.datatrans.payment.paymentmethods.SavedCardch.datatrans.api.payment.saved.SavedCard
ch.datatrans.payment.paymentmethods.CardExpiryDatech.datatrans.paymentmethod.card.CardExpiryDate
ch.datatrans.payment.paymentmethods.GooglePayConfigch.datatrans.paymentmethod.googlepay.GooglePayConfig
ch.datatrans.payment.paymentmethods.GooglePayCustomerInfoch.datatrans.paymentmethod.googlepay.GooglePayCustomerInfo
ch.datatrans.payment.paymentmethods.GooglePayCustomerInfoCallbackch.datatrans.paymentmethod.googlepay.GooglePayCustomerInfoCallback
ch.datatrans.payment.paymentmethods.ShippingAddressParametersch.datatrans.paymentmethod.googlepay.ShippingAddressParameters
ch.datatrans.payment.paymentmethods.CustomerInfoParametersch.datatrans.paymentmethod.googlepay.CustomerInfoParameters

SDK start + transaction result

We have redesigned how the Android SDK is started and how transaction results are returned to the app. The SDK is now launched using Android's standard ActivityResultLauncher concept, allowing us to more reliably reconstruct internal state when the SDK activity or the whole app is killed and restarted while a transaction is in progress.

Previously, the SDK was started via TransactionRegistry and results were delivered through a TransactionListener:

// v3
transaction.listener = object : TransactionListener {
    override fun onTransactionSuccess(result: TransactionSuccess) { ... }
    override fun onTransactionError(exception: TransactionException) { ... }
    override fun onTransactionCancel(mobileToken: String) { ... }
}
TransactionRegistry.startTransaction(activity, transaction)

In Mobile SDK 4, this is replaced by an ActivityResultLauncher with a TransactionContract:

// v4
// 1. Declare a launcher with callback handlers
private val launcher = registerForActivityResult(TransactionContract()) { result ->
    when (result) {
       is TransactionSuccess -> processTransactionSuccess(result)
       is TransactionError -> processTransactionError(result.transactionException)
       is TransactionCanceled -> processTransactionCancel()
    }
}

// 2. Configure the transaction object
val transaction = Transaction(transactionIdFromBackend)
// optionally configure transaction.options

// 3. Launch
launcher.launch(transaction)

The launcher callback receives the transaction result, which can then be handled based on type.

  • TransactionResult.TransactionSuccess will contain details of the successful transaction, including the payment method and a saved method if a registration took place
  • TransactionResult.TransactionError will contain the transaction exception with error code and optional error message, which correspond to the same transaction errors returned via webhooks or the status API
  • TransactionResult.TransactionCanceled indicates that the transaction was canceled

Note: The payment callback may be invoked after the activity or app has been killed and restarted. The launcher must therefore be registered unconditionally whenever the activity or fragment is created. Do not register it inside button clicks, callbacks, or conditional code.


TransactionException redesign

TransactionException has been redesigned and now primarily contains:

  • errorCode: Error code from the Datatrans JSON API
  • errorMessage: Optional error message

These correspond to the same transaction errors returned via webhooks or the status API.

The SDK may also return internal errors such as SDK_CONFIGURATION_ERROR and 3DS_SDK_ERROR. These are defined as constants on TransactionException.

The Mobile SDK 3 exception hierarchy (AuthenticationException, AuthorizationException, BackendException, TechnicalException, InitializationException, etc.) has been removed.


Google Pay

SavedGooglePay.token: SavedCard has been replaced by:

  • SavedGooglePay.cardInfo: SavedCardInfo – provides additional card metadata such as brand, type, and issuer

SavedGooglePay.last4 remains available.


Various

  • SavedPaymentMethod no longer supports legacy (non-JSON) deserialization. Only create(jsonString:) is supported.