iOS

Create a view controller with a WKWebview and set its class to EGreetingButtonViewController. Assign the webView’s Outlet to the view controller’s WKWebview.

EGreetingButtonViewController.swift

import UIKit
import WebKit

class EGreetingButtonViewController: UIViewController, WKScriptMessageHandler {
    @IBOutlet weak var webView: WKWebView!

    let jwt = /* supplied by FI */
    let cid = /* Partner-supplied Client ID property */
    let baseUrl = /* supplied by FI */

    override func viewDidLoad() {
        super.viewDidLoad()
        let url = URL(string: "\(baseURL)/#tkn=\(jwt)&cid=\(cid)&action=%2Fpersonalize")!
        webView.configuration.userContentController.add(self, name: "appInterface")
        webView.load(URLRequest(url: url))
    }

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if let messageString = message.body as? String,
            let data = messageString.data(using: .utf8),
            let eventDictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {

            if eventDictionary["event"] as? String == "PERSONALIZE" {
                // get the action
                guard let action = eventDictionary["actions"]["personalize"] as? String else {
                    return
                }
                let eCardViewController = // instantiate view controller
                eCardViewController.action = action
                present(activityVC, animated: true)
            }
        }
    }
}

Create a view controller with a WKWebview and set its class to EGreetingViewController. Assign the webView’s Outlet to the view controller’s WKWebview.

EGreetingViewController.swift

import UIKit
import MessageUI
import WebKit

class EGreetingViewController: UIViewController, UIActivityItemSource, WKScriptMessageHandler {
    @IBOutlet weak var webView: WKWebView!

    let verifiedHost: String = ""// supplied by the FI
    let jwt = /* supplied by FI */
    let cid = /* Partner-supplied Client ID property */
    let baseUrl = /* supplied by FI */
    var action: String?

    var redemptionUrl = "" /* initialize */
    var envelopeUrl = "" /* initialize */
    var logoUrl = "" /* initialize */
    var messageTitle = "" /* initialize */
    var messageDescription = "" /* initialize */

    override func viewDidLoad() {
        super.viewDidLoad()
        var urlString = "\(baseURL)/#tkn=\(jwt)&cid=\(cid)"
        if let action = action {
            urlString = urlString + "&action=\(action)"
        }
        let url = URL(string: urlString)!
        webView.configuration.userContentController.add(self, name: "appInterface")
        webView.load(URLRequest(url: url))
    }

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if let messageString = message.body as? String,
            let data = messageString.data(using: .utf8),
            let eventDictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {

            if eventDictionary["event"] as? String == "VOUCHER_CREATED" {
                guard let urlString = eventDictionary["url"] as? String else { return }

                guard let shareInfo = eventDictionary["shareInfo"] as? [String: Any], let
                            envelopeUrl = shareInfo["packagingImage"] as? String, let logoUrl = shareInfo["favIcon"] as? String, let messageTitle = shareInfo["title"] as? String, let messageDescription = shareInfo["description"] as? String else {
                        return
                    }
                // store the values for iOS sharing
                self.redemptionUrl = urlString
                self.envelopeUrl = envelopeUrl
                self.logoUrl = logoUrl
                self.messageTitle = messageTitle
                self.messageDescription = messageDescription

                // validate url
                guard redemptionUrl.scheme == "https" && redemptionUrl.host == verifiedHost else {
                    print("invalid url")
                    return
                }
                // handle url e.g. present the share sheet
                let items = [self]
                let activityVC = UIActivityViewController(activityItems: items, applicationActivities: nil)

                // IPAD sharesheet requirement
                activityVC.excludedActivityTypes = [.airDrop]
                if let popoverController = activityVC.popoverPresentationController {
                    popoverController.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
                    popoverController.sourceView = self.view
                    popoverController.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
                }

                present(activityVC, animated: true)
            }
        }
    }

    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return self.activityViewController(activityViewController, itemForActivityType: UIActivity.ActivityType.message) ?? ""
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        let buttonText = "Open"
        let footerMessage = "Brought to you by Vouchr!"

        let backgroundColor = "#0c2da1"
        let textColor = "white"
        let buttonColor = "#007aff"
        let buttonTextColor = "white"

        // Apple Mail HTML
        let htmlString = """
            <html>
              <body style="font-family: sans-serif">
                <table
                  class="main"
                  style="
                    background-color: \(backgroundColor);
                    color: \(textColor);
                    margin: auto;
                    min-width: 500px;
                    padding-top: 32px;
                    padding-bottom: 32px;
                    text-align: center;
                    width: 500px;
                  "
                >
                  <tr>
                    <td>
                      <img
                        class="logo"
                        src="\(self.logoUrl)"
                        style="height: 48px"
                      />
                      <h1>\(self.messageTitle)</h1>
                      <p>\(self.messageDescription)</p>
                      <img
                        class="envelope"
                        src="\(self.envelopeUrl)"
                        style="padding: 20px 0px 20px 0px"
                      />
                      <div>
                        <a
                          href="\(self.redemptionUrl)"
                          target="_blank"
                        >
                          <button
                            style="
                              background: \(buttonColor);
                              border-color: \(buttonColor);
                              border-radius: 999px;
                              border-style: solid;
                              color: \(buttonTextColor);
                              font-size: large;
                              height: 40px;
                              width: 200px;
                            "
                          >
                            \(buttonText)
                          </button>
                        </a>
                      </div>
                    </td>
                  </tr>
                </table>

                <table
                  class="footer"
                  style="
                    border: 1px solid #e0e0e088;
                    margin: auto;
                    min-width: 500px;
                    padding: 24px 0px 24px 0px;
                    width: 500px;
                  "
                >
                  <tr>
                    <td>
                      <p
                        class="footerMessage"
                        style="margin: auto; text-align: center; width: 70%;"
                      >
                        \(footerMessage)
                      </p>
                    </td>
                  </tr>
                </table>
              </body>
            </html>
        """

        if (activityType == .mail) {
            return htmlString
        }
        return redemptionUrl
    }

    func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String {
        // Apple Mail Subject line
        return "Check out this eCard!"
    }

    /*
     * Connect this IBAction method to a separate back button if desired (optional)
     */
    @IBAction func browserBack() {
        if (self.webview.canGoBack){
            self.webview.goBack()
        }
    }
}

%}

ChangeLog

v1.4.3 - May 18, 2023

  • Separated full iOS example