Usage
Starting the flow
AzakawKyc.start presents the onboarding flow and resolves once the user
leaves it.
import 'package:azakaw_kyc_flutter/azakaw_kyc_flutter.dart';
final result = await AzakawKyc.start(
context: context,
config: AzakawKycConfig(
sessionId: sessionId,
region: AzakawRegion.uae,
environment: AzakawEnvironment.sandbox,
),
);
Handling the result
switch (result.status) {
case AzakawKycStatus.completed:
// The portal reported the onboarding finished.
// Confirm server-side before treating the user as verified.
break;
case AzakawKycStatus.cancelled:
// The user closed the flow, via the close button or the system back
// gesture. Both route through a confirmation dialog.
break;
case AzakawKycStatus.failed:
// The portal could not be loaded.
debugPrint('${result.error}');
break;
}
If you prefer callbacks, start also accepts onComplete, onCancel and
onError. Note they do not all carry the same payload:
| Callback | Receives |
|---|---|
onComplete | AzakawKycResult — status and sessionId |
onCancel | AzakawKycResult — status and sessionId |
onError | AzakawKycException only — message, statusCode, url |
The returned future always resolves to an AzakawKycResult, so a failure
reaches you there as AzakawKycStatus.failed with the exception on
result.error.
await AzakawKyc.start(
context: context,
config: config,
onComplete: (result) => debugPrint('done'),
onCancel: (result) => debugPrint('cancelled'),
onError: (error) => debugPrint('$error'),
);
Treat AzakawKycStatus.completed as a hint to re-check, not as proof. It
means the portal signalled completion on the device; always verify the
session's real state against the Azakaw API before granting access.
Embedding in your own layout
Use AzakawKycView to place the flow inside a screen you control rather than
a full-screen route:
class VerifyScreen extends StatefulWidget {
const VerifyScreen({super.key, required this.config});
final AzakawKycConfig config;
@override
State<VerifyScreen> createState() => _VerifyScreenState();
}
class _VerifyScreenState extends State<VerifyScreen> {
// Attach this to the view to drive it from your own chrome.
final _kycKey = GlobalKey<AzakawKycViewState>();
Future<void> _close() async {
// Shows the same confirmation the built-in close button uses. When the
// user confirms, requestClose() calls onCancelled itself — so don't pop
// here too, or you pop twice and leave the screen underneath as well.
await _kycKey.currentState?.requestClose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Verify your identity'),
leading: IconButton(icon: const Icon(Icons.close), onPressed: _close),
),
body: AzakawKycView(
key: _kycKey,
config: widget.config,
onCompleted: () => Navigator.of(context).pop(true),
onCancelled: () => Navigator.of(context).pop(false),
onError: (error) => debugPrint('$error'),
),
);
}
}
AzakawKycViewState.currentError reports the failure currently on screen, or
null once a retry has cleared it — read it rather than caching a copy, which
would go stale after a successful retry.
Language and RTL
AzakawKycConfig(
sessionId: sessionId,
language: AzakawLanguage.ar, // Arabic, with RTL layout
);
Leaving language as null keeps whatever the portal defaults to.
External links
Any http/https navigation stays inside the WebView, including the
tenant domain the portal may redirect to and third-party pages it embeds such
as e-signing. Other schemes (mailto:, tel:, app links) are cancelled and
handed to your app:
AzakawKyc.start(
context: context,
config: config,
onExternalUrl: (url) => launchUrl(url), // package:url_launcher
);
On Android 11+, url_launcher can only open mailto: and tel: links if
your AndroidManifest.xml declares them inside <queries>:
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
<intent>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent>
</queries>
How the SDK talks to the portal
The Web SDK is a parent page holding an iframe, so the portal's
postMessage calls cross a frame boundary. A Flutter WebView has no parent
frame, so the SDK reports the portal's own origin as hostOrigin and injects
a script at document start that forwards the portal's messages to Dart.
This is what makes completion detection possible: the portal only emits
events when a hostOrigin is present.
Supported events:
| Event | Direction | Handling |
|---|---|---|
OnboardingCompleted | portal → SDK | Resolves with AzakawKycStatus.completed. |
IframeParametersRequest | portal → SDK | Answered with hideSidebar and hideOnboardingSections. |
IframeParametersResponse | SDK → portal | The only message the SDK sends. |
TenantBaseUrl | portal → SDK | Reloads the flow on the tenant's own host. |
ResizeIframe | portal → SDK | Ignored — a WebView fills its own box and the portal scrolls inside it. |