Webview Integration
Flow version supported: v1.2 (or earlier)
Embed the H5 identity verification flow in a webview to keep users inside your native Android or iOS app instead of redirecting to an external browser.
Prerequisites
- Obtain a launch URL by calling the Initiate Flow API
- Ensure your app has camera permission declared in its manifest (Android) or
Info.plist(iOS)
Integration Steps
Step 1: Override WebChromeClient for camera access
Override WebChromeClient to handle camera permission requests within the webview. The H5 flow requires camera access for selfie capture.
private var mWebChromeClient: WebChromeClient = object : WebChromeClient() {
override fun onPermissionRequest(request: PermissionRequest?) {
if (ContextCompat.checkSelfPermission(
this@DemoH5Activity,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
request?.grant(request.resources)
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(
arrayOf(Manifest.permission.CAMERA),
REQUEST_CAMERA_PERMISSION
)
}
}
}
override fun onShowCustomView(view: View, callback: CustomViewCallback) {}
override fun onHideCustomView() {}
}Step 2: Initialize the webview and load the launch URL
Configure the webview with JavaScript enabled and user-gesture-free media playback, then load your launch URL. Replace https://xxx with the actual URL from the Initiate Flow API.
webview.apply {
settings.apply {
javaScriptEnabled = true
mediaPlaybackRequiresUserGesture = false
}
webChromeClient = mWebChromeClient
loadUrl("https://xxx")
}
Step 1: Initialize the webview
Create a WKWebView configured for inline media playback and JavaScript execution.
let configuration = WKWebViewConfiguration()
configuration.allowsInlineMediaPlayback = true
configuration.mediaTypesRequiringUserActionForPlayback = []
configuration.preferences.javaScriptEnabled = true
configuration.preferences.javaScriptCanOpenWindowsAutomatically = true
webView = WKWebView(frame: self.view.bounds, configuration: configuration)
webView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(webView)
webView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
webView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = trueStep 2: Request camera permission
Check and request camera authorization before loading the verification page.
func checkAVAuthorizationStatus(with block: @escaping((_ authed: Bool) -> Void)) {
let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
if authStatus == .authorized {
block(true)
} else if authStatus == .denied || authStatus == .restricted {
block(false)
} else {
AVCaptureDevice.requestAccess(for: .video) { (result) in
DispatchQueue.main.async {
block(result)
}
}
}
}
func loadWebPage() {
if let webUrl = webUrl {
checkAVAuthorizationStatus { authed in
if authed {
self.webView.load(URLRequest(url: webUrl))
}
}
}
}
Step 3: Present the webview and load the launch URL
Present the webview controller modally and load your launch URL. Replace https://xxx with the actual URL from the Initiate Flow API.
if let webviewController = storyboard?.instantiateViewController(withIdentifier: "WebViewController") as? WebViewController {
webviewController.webUrl = URL(string: "https://xxx")
webviewController.modalPresentationStyle = .fullScreen
present(webviewController, animated: true)
}
Handling Redirection
After the flow completes, fails, or the user exits, they are redirected back to your application. The redirect URL includes query parameters indicating the flow outcome.
For the full specification of query parameters and status codes returned during redirection, refer to the Partner Redirection document.
Updated 5 months ago