> For a complete page index, fetch https://docs.transak.com/llms.txt

# iOS

The Transak iOS integration allows you to embed a fully functional interface directly into your native iOS application using Webview.

Google Pay is not supported with iOS webview integration.

Update your `Info.plist` to include camera permission (required for KYC verification):

```xml
<key>NSCameraUsageDescription</key>
<string>Permission required for Camera Access.</string>
```

Configure your View Controller to load the Transak widget URL using your preferred implementation:

```swift title="SwiftUI"
import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    let url: URL

    func makeUIView(context: Context) -> WKWebView {
        let webview = WKWebView()
        return webview
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        let request = URLRequest(url: url)
        uiView.load(request)
    }
}

struct ContentView: View {
    var body: some View {
        WebView(url: URL(string: "https://global-stg.transak.com?apiKey=<YOUR_API_KEY>&sessionId=<YOUR_SESSION_ID>")!)
        .edgesIgnoringSafeArea(.all)
        .padding(10)
    }
}
```

```swift title="UIKit"
import UIKit
import WebKit

class WebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
    @IBOutlet weak var webView: WKWebView!

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let myURL = URL(string: "https://global-stg.transak.com?apiKey=<YOUR_API_KEY>&sessionId=<YOUR_SESSION_ID>")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }

    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if let serverTrust = challenge.protectionSpace.serverTrust {
            completionHandler(.useCredential, URLCredential(trust: serverTrust))
        }
    }
}
```

Call the [Create Widget URL](/api/public/create-widget-url) API from your backend to generate a secure widget url using Query parameters

The response returns a `widgetUrl` that should be used to load Transak in iOS Webview.

A `widgetUrl` is valid for 5 minutes and can only be used once. A new `widgetUrl` must be generated for every user flow.

**Example Request:**

```bash
curl --request POST \
  --url https://api-gateway-stg.transak.com/api/v2/auth/session \
  --header 'access-token: YOUR_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
  "widgetParams": {
    "apiKey": "YOUR_API_KEY",
    "referrerDomain": "yourdomain.com"
  }
}'
```

## Use cases

Use the table below to choose the right approach for redirects, order data, and WebView events.

<table>
  <thead>
    <tr>
      <th>
        Feature
      </th>

      <th>
        Approach
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        How to redirect users back to your app after a transaction
      </td>

      <td>
        [Deeplink](#deeplinking)
      </td>
    </tr>

    <tr>
      <td>
        How to get order data (e.g. status, order ID, amount)
      </td>

      <td>
        [Deeplink](#deeplinking), [Events](#events)
      </td>
    </tr>

    <tr>
      <td>
        Listen to WebView events (order created, widget close, etc.)
      </td>

      <td>
        [Events](#events)
      </td>
    </tr>
  </tbody>
</table>

### Deeplink

Transak supports deeplinking through the use of the `redirectURL` query parameter to enable seamless navigation after the purchase/sell process is completed.

Add the URL scheme to your `Info.plist` to handle the deeplink

```xml
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
        </array>
    </dict>
</array>
```

Listen for the deeplink and parse the returned parameters in your App

When Transak redirects back, it includes additional query parameters appended to deeplink URL mentioned [here](/customization/query-parameters#redirecturl-1).

```swift
@main
struct SampleApp: App {
     @State private var deepLinkPath: URL?

     var body: some Scene {
         WindowGroup {
             ContentView()
             NavigationView {
                 if let deepLinkPath = deepLinkPath {
                   // handle deeplink query parameters
                 } else {
                   ContentView()
                 }
             }
             .onOpenURL { url in
                 if url.scheme == "myapp" {
                     deepLinkPath = url
                 }
             }
         }
     }
}
```

Call the [Create Widget URL](/api/public/create-widget-url) API from your backend to generate a secure widget url using Query parameters along with `redirectURL` parameter.

The response returns a `widgetUrl` that should be used to load Transak in iOS Webview.

A `widgetUrl` is valid for 5 minutes and can only be used once. A new `widgetUrl` must be generated for every user flow.

**Example Request:**

```bash
curl --request POST \
  --url https://api-gateway-stg.transak.com/api/v2/auth/session \
  --header 'access-token: YOUR_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
  "widgetParams": {
    "apiKey": "YOUR_API_KEY",
    "referrerDomain": "yourdomain.com",
    "redirectURL": "myapp://transak-redirect"
  }
}'
```

### Events

Transak allows listening of in-widget events (like order creation, completion, and widget close) through native event handlers in iOS WebViews.

Add a script message handler to your WebView using the handler name IosWebview to listen for all frontend events.

```swift
struct WebView: UIViewRepresentable {
    let url: URL

    func makeCoordinator() -> WebViewCoordinator {
        return WebViewCoordinator(self)
    }

    func makeUIView(context: Context) -> WKWebView {
        let contentController = WKUserContentController()
        contentController.add(context.coordinator, name: "IosWebview")

        let config = WKWebViewConfiguration()
        config.userContentController = contentController

        let webView = WKWebView(frame: .zero, configuration: config)
        webView.navigationDelegate = context.coordinator
        webView.load(URLRequest(url: url))

        return webView
    }

    func updateUIView(_ webView: WKWebView, context: Context) {}

    class WebViewCoordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
        var parent: WebView

        init(_ parent: WebView) {
            self.parent = parent
        }

        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            if message.name == "IosWebview", let body = message.body as? String {
                print(body)
            }
        }
    }
}
```

#### Supported Events

<table>
  <thead>
    <tr>
      <th>
        Event Name
      </th>

      <th>
        Description
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        <code>
          TRANSAK_WIDGET_INITIALISED
        </code>
      </td>

      <td>
        Widget initialised with query params
      </td>
    </tr>

    <tr>
      <td>
        <code>
          TRANSAK_WIDGET_OPEN
        </code>
      </td>

      <td>
        Widget fully loaded
      </td>
    </tr>

    <tr>
      <td>
        <code>
          TRANSAK_ORDER_CREATED
        </code>
      </td>

      <td>
        Order created by user
      </td>
    </tr>

    <tr>
      <td>
        <code>
          TRANSAK_ORDER_SUCCESSFUL
        </code>
      </td>

      <td>
        Order is successful
      </td>
    </tr>

    <tr>
      <td>
        <code>
          TRANSAK_ORDER_CANCELLED
        </code>
      </td>

      <td>
        Order is cancelled
      </td>
    </tr>

    <tr>
      <td>
        <code>
          TRANSAK_ORDER_FAILED
        </code>
      </td>

      <td>
        Order is failed
      </td>
    </tr>

    <tr>
      <td>
        <code>
          TRANSAK_WIDGET_CLOSE
        </code>
      </td>

      <td>
        Widget is about to close
      </td>
    </tr>
  </tbody>
</table>