Like other platforms, iOS requires the same two or three simple steps: Add a web view, handle events/messages, and, in some cases, authenticate the user.
Component used: WKWebView
Note: iOS 26 introduced WebKit for SwiftUI which has not yet been tested with Elements. No problems are expected, but implementation details may change.
Required Web View Configuration
- Enable JavaScript
- Enable Web Storage (DOM Storage)
elements-in-ios.swift
// Step 1: Set Up a Web View
WebView(
url: url,
onTokenReceived: { token in
self.token = token
self.showTokenAlert = true
},
onFullResponseReceived: { response in
handleCardTokenizeResponse(response)
}
)
.edgesIgnoringSafeArea(.all)
Component used: WKUserContentController
Note: iOS 26 introduced WebKit for SwiftUI which has not yet been tested with Elements. No problems are expected, but implementation details may change.
Please Log In to view this content.
elements-in-ios.swift
// Step 2: Set Up Communications: Event/Message Handling
// Step 2a: Send Event to Elements
Component used: WKUserContentController
Please Log In to view this content.
elements-in-ios.swift
// Step 2b: Listen for events from Elements
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("Received postMessage: \(message.body)")
var data: Data? = nil
if let dict = message.body as? [String: Any] {
data = try? JSONSerialization.data(withJSONObject: dict)
} else if let str = message.body as? String {
data = str.data(using: .utf8)
}
if let data, let msg = try? JSONDecoder().decode(DailypayCardTokenizeMessage.self, from: data),
msg.type == "DAILYPAY_CARD_TOKENIZE_RESPONSE" {
onIssuerReceived?(msg.response.issuer)
onTokenReceived?(msg.response.token)
onFullResponseReceived?(msg.response)
}
}
elements-in-ios.swift
// Step 3: Setup Authentication
//
// Code sample coming soon
//
elements-in-ios.swift
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let url: URL
let handlerName = "iosListener"
var onTokenReceived: ((String) -> Void)?
var onFullResponseReceived: ((DailypayCardTokenizeResponse) -> Void)?
class Coordinator: NSObject, WKScriptMessageHandler {
var onIssuerReceived: ((String) -> Void)?
var onTokenReceived: ((String) -> Void)?
var onFullResponseReceived: ((DailypayCardTokenizeResponse) -> Void)?
init(onTokenReceived: ((String) -> Void)?, onFullResponseReceived: ((DailypayCardTokenizeResponse) -> Void)?) {
self.onTokenReceived = onTokenReceived
self.onFullResponseReceived = onFullResponseReceived
}
// Step 2: Set Up Communications: Event/Message Handling
// Step 2a: Send Event to Elements
// Step 2b: Listen for events from Elements
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("Received postMessage: \(message.body)")
var data: Data? = nil
if let dict = message.body as? [String: Any] {
data = try? JSONSerialization.data(withJSONObject: dict)
} else if let str = message.body as? String {
data = str.data(using: .utf8)
}
if let data, let msg = try? JSONDecoder().decode(DailypayCardTokenizeMessage.self, from: data),
msg.type == "DAILYPAY_CARD_TOKENIZE_RESPONSE" {
onIssuerReceived?(msg.response.issuer)
onTokenReceived?(msg.response.token)
onFullResponseReceived?(msg.response)
}
}
// Step 2 End
}
// Step 3: Setup Authentication
//
// Code sample coming soon
//
// Step 3 End
func makeCoordinator() -> Coordinator {
Coordinator(onTokenReceived: onTokenReceived, onFullResponseReceived: onFullResponseReceived)
}
func makeUIView(context: Context) -> WKWebView {
let contentController = WKUserContentController()
contentController.add(context.coordinator, name: handlerName)
let config = WKWebViewConfiguration()
config.userContentController = contentController
// Forward window.postMessage to iOS
let js = """
window.postMessage = function(data) {
window.webkit.messageHandlers.\(handlerName).postMessage(data);
};
"""
let userScript = WKUserScript(source: js, injectionTime: .atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(userScript)
let webView = WKWebView(frame: .zero, configuration: config)
let request = URLRequest(url: url)
webView.load(request)
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
// No-op
}
}
struct DailypayCardTokenizeResponse: Decodable {
let firstName: String
let lastName: String
let addressLineOne: String
let addressLineTwo: String
let addressCity: String
let addressState: String
let addressZipCode: String
let expirationMonth: String
let expirationYear: String
let addressCountry: String
let issuer: String
let token: String
enum CodingKeys: String, CodingKey {
case firstName = "first_name"
case lastName = "last_name"
case addressLineOne = "address_line_one"
case addressLineTwo = "address_line_two"
case addressCity = "address_city"
case addressState = "address_state"
case addressZipCode = "address_zip_code"
case expirationMonth = "expiration_month"
case expirationYear = "expiration_year"
case addressCountry = "address_country"
case issuer
case token
}
}
struct DailypayCardTokenizeMessage: Decodable {
let type: String
let response: DailypayCardTokenizeResponse
let success: Bool
}
struct ContentView: View {
// Replace client_id and implementation_id with values supplied by DailyPay
// that are unique to you and your application
@State private var urlString: String = "https://elements.uat.dailypay.com/v1/debit-card-tokenization?client_id=REPLACE_WITH_YOUR_CLIENT_ID&implementation_id=REPLACE_WITH_YOUR_IMPLEMENTATION_ID"
@State private var showAlert = false
@State private var issuer: String? = nil
@State private var showTokenAlert = false
@State private var token: String? = nil
func handleCardTokenizeResponse(_ response: DailypayCardTokenizeResponse) {
// Add card to DailyPay using POST /accounts
// See https://developer.dailypay.com/tag/Accounts#operation/createAccount
print("Ready to send to the DailyPay REST API: \(response)")
}
var body: some View {
VStack {
TextField("Enter URL", text: $urlString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
if let url = URL(string: urlString) {
// Step 1: Set Up a Web View
WebView(
url: url,
onTokenReceived: { token in
self.token = token
self.showTokenAlert = true
},
onFullResponseReceived: { response in
handleCardTokenizeResponse(response)
}
)
.edgesIgnoringSafeArea(.all)
// Step 1 End
} else {
Text("Invalid URL")
}
}
.alert(isPresented: $showTokenAlert) {
Alert(
title: Text("Token Received"),
message: Text(token ?? "No token"),
dismissButton: .default(Text("OK"))
)
}
}
}
#Preview {
ContentView()
}