iOS-specific Mobile Widget

Generate widget config

Read more about widget config

  1. Need to get otp
  2. Prepare link to css file
  3. Create config object with specific configuration
  4. Get base64 string from config object
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

This is an example of a function to get a string with html. For apiHostPci check this link. traceId should be the same as for 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>
            """
  }

Take a look on this code. It will allow you to receive messages from iframe with events. Replace myMessageHandler with your name.

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

Configure WebView

Example:

let webView = WKWebView();

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

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

Keep in mind: you need to specify baseURL: 'https://localhost'

iFrame Events

You may receive messages from iframe with events. Example:

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 your name.