Web SDK in a mobile WebView
Host a merchant web checkout in a mobile WebView while preserving DEUNA callbacks, external authentication, security boundaries, and responsive behavior.
On this page
Use a custom WebView only when your application must host an existing merchant-owned web checkout. For a new mobile integration, prefer the maintained iOS, Android, or React Native SDK; those SDKs already implement the DEUNA WebView bridge and external-action lifecycle.
Architecture#
See the WebView wrapper pattern#
This walkthrough shows a merchant web checkout loaded inside an iOS WebView. The native wrapper exchanges messages with the checkout page while DEUNA Web SDK renders the payment experience:
The video demonstrates the presentation pattern. UI details can change; use the architecture, security boundaries, and platform requirements below as the implementation contract.
Required WebView capabilities#
| Capability | Why it is required |
|---|---|
| JavaScript and DOM storage | The hosted checkout and SDK require browser execution and session storage. |
| New-window interception | 3DS and APM flows can use window.open. |
| Navigation allow-list | Prevent the checkout WebView from becoming a general-purpose browser. |
| Bidirectional message bridge | Forward safe completion, error, close, and lifecycle messages. |
| App lifecycle handling | Preserve state across backgrounding and external authentication. |
| Downloads or sharing, if used | Voucher flows can produce a file or downloadable reference. |
Define a minimal bridge#
type NativeMessage = {
version: 1;
type: 'success' | 'error' | 'closed' | 'event';
widget: 'payment' | 'elements' | 'voucher' | 'nextAction';
data?: unknown;
};
function postToNative(message: NativeMessage) {
const body = JSON.stringify(message);
window.webkit?.messageHandlers.deunaPayment?.postMessage(body); // iOS
window.deunaPayment?.postMessage(body); // Android
window.ReactNativeWebView?.postMessage(body); // React Native
}At the native boundary, parse JSON with a strict schema, reject unknown message versions and types, cap message size, and ignore messages from an unexpected top-level page. Never expose a generic native method dispatcher to JavaScript.
Forward SDK outcomes#
await DeunaSDK.initPaymentWidget({
orderToken,
callbacks: {
onSuccess: (data) => postToNative({version: 1, type: 'success', widget: 'payment', data}),
onError: (data) => postToNative({version: 1, type: 'error', widget: 'payment', data}),
onClosed: (action) => postToNative({version: 1, type: 'closed', widget: 'payment', data: {action}}),
onEventDispatch: (event) => postToNative({
version: 1,
type: 'event',
widget: 'payment',
data: {event},
}),
},
});Forward only the fields the native application needs. Do not bridge order tokens, wallet tokens, card data, complete customer objects, or arbitrary raw event payloads.
External windows and redirects#
The Web SDK emits lifecycle events for supported external popups. Your WebView must intercept window.open or new-window requests and present the target without falsely reporting it as immediately closed.
- Allow only
httpsURLs whose host matches your approved authentication or payment destinations. - Prefer an isolated browser surface for third-party content; do not inject the merchant bridge into an issuer or provider page.
- Track the external surface independently from the checkout WebView.
- On close or return, resume the checkout and retrieve the order state.
- Do not suppress timeout errors globally. A timeout can represent a real incomplete action; reconcile, then show an appropriate recovery path.
The SDK repositories include maintained reference wrappers in Examples/checkout-web-wrapper for iOS and examples/checkout-web-wrapper for Android.
Platform checklist#
iOS · WKWebView
Enable JavaScript for the trusted checkout configuration, register a narrowly named WKScriptMessageHandler, validate top-level navigation in WKNavigationDelegate, and implement WKUIDelegate new-window handling. Remove script handlers when the controller is disposed to avoid retaining the bridge.
Android · WebView
Enable JavaScript and DOM storage only for the checkout WebView, use a constrained JavaScript interface, validate URLs in WebViewClient, and handle new windows through the WebChromeClient or a controlled secondary surface. Disable file and content access unless your application explicitly needs them.
React Native · react-native-webview
Use onMessage, onShouldStartLoadWithRequest, and the supported new-window callback. Keep the main checkout component mounted while the external surface is visible. The maintained DEUNA React Native SDK already implements this controller and is preferred for new integrations.
Responsive and accessible presentation#
- Respect safe-area insets and the on-screen keyboard.
- Use the full available width and dynamic viewport height; avoid a fixed desktop-sized WebView.
- Keep native close controls outside payment content but reachable by assistive technology.
- Announce navigation and errors, and restore focus after an external surface closes.
- Test rotation, split-screen, large text, screen readers, slow networks, and app backgrounding.
Test matrix#
- Card success, decline, and customer closure.
- Frictionless and challenged 3DS.
- APM redirect success, cancellation, and provider timeout.
- External window closed by the customer.
- App backgrounded and later resumed.
- Network loss before and after submission.
- Untrusted navigation and malformed bridge messages are rejected.
- Backend state is correct after every ambiguous client outcome.