flutter_meon_kyc 2.0.4
flutter_meon_kyc: ^2.0.4 copied to clipboard
A comprehensive Flutter package for handling Know Your Customer (KYC) processes with automatic permissions, IPV support, payment integration, and complete lifecycle management.
flutter_meon_kyc #
A comprehensive Flutter package for handling Know Your Customer (KYC) processes in mobile applications. This package provides an advanced WebView-based KYC solution with automatic permission handling, IPV (In-Person Verification) support, payment link integration, and complete lifecycle management.
Features #
- π Easy Integration - Simple API with sensible defaults
- π― Automatic Permission Management - Camera, microphone, and location permissions
- π€ IPV Support - In-Person Verification with automatic detection
- π³ Payment Link Handling - UPI and payment app integration
- π Lifecycle Management - Automatic session cleanup with logout
- β Success Detection - Intelligent detection of KYC completion
- π¨ Customizable UI - Custom styles and header configuration
- π± Platform Support - Android and iOS compatible
- π Error Handling - Comprehensive error management
- π Logging - Built-in logging for debugging
Installation #
Add flutter_meon_kyc to your pubspec.yaml:
dependencies:
flutter_meon_kyc: ^2.0.1
Run:
flutter pub get
Platform Setup #
Android #
Add the following permissions to your android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Required permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Optional: For payment links -->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="upi" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="phonepe" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="gpay" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="paytmmp" />
</intent>
</queries>
<application>
<!-- Your app configuration -->
</application>
</manifest>
Update android/app/build.gradle:
android {
compileSdkVersion 34 // or higher
defaultConfig {
minSdkVersion 21 // or higher
targetSdkVersion 34
}
}
iOS #
Add the following to your ios/Runner/Info.plist:
<dict>
<!-- Camera permission -->
<key>NSCameraUsageDescription</key>
<string>Camera access is required for KYC verification</string>
<!-- Microphone permission -->
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for video verification</string>
<!-- Location permission -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access is required for KYC verification</string>
<!-- Optional: Allow arbitrary loads for specific domains -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
Update ios/Podfile (minimum iOS version):
platform :ios, '12.0'
Usage #
Basic Usage #
import 'package:flutter/material.dart';
import 'package:flutter_meon_kyc/flutter_meon_kyc.dart';
class KYCScreen extends StatelessWidget {
const KYCScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: MeonKYC(
companyName: 'your-company-name',
onSuccess: (data) {
print('KYC Completed: $data');
// Handle success - navigate to next screen
Navigator.of(context).pop();
},
onError: (error) {
print('KYC Error: $error');
// Handle error
},
onClose: () {
print('KYC Closed');
Navigator.of(context).pop();
},
),
);
}
}
Advanced Usage #
MeonKYC(
// Required
companyName: 'your-company-name',
// Optional - Workflow type
workflow: 'individual', // or 'business', 'custom-workflow'
// Optional - Callbacks
onSuccess: (data) {
// data contains:
// - status: 'completed'
// - timestamp: ISO8601 timestamp
// - url: current URL
// - message: success message
print('Success: ${data['message']}');
Navigator.of(context).pushReplacementNamed('/dashboard');
},
onError: (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $error')),
);
},
onClose: () {
Navigator.of(context).pop();
},
// Optional - Feature flags
enableIPV: true, // Enable In-Person Verification
enablePayments: true, // Enable payment link handling
autoRequestPermissions: true, // Auto-request permissions for IPV
// Optional - Permission control (for IPV)
enableCameraPermission: true, // Request camera permission
enableMicrophonePermission: true, // Request microphone permission
enableLocationPermission: true, // Request location permission
showHeader: true, // Show custom header bar
// Optional - Customization
headerTitle: 'Complete Your KYC',
baseURL: 'https://live.meon.co.in', // Or your custom domain
// Optional - Custom styles
customStyles: {
'container': BoxDecoration(
color: Colors.white,
),
'header': BoxDecoration(
color: Colors.blue,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 4,
offset: Offset(0, 2),
),
],
),
'headerTitle': TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
},
)
Full Example with Navigation #
import 'package:flutter/material.dart';
import 'package:flutter_meon_kyc/flutter_meon_kyc.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'KYC Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('KYC Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const KYCScreen(),
),
);
},
child: const Text('Start KYC Process'),
),
),
);
}
}
class KYCScreen extends StatelessWidget {
const KYCScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: MeonKYC(
companyName: 'demo-company',
workflow: 'individual',
enableIPV: true,
enablePayments: true,
autoRequestPermissions: true,
showHeader: true,
headerTitle: 'Complete KYC',
onSuccess: (data) {
// Show success dialog
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Success'),
content: Text('KYC completed at ${data['timestamp']}'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // Close dialog
Navigator.of(context).pop(); // Close KYC screen
},
child: const Text('OK'),
),
],
),
);
},
onError: (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: $error'),
backgroundColor: Colors.red,
),
);
},
onClose: () {
Navigator.of(context).pop();
},
),
);
}
}
API Reference #
MeonKYC Widget #
Required Parameters
| Parameter | Type | Description |
|---|---|---|
companyName |
String |
Your company identifier (required) |
Optional Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
workflow |
String |
'individual' |
KYC workflow type ('individual', 'business', etc.) |
onSuccess |
Function(Map<String, dynamic>) |
null |
Called when KYC is completed successfully |
onError |
Function(String) |
null |
Called when an error occurs |
onClose |
Function() |
null |
Called when user closes the KYC screen |
customStyles |
Map<String, dynamic>? |
null |
Custom styles for container, header, and title |
enableIPV |
bool |
true |
Enable In-Person Verification features |
enablePayments |
bool |
true |
Enable payment link handling |
autoRequestPermissions |
bool |
true |
Auto-request permissions when IPV step is detected |
enableCameraPermission |
bool |
true |
Request camera permission for IPV (can be controlled from frontend) |
enableMicrophonePermission |
bool |
true |
Request microphone permission for IPV (can be controlled from frontend) |
enableLocationPermission |
bool |
true |
Request location permission for IPV (can be controlled from frontend) |
showHeader |
bool |
true |
Show custom header with navigation controls |
headerTitle |
String |
'KYC Process' |
Title text in the header |
baseURL |
String |
'https://live.meon.co.in' |
Base URL for the KYC service |
Callback Data Structures #
onSuccess Data
{
'status': 'completed',
'timestamp': '2025-11-25T10:30:00.000Z',
'url': 'https://live.meon.co.in/company/thank-you',
'message': 'KYC process completed successfully'
}
Features in Detail #
1. Automatic Permission Management #
The package automatically requests and manages the following permissions:
- Camera: For document scanning and face verification
- Microphone: For video verification
- Location: For verification purposes
Dynamic Permission Control - You can control which permissions to request from the frontend:
MeonKYC(
companyName: 'your-company',
enableCameraPermission: true, // Request camera
enableMicrophonePermission: true, // Request microphone
enableLocationPermission: false, // Skip location (if not needed)
)
Permissions are requested:
- Automatically when IPV step is detected (if
autoRequestPermissionsis true) - Only the permissions you've enabled will be requested
- With proper error handling and settings navigation
- Users can retry or open device settings if denied
Permission Storage: When permissions are granted, they are stored in:
sessionStorage- For current sessionlocalStorage- For persistent storageCookies- For cross-domain persistence (7 days expiry)
This ensures that the WebView and any embedded iframes can access the permission states reliably.
2. IPV Detection & Auto-Reload #
The package intelligently detects IPV (In-Person Verification) steps by monitoring URLs for:
face-finder.meon.co.in/ipvpaths- Keywords:
face,video
When detected:
- Permissions are automatically requested (if enabled)
- Header title changes to "IPV Verification"
- Permission state is injected into the WebView
White Screen Auto-Fix: If the IPV page loads with a white screen (no content detected), the package will automatically reload the page (up to 2 attempts) to ensure proper loading. This prevents users from seeing blank screens and having to manually refresh.
3. Payment Link Handling #
Supports opening payment apps directly:
- UPI apps: PhonePe, Google Pay, Paytm, BHIM
- Google Pay with multiple scheme fallbacks
- Automatic detection and external app launching
- Prevents WebView from loading payment URLs
4. Success Detection #
Intelligent detection of KYC completion:
- Monitors page content for success patterns
- Checks for: "Thank You" + "journey has been completed" + "Redirecting in"
- Uses MutationObserver for dynamic content
- Prevents duplicate success callbacks
- Automatically performs logout before success callback
5. Session Management #
Complete lifecycle management:
- Initial Logout: Cleans up any existing session before starting
- Final Logout: Automatically logs out after successful completion
- Graceful handling of logout failures
6. Custom Styling #
Customize the appearance:
customStyles: {
'container': BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
),
),
'header': BoxDecoration(
color: Color(0xFF1E88E5),
),
'headerTitle': TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.white,
),
}
7. Header Controls #
The custom header provides:
- Back Button: Navigate back in WebView history (when available)
- Refresh Button: Reload current page
- Close Button: Close KYC with confirmation dialog
- Dynamic Title: Changes based on current step (IPV, etc.)
Troubleshooting #
Permissions Not Working #
- Ensure permissions are added to
AndroidManifest.xml(Android) andInfo.plist(iOS) - Set
autoRequestPermissions: true - Check device settings to ensure permissions are granted
WebView Not Loading #
- Verify
companyNameis correct - Check network connectivity
- Ensure
baseURLis accessible - Check logs for detailed error messages
Payment Links Not Opening #
- Add
<queries>section toAndroidManifest.xml - Ensure payment apps are installed on the device
- Set
enablePayments: true
Back Button Not Working #
The package uses PopScope to handle Android back button. If you're wrapping the widget in another PopScope or WillPopScope, it may conflict.
Migration from SDKCall #
If you're using the old SDKCall widget, migrate to MeonKYC:
Old Code:
SDKCall(
companyName: 'company',
workflowName: 'individual',
)
New Code:
MeonKYC(
companyName: 'company',
workflow: 'individual',
onSuccess: (data) => print('Success'),
onError: (error) => print('Error'),
onClose: () => Navigator.pop(context),
)
The SDKCall widget is deprecated but still available for backward compatibility.
Debugging #
Enable detailed logging by checking console output. The package uses the logger package with tags:
[MeonKYC]- General messages- Look for permission, navigation, and success detection logs
Requirements #
- Flutter: >= 1.17.0
- Dart SDK: >= 2.19.0 < 4.0.0
- Android: minSdkVersion 21+
- iOS: 12.0+
License #
MIT License - See LICENSE file for details
Support #
For issues and feature requests, please visit: GitHub Issues
Changelog #
See CHANGELOG.md for version history and updates.
Note: This package requires an active Meon KYC account and valid company configuration. Contact Meon support for setup assistance.