Meon DigiLocker SDK for Flutter
A Flutter package for integrating Meon DigiLocker APIs with dynamic form fields and validation. Includes searchable document dropdowns, complete document verification flow with WebView integration, and comprehensive error handling.
Features
- ✅ 6 Complete API integrations with DigiLocker services
- ✅ Dynamic form fields based on document selection
- ✅ Searchable document dropdown for easy issuer and document discovery
- ✅ Comprehensive validation for all inputs
- ✅ Complete document verification flow with WebView integration
- ✅ All API calls handled internally - no need to manage complex API sequences
- ✅ Dynamic client credentials support for different environments
- ✅ TypeScript-inspired Dart models with proper serialization
- ✅ Material Design 3 compatible widgets
- ✅ Error handling with descriptive messages
- ✅ Customizable theming and styling
Installation
Add this to your package's pubspec.yaml file:
dependencies:
meon_digilocker_sdk: ^2.1.0
Or for local development:
dependencies:
meon_digilocker_sdk:
path: ../path/to/meon_digilocker_sdk
Then run:
flutter pub get
Platform Setup
Android
Add internet permission to android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- ... other permissions ... -->
</manifest>
iOS
Add the following to ios/Runner/Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>io.flutter.embedded_views_preview</key>
<true/>
Quick Start
Simple Usage (Recommended)
The easiest way to use this SDK is with the DigilockerForm widget. All API calls and logic are handled internally:
import 'package:flutter/material.dart';
import 'package:meon_digilocker_sdk/meon_digilocker_sdk.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: DigilockerForm(
companyName: 'your-company-name',
secretToken: 'your-secret-token',
onSuccess: (data) {
print('Document verification successful!');
// Handle the verified document data here
// data contains all the document information like:
// - aadhar_no, pan_number, name, dob, etc.
},
onError: (error) {
print('Error: $error');
// Handle errors here
},
),
);
}
}
That's it! The DigilockerForm component handles:
- Loading issuers
- Loading documents
- Loading form fields
- Form submission
- WebView handling
- Final data retrieval
Advanced Usage (SDK Methods)
If you need more control, you can use the SDK methods directly:
import 'package:meon_digilocker_sdk/meon_digilocker_sdk.dart';
// Initialize SDK with your credentials
final sdk = MeonDigilockerSDK(
companyName: 'democapital',
secretToken: 'cy7Kw2rWqdzVo2KPxlU0ymd9uRQKPSsb',
);
// Get access token
final tokenResponse = await sdk.getAccessToken();
print(tokenResponse.clientToken);
// Search for issuers
final issuersResponse = await sdk.getListOfIssuersInDetail(
GetListOfIssuersInDetailParams(
clientToken: tokenResponse.clientToken,
state: tokenResponse.state,
search: 'insurance',
),
);
// Generate DigiLocker URL
final urlResponse = await sdk.generateDigiUrl(
GenerateDigiUrlParams(
clientToken: tokenResponse.clientToken,
redirectUrl: 'https://your-app.com/callback',
companyName: 'your-company-name',
otherDocuments: [
{
'doctype': 'PAN',
'orgid': 'ORG001',
'consent': 'Y',
'pan_number': 'ABCDE1234F',
}
],
),
);
// Get final verification data
final finalData = await sdk.sendEntireData(
SendEntireDataParams(
clientToken: tokenResponse.clientToken,
state: tokenResponse.state,
status: true,
),
);
Using Individual Components
You can also use the individual Flutter widgets:
import 'package:flutter/material.dart';
import 'package:meon_digilocker_sdk/meon_digilocker_sdk.dart';
class CustomDigilockerForm extends StatefulWidget {
@override
_CustomDigilockerFormState createState() => _CustomDigilockerFormState();
}
class _CustomDigilockerFormState extends State<CustomDigilockerForm> {
final sdk = MeonDigilockerSDK(
companyName: 'democapital',
secretToken: 'cy7Kw2rWqdzVo2KPxlU0ymd9uRQKPSsb',
);
List<IssuerDetail> issuers = [];
IssuerDetail? selectedIssuer;
DocumentInfo? selectedDocument;
List<DocumentField> fields = [];
Map<String, String> fieldValues = {};
@override
void initState() {
super.initState();
_loadIssuers();
}
Future<void> _loadIssuers() async {
try {
final tokenResponse = await sdk.getAccessToken();
final response = await sdk.getListOfIssuersInDetail(
GetListOfIssuersInDetailParams(
clientToken: tokenResponse.clientToken,
state: tokenResponse.state,
search: 'insurance',
),
);
setState(() {
issuers = response.results;
});
} catch (e) {
print('Error loading issuers: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Custom DigiLocker Form')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
// Issuer Selection
if (issuers.isNotEmpty)
DropdownButtonFormField<IssuerDetail>(
value: selectedIssuer,
hint: Text('Select Issuer'),
items: issuers.map((issuer) {
return DropdownMenuItem(
value: issuer,
child: Text(issuer.name),
);
}).toList(),
onChanged: (issuer) {
setState(() {
selectedIssuer = issuer;
selectedDocument = null;
fields = [];
fieldValues = {};
});
},
),
// Document Selection
if (selectedIssuer != null)
DocumentDropdown(
documents: selectedIssuer!.documentsInfo,
onSelect: (document) {
setState(() {
selectedDocument = document;
fields = document!.requiredParameters;
fieldValues = {};
});
// Initialize field values
document!.requiredParameters.forEach((field) {
fieldValues[field.paramname] = '';
});
},
placeholder: 'Select a document...',
),
// Dynamic Form Fields
if (selectedDocument != null && fields.isNotEmpty)
DynamicFormFields(
fields: fields,
values: fieldValues,
onChanged: (values) {
setState(() {
fieldValues = values;
});
},
),
// Submit Button
if (selectedDocument != null && fields.isNotEmpty)
ElevatedButton(
onPressed: () async {
// Handle form submission
print('Submitting with values: $fieldValues');
},
child: Text('Submit & Verify'),
),
],
),
),
);
}
}
API Reference
MeonDigilockerSDK
Main SDK class for Meon DigiLocker integration.
Constructor
MeonDigilockerSDK({
required String companyName,
required String secretToken,
Duration timeout = const Duration(seconds: 30),
});
companyName(required): Your company namesecretToken(required): Your secret tokentimeout: Request timeout duration (default: 30 seconds)
Methods
getAccessToken()
Get access token and state for authentication.
GetAccessTokenResponse response = await sdk.getAccessToken();
// Returns: { clientToken, state, status }
getListOfIssuersInDetail(params)
Search for available document issuers.
GetListOfIssuersInDetailResponse response = await sdk.getListOfIssuersInDetail(
GetListOfIssuersInDetailParams(
clientToken: 'token',
state: 'state',
search: 'insurance',
page: 1,
),
);
generateDigiUrl(params)
Create URL for DigiLocker document verification flow.
GenerateDigiUrlResponse response = await sdk.generateDigiUrl(
GenerateDigiUrlParams(
clientToken: 'token',
redirectUrl: 'https://your-app.com/callback',
companyName: 'company',
otherDocuments: [...],
),
);
sendEntireData(params)
Retrieve final document data after verification.
SendEntireDataResponse response = await sdk.sendEntireData(
SendEntireDataParams(
clientToken: 'token',
state: 'state',
status: true,
),
);
Flutter Widgets
DigilockerForm
Complete form component that handles the entire document verification flow.
Props:
companyName(required): Your company namesecretToken(required): Your secret tokenredirectUrl: Redirect URL after verificationonSuccess: Callback when verification succeedsonError: Callback when an error occursprimaryColor: Primary color for themingbackgroundColor: Background colorloadingColor: Loading indicator color
DocumentDropdown
Searchable dropdown for selecting documents.
Props:
documents(required): List of documents to displayonSelect: Callback when document is selectedplaceholder: Placeholder textdisabled: Whether the dropdown is disabledprimaryColor: Primary color for theming
DynamicFormFields
Dynamic form fields based on document selection.
Props:
fields(required): List of field definitionsvalues(required): Current field valuesonChanged(required): Callback when values changeshowLabels: Whether to show field labels (default: true)primaryColor: Primary color for theming
Data Models
DocumentField
Represents a form field for document input.
DocumentInfo
Contains document information including required parameters.
IssuerDetail
Contains issuer information and available documents.
SendEntireDataResponse
Contains the final verification data including Aadhaar, PAN, and other document details.
Validation
The SDK includes comprehensive validation:
- Company name and secret token validation
- Client token and state validation
- Document field validation
- API response validation
All methods throw descriptive Exception objects if validation fails.
Error Handling
All API methods throw exceptions that can be caught:
try {
final response = await sdk.getAccessToken();
} catch (e) {
print('Error: $e');
// Handle the error appropriately
}
Example App
Check out the example/ directory for a complete Flutter app demonstrating all features of the SDK.
Run the example:
cd example
flutter run
License
MIT License - see LICENSE file for details.
Support
For issues and questions, please contact support or create an issue on GitHub.
Libraries
- meon_digilocker_sdk
- Meon DigiLocker SDK for Flutter
- models/models
- services/meon_digilocker_sdk
- widgets/digilocker_form
- widgets/document_dropdown
- widgets/dynamic_form_fields