Skip to content
Last updated

Embedded Checkout (iFrame) — Mobile Implementation

Loading the Banxa checkout in a mobile WebView requires specific configuration to support camera access, payment methods, and KYC flows.


Android

If your integration includes Google Pay, use Custom Chrome Tabs instead of a standard WebView. Standard WebView does not support GPAY or ACH.

import androidx.browser.customtabs.CustomTabsIntent

val customTabsIntent = CustomTabsIntent.Builder().build()
customTabsIntent.launchUrl(context, Uri.parse(checkoutUrl))

WebView (for integrations without Google Pay)

If you are not using Google Pay, you can use a WebView with the following configuration:

webView.settings.apply {
    javaScriptEnabled = true
    domStorageEnabled = true          // Required: enables local storage
    mediaPlaybackRequiresUserGesture = false  // Required: enables video instructions
    allowFileAccess = true
    setSupportZoom(false)
}

// Enable camera access
webView.webChromeClient = object : WebChromeClient() {
    override fun onPermissionRequest(request: PermissionRequest) {
        request.grant(request.resources)  // Grant camera/microphone
    }

    // Required for HTML5 video playback
    override fun onShowCustomView(view: View, callback: CustomViewCallback) {
        // Handle fullscreen video
    }
}

Declare permissions in AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />

iOS

Use SFSafariViewController when your integration includes KYC liveness checks (Sumsub). Liveness checks cannot complete in a standard WKWebView.

import SafariServices

let safariVC = SFSafariViewController(url: URL(string: checkoutUrl)!)
present(safariVC, animated: true)

WKWebView

If liveness checks are not required, WKWebView can be used with the following configuration:

import WebKit

let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true          // Required
config.mediaTypesRequiringUserActionForPlayback = []  // Required: allow autoplay for video instructions

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

// Request camera permission
webView.uiDelegate = self  // Implement WKUIDelegate

Implement WKUIDelegate to handle permission requests:

func webView(_ webView: WKWebView,
             requestMediaCapturePermissionFor origin: WKSecurityOrigin,
             initiatedByFrame frame: WKFrameInfo,
             type: WKMediaCaptureType,
             decisionHandler: @escaping (WKPermissionDecision) -> Void) {
    decisionHandler(.grant)
}

Add to Info.plist:

<key>NSCameraUsageDescription</key>
<string>Required for identity verification</string>
<key>NSMicrophoneUsageDescription</key>
<string>Required for identity verification</string>

React Native

Use react-native-webview with the following props:

import { WebView } from 'react-native-webview';

<WebView
  source={{ uri: checkoutUrl }}
  allowsInlineMediaPlayback={true}        // Required: inline video for instructions
  mediaPlaybackRequiresUserAction={false} // Required: allow autoplay
  domStorageEnabled={true}               // Required: local storage (Android)
  enableApplePay={true}                  // Required: Apple Pay on iOS
  onNavigationStateChange={(navState) => {
    // Detect redirect to your redirectUrl
    if (navState.url.startsWith('https://yourapp.com/order-complete')) {
      // Dismiss WebView and check order status
    }
  }}
/>

Camera and microphone access is controlled by OS-level permissions — set in AndroidManifest.xml and Info.plist as shown below, not via WebView props.


Flutter

Use webview_flutter with the following configuration:

import 'package:webview_flutter/webview_flutter.dart';

late final WebViewController controller;

controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setNavigationDelegate(NavigationDelegate(
    onNavigationRequest: (NavigationRequest request) {
      if (request.url.startsWith('https://yourapp.com/order-complete')) {
        // Dismiss WebView
        return NavigationDecision.prevent;
      }
      return NavigationDecision.navigate;
    },
  ))
  ..loadRequest(Uri.parse(checkoutUrl));

For camera access on Android, add to AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />

Payment methods that redirect out of the WebView

iDEAL, Klarna, and PayPal cannot complete inside a WebView. When a customer selects one of these methods, they will be redirected to an external browser to complete their payment. After payment, the customer is returned to the Banxa order status page — they will not be returned automatically to your WebView.

Design your post-payment UX accordingly: a confirmation screen with a link back to your app is the recommended pattern.


Configuration checklist

RequirementAndroidiOS
Local storagedomStorageEnabled = trueEnabled by default in WKWebView
Camera accessonPermissionRequest grantWKUIDelegate + Info.plist
Video playbackWebChromeClient + mediaPlaybackRequiresUserGesture = falseallowsInlineMediaPlayback = true
KYC livenessCustom Chrome Tabs or WebViewSFSafariViewController required
Google PayCustom Chrome Tabs requiredSupported in WKWebView