# Code Samples ## Apple 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 } 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) } } } 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://companion.workloads.production.dailypay.com/v1/widgets/debitcard/tokenizer?client_id=123&implementation_id=3213" @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) { WebView( url: url, onTokenReceived: { token in self.token = token self.showTokenAlert = true }, onFullResponseReceived: { response in handleCardTokenizeResponse(response) } ) .edgesIgnoringSafeArea(.all) } else { Text("Invalid URL") } } .alert(isPresented: $showTokenAlert) { Alert( title: Text("Token Received"), message: Text(token ?? "No token"), dismissButton: .default(Text("OK")) ) } } } #Preview { ContentView() } ``` ## Google Android ```kotlin package com.example.webviewrunner import android.os.Bundle import android.webkit.JavascriptInterface import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient import android.app.AlertDialog import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { private lateinit var webView: WebView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) webView = findViewById(R.id.webView) // Configure WebView settings val webSettings: WebSettings = webView.settings webSettings.javaScriptEnabled = true // Enable JavaScript if your page uses it webSettings.setSupportZoom(true) // Enable zoom controls webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // Allow mixed content (HTTP/HTTPS) webSettings.domStorageEnabled = true // Enable DOM storage // Set a WebViewClient to handle page navigation within the WebView itself webView.webViewClient = object : WebViewClient() { // This method is deprecated in API 24 and later, but still useful for older devices override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { url?.let { view?.loadUrl(it) } return true // Return true to indicate that the app handled the URL } // For API 24 and later override fun shouldOverrideUrlLoading(view: WebView?, request: android.webkit.WebResourceRequest?): Boolean { request?.url?.let { uri -> view?.loadUrl(uri.toString()) } return true // Return true to indicate that the app handled the URL } override fun onReceivedError(view: WebView?, request: android.webkit.WebResourceRequest?, error: android.webkit.WebResourceError?) { super.onReceivedError(view, request, error) android.util.Log.e("WebView", "Error: ${error?.description}") } override fun onReceivedHttpError(view: WebView?, request: android.webkit.WebResourceRequest?, errorResponse: android.webkit.WebResourceResponse?) { super.onReceivedHttpError(view, request, errorResponse) android.util.Log.e("WebView", "HTTP error: ${errorResponse?.statusCode}") } } // Add JavaScript interface for postMessage webView.addJavascriptInterface(object { @JavascriptInterface fun postMessage(message: String) { // Interpret response and send to DailyPay using POST /accounts // See https://developer.dailypay.com/tag/Accounts#operation/createAccount // For demo - alert the response payload here. runOnUiThread { AlertDialog.Builder(this@MainActivity) .setTitle("Message from WebView") .setMessage(message) .setPositiveButton("OK", null) .show() } } }, "AndroidInterface") // Replace client_id and implementation_id with values supplied by DailyPay // that are unique to you and your application webView.loadUrl("https://companion.workloads.production.dailypay.com/v1/widgets/debitcard/tokenizer?client_id=123&implementation_id=3213") } // Handle back button presses to navigate within the WebView's history override fun onBackPressed() { if (webView.canGoBack()) { webView.goBack() } else { super.onBackPressed() } } } ``` ## React Native Install dependencies: `npm install react-native-webview` or `yarn add react-native-webview` ```javascript import React, { useRef, useState } from "react"; import { View } from "react-native"; import { WebView } from "react-native-webview"; const TokenizerComponent = () => { const webViewRef = useRef(null); const [tokenData, setTokenData] = useState(null); const handleWebViewMessage = (event) => { try { const messageData = JSON.parse(event.nativeEvent.data); if (messageData.type === "DAILYPAY_CARD_TOKENIZE_RESPONSE") { if (messageData.success && messageData.response) { setTokenData(messageData.response); } } } catch (error) { console.error("Failed to parse message:", error); } }; return ( ); }; ```