> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://amer.developers.trustly.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://amer.developers.trustly.com/_mcp/server.

# iOS

The Trustly Lightbox SDK for iOS allows you to build a bank authorization workflow in your iOS app. Integrate the Select Bank Widget or the Trustly Lightbox to retrieve bank authorization data that can be used with other Trustly APIs.

To use an example project for testing and learning, see the [Swift iOS Example App](https://github.com/TrustlyInc/trustly-ios-example) in GitHub.

If you need help with your integration, contact your Trustly representative or send your request to <a href="mailto:us.integrations@trustly.com">[us.integrations@trustly.com](mailto:us.integrations@trustly.com)</a>.

*Note*: The examples provided here assume you're using [UIKit](https://developer.apple.com/documentation/uikit).

`PayWithMyBank` references are deprecated. If your app is using `PayWithMyBank`, you must change it to `Trustly`.

## Prerequisites

* [iOS 12](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-12-release-notes) or later
* [Xcode 14](https://developer.apple.com/documentation/xcode-release-notes/xcode-14-release-notes) or later

## Add the Trustly package

Add the Trustly package to your application to enable secure and convenient online bank payments.

### CocoaPods

1. Open your project’s Podfile, or create one if it doesn’t exist.

2. Add the following line:

   ```
   pod 'TrustlySDK'
   ```

3. In Terminal, go to your project folder and run:

   ```text
   pod install
   ```

### Swift Package Manager

1. Open your project in Xcode,  and then click **File** > **Add Package Dependencies**.

2. Search for `trustly-ios` or paste the following URL into the search field:

   ```
   https://github.com/TrustlyInc/trustly-ios.git
   ```

3. Click **Add Package** and follow the prompts.

### Manual

To install the Trustly package manually, see the [ios-legacy documentation](/sdks/mobile/i-os) .

## Set up OAuth support (Bank Login)

To support OAuth login flows, the Trustly Lightbox interacts with the [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) class. In some cases it interacts with the customer's mobile banking app directly. To support this functionality, your app must be configured to handle Universal Links so users are automatically returned to your app after authenticating with their bank. See [Set up Universal Links](#set-up-universal-links) for configuration steps.

If your app does not already have a Universal Link configured, you must set one up. Without it, users will not be automatically redirected to your app after logging in on a mobile banking app.

## Define Establish Data with a Request Signature

To ensure communications between the Trustly Lightbox SDK and the Trustly API are secure, add a `requestSignature` authentication request to your iOS app to request the server access key before rendering the Select Bank Widget or Trustly Lightbox. Most of the information in the `establishData` property should be fetched or calculated dynamically. For example, customer information or unique order identifiers you want included in the `merchantReference` field. For example:

```swift
import UIKit
import TrustlySDK

@IBOutlet weak var trustly: TrustlyView!
var establishData:Dictionary<AnyHashable,Any>?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.establishData = [
          "accessId": YOUR_ACCESS_ID,
          "merchantId": YOUR_MERCHANT_ID,
          "requestSignature": GENERATED_HASH, 
          "description": "transaction description",
          "merchantReference": YOUR_UNIQUE_TRANSACTION_REF,
          "amount": "0.00",
          "paymentType":"Deferred",
          "currency":"USD",
          "metadata.deepLinkUrl":"https://yourdomain.com/trustly-return", // Your Universal Link.
     //   "env": "sandbox",
       ]
    }
```

> NOTE: When using the sandbox environment, set the `env` property to `sandbox`. Before publishing your production application, remove the `env` property.

For more information about generating a `requestSignature`, see [Securing Requests](/integrate/api-fundamentals/secure-requests-and-signature-validation).

For more information about properties, accepted values, and their behaviors, see [Establish Data Object](/integrate/core-concepts/the-establish-data-object).

## Display the Select Bank Widget

The Trustly Lightbox can be launched without using the Select Bank Widget. However, Trustly recommends rendering the Select Bank Widget for an optimal customer experience. For information about using the Select Bank Widget with the Trustly Lightbox, see [Displaying the Bank Widget](/sdks#select-bank-widget).

In your application, on the parent view implementation of `viewDidLoad` call the Trustly Lightbox SDK`selectBankWidget` function to initiate the Select Bank Widget view.

The following examples render the Select Bank Widget and then allow a customer to select their bank.

```swift
var establishData:Dictionary<AnyHashable,Any>?

override func viewDidLoad() {
        super.viewDidLoad()

        let widgetVC = WidgetViewController(establishData: establishData)
        widgetVC.delegate = self

        widgetVC.view.frame = CGRect(x: 16, y: 220, width: 350, height: 500)
        view.addSubview(widgetVC.view)
}
...

extension YOUR_VIEW_CONTROLLER: TrustlySDKProtocol {
    func onReturn(_ returnParameters: [AnyHashable : Any]) {
        // Triggered when lightbox completes authentication successfully.
    }
    func onCancel(_ returnParameters: [AnyHashable : Any]) {
        // Triggered when lightbox completes failed authentication.
    }
    func onBankSelected(data: [AnyHashable: Any]) {
        // Triggered when the widget returns the selected bank.
    }
    func onExternalUrl(onExternalUrl: TrustlyViewCallback?) {
        // Called when the TrustlySDK panel must open an external URL.
    }
    func onChangeListener(_ eventName: String, _ eventDetails: [AnyHashable : Any]) {
        // Triggered when JavaScript posts some event.
    }
}
```

## Launch the Lightbox

The Lightbox is launched by using the `establishData` parameter and the `establish` method. Customers activate the method by selecting a **Checkout** or a **Continue** button in your app. For example:

```swift
func launchTrustly() {
        let widgetVC = WidgetViewController(establishData: establishData)
        widgetVC.delegate = self

        if let nav = self.navigationController {
            nav.pushViewController(widgetVC, animated: true)
        } else {
            self.present(widgetVC, animated: true)
        }
}
```

## Handle the return from bank authentication

When the bank redirects back to your app via Universal Link, implement the handler in your `SceneDelegate` (iOS 13+) or `AppDelegate` (legacy) to notify the Lightbox SDK that the user has returned.

```swift title="Scene Delegate (iOS 13+)"
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
              let incomingURL = userActivity.webpageURL else {
            return
        }
        NotificationCenter.default.post(name: .trustlyCloseWebview, object: nil)
    }
}

extension Notification.Name {
    static let trustlyCloseWebview = Notification.Name(TrustlyView.trustlyCloseWebview)
}
```

```swift title="App Delegate (Legacy)"
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication,
                     continue userActivity: NSUserActivity,
                     restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
              let _ = userActivity.webpageURL else {
            return false
        }
        NotificationCenter.default.post(name: .trustlyCloseWebview, object: nil)
        return true
    }
}

extension Notification.Name {
    static let trustlyCloseWebview = Notification.Name(TrustlyView.trustlyCloseWebview)
}
```

For a more comprehensive example of this logic, see the [Trustly iOS example app](https://github.com/TrustlyInc/trustly-ios-example).

## Add callback functions

The Trustly Lightbox provides two callback functions to process terminal customer behaviors. When a customer successfully creates a bank authorization, the `onReturn` function is called. If the user exits the process at any time, or the authorization is otherwise unsuccessful, the `onCancel` function is called. For more information about these functions, see [Redirect URLs](/integrate/core-concepts/redirect-urls-and-return-flow).

Define two functions to handle these callbacks and pass them into the `onReturn` and `onCancel` parameters of the `establish` method. In the following examples, customer or Trustly app responses activate specific events:

````swift
...

extension YOUR_VIEW_CONTROLLER: TrustlySDKProtocol {
    func onReturn(_ returnParameters: [AnyHashable : Any]) {
        // Triggered when lightbox completes authentication successfully.
    }
    
    func onCancel(_ returnParameters: [AnyHashable : Any]) {
        // Triggered when lightbox authentication fails.
    }
    
    func onBankSelected(data: [AnyHashable : Any]) {
        // Triggered when the widget returns the selected bank.
    }
    
    func onExternalUrl(onExternalUrl: TrustlyViewCallback?) {
        // Called when the TrustlySDK panel must open an external URL.
    }
    
    func onChangeListener(_ eventName: String, _ eventDetails: [AnyHashable : Any]) {
        // Triggered when JavaScript posts some event.
    }
}

...

## Set up Universal Links

[Universal Links](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content/) use standard HTTPS URLs to return users directly to your app after bank authentication. Unlike custom URL schemes, they are verified against your domain — preventing other apps from intercepting them — and fall back to your website if the app isn't installed.

### Define the associated domains

Create a JSON file named `apple-app-site-association` and host it at one of the following locations on your server:

* **Root**: `https://yourdomain.com/apple-app-site-association`
* **Subdirectory**: `https://yourdomain.com/.well-known/apple-app-site-association`

Server requirements:

* Served over HTTPS.
* `Content-Type` header set to `application/json`.
* Filename must have no extension.

```json
{
  "applinks": {
    "apps": [
      "ABCDE12345.com.yourcompany.YourApp"
    ],
    "details": [
      {
        "appID": "ABCDE12345.com.yourcompany.YourApp",
        "paths": [
          "/trustly-return",
          "*"
        ]
      }
    ]
  }
}
````

| Key     | Description                                                                                                                  |
| :------ | :--------------------------------------------------------------------------------------------------------------------------- |
| `apps`  | An array of application identifiers. Detailed matching is handled in `details`.                                              |
| `appID` | Your app's unique identifier in the format `<Team ID>.<Bundle Identifier>`. Find your Team ID in the Apple Developer Portal. |
| `paths` | URL paths the app should handle. Use `*` as a catch-all, or `NOT /path` to exclude a path from opening the app.              |

Verify your server returns the correct `Content-Type`:

```bash
curl -I https://yourdomain.com/.well-known/apple-app-site-association
```

### Add the Associated Domains entitlement

1. Open your project in Xcode and select your application target.
2. Go to **Signing & Capabilities**.
3. Click **+ Capability** and select **Associated Domains**.
4. Add your domains, prefixed with `applinks:`:

```text
applinks:yourdomain.com
applinks:www.yourdomain.com
```

Adding this capability automatically inserts the `com.apple.developer.associated-domains` key into your app's entitlements file.

### Implement the Universal Link handler

iOS delivers the Universal Link to your app via the `scene(_:continue:)` method in your `SceneDelegate`. Implement this method to extract the incoming URL and pass it to your routing logic:

```swift
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let incomingURL = userActivity.webpageURL else {
        return
    }
    handleDeepLink(url: incomingURL)
}
```

For apps that support both Universal Links and legacy custom URL schemes during a migration period, see [Migrate from custom schemes (iOS)](/sdks/mobile/migrate-from-custom-schemes-i-os) for a unified router pattern that handles both link types through a single navigation flow.

### Configure your deep link strategy (optional)

Universal Links function without a fallback. However, Trustly recommends having a default deep link strategy configured for your merchant account. This ensures your application has a consistent fallback behavior if a strategy isn't explicitly provided within the `establishData` object in your code.

Any settings passed to the `establishData` object in your code override the default configurations stored in your Trustly account profile.

Because this setup requires internal configuration, you'll need to contact your Customer Success Manager (CSM) or <a href="mailto:us.support@trustly.com">Trustly Support</a> to enable this fallback for your account.

When you submit your request, you must provide the following information:

* **Deep link strategy**: Specify `deeplink-url`.
* **Universal Link**: Provide your fully qualified domain (for example, `https://yourdomain.com/`).