This guide demonstrates how to integrate the PCI widget into your iOS application using Swift. Follow these steps for successful implementation.

Generate Widget Configuration

Read more about widget config

To generate your widget configuration:

  1. Obtain an OTP (one-time password)
  2. Prepare a URL link to your CSS file
  3. Create a configuration object with your specific settings
  4. Convert this configuration object to a base64-encoded string
private func generateWidgetConfig() {
    let config: [String: Any] = [
      "token": otp,
      "cardId": cardId,
      "styleUrl": styleUrl,
      "cssClass": cssClass,
      "cardholderName": [
        "display": false
      ]
    ]

    // Convert config dictionary to JSON data
    do {
      let jsonData = try JSONSerialization.data(withJSONObject: config, options: [])

      let widgetConfig = jsonData.base64EncodedString();
    } catch {
      NSLog("Error: \(error)")
    }
  }

Generate HTML for WebView

The following function creates an HTML string for your WebView. For apiHostPci values, refer to the environments documentation. Important: The traceId must match the one used in your OTP generation request.

private func getHtml() -> String {
    let iframeUrl = "\(apiHostPci)/card-details/widget?traceId=\(traceId!)&params=\(widgetConfig)";

    return """
            <!DOCTYPE html>
                <html>
                  <script>
                    window.addEventListener('message', function(event) {
                      window.webkit.messageHandlers.myMessageHandler.postMessage(event.data);
                    });
                  </script>
                  <head>
                    <meta charset="utf-8">
                    <meta name="viewport" content="width=device-width">
                    <title>Card</title>
                    <style>
                      body {
                        margin: 0;
                        padding: 0;
                        width: 100vw;
                        height: 100vh;
                        background-color: transparent;
                      }
                    </style>
                  </head>
                  <body>
                    <iframe
                      src="\(iframeUrl)"
                      title="Card Details"
                      width="100%"
                      height="100%"
                      frameBorder="0"
                      id="card-details-widget-frame"
                      allow="clipboard-read; clipboard-write"
                    />
                  </body>
                </html>
            """
  }

Notice the JavaScript event listener in the HTML. This enables your app to receive messages from the iframe containing event data. Replace myMessageHandler with your own handler name::

window.addEventListener('message', (event) => {
  window.webkit.messageHandlers.myMessageHandler.postMessage(event.data);
});

Configure Your WebView

Set up a basic WebView with transparency support:

let webView = WKWebView();

// to make it transparent
webView.backgroundColor = .clear
webView.isOpaque = false

let baseUrl = URL(string: "https://localhost");
webView.loadHTMLString(html, baseURL: baseUrl);

Note: You must specify baseURL: 'https://localhost' when loading the HTML string.

iframe Events

Configure your WebView to receive and process events from the iframe:

let config = WKWebViewConfiguration()
let userContentController = WKUserContentController()

// Add message handler
userContentController.add(self, name: "myMessageHandler")

config.userContentController = userContentController

webView = WKWebView(frame: .zero, configuration: config)

// Implement WKScriptMessageHandler method to receive messages
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    // Handle message received from JavaScript
    print("Message received from JavaScript: \(message.body)")
}

Replace myMessageHandler with the same handler name you used in your HTML script.