digified_flutter_plugin 0.0.30
digified_flutter_plugin: ^0.0.30 copied to clipboard
Flutter plugin for Digified's Arabic eKYC and eContract SDKs. Provides native flows for identity verification and electronic contract signing with updated Android integration (FlutterActivity + Hilt) [...]
example/lib/main.dart
import 'dart:convert';
import 'package:digified_flutter_plugin/digified_flutter_plugin.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'testing_profiles/models/test_profile.dart';
import 'testing_profiles/storage/profile_store.dart';
import 'testing_profiles/ui/profile_management_page.dart';
import 'testing_profiles/ui/profile_picker_sheet.dart';
// This file keeps concise, customer-facing API examples.
// The tester tooling UI is implemented under lib/app and lib/testing_profiles.
class DigifiedApiExamples {
const DigifiedApiExamples._();
static Future<String?> presentEkyc({
required String apiKey,
required String baseUrl,
}) async {
try {
return await DigifiedFlutterPlugin.presentEKYC(
apiKey: apiKey,
baseUrl: baseUrl,
);
} on PlatformException {
rethrow;
}
}
static Future<void> presentEcontract({
required String apiKey,
required String baseUrl,
required String faceMatchingApiKey,
required String faceMatchingBaseUrl,
required String eKYCSessionID,
required String templateVersionID,
required Map<String, String> variables,
}) async {
try {
await DigifiedFlutterPlugin.presentEContract(
apiKey: apiKey,
baseUrl: baseUrl,
faceMatchingApiKey: faceMatchingApiKey,
faceMatchingBaseUrl: faceMatchingBaseUrl,
eKYCSessionID: eKYCSessionID,
templateVersionID: templateVersionID,
variables: variables,
);
} on PlatformException {
rethrow;
}
}
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MainApp());
}
class MainApp extends StatefulWidget {
const MainApp({super.key});
@override
State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
static const _languageKey = 'app_language';
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
final GlobalKey<ScaffoldMessengerState> _scaffoldMessengerKey =
GlobalKey<ScaffoldMessengerState>();
Locale _locale = const Locale('en');
ProfileStore? _store;
String t(String en, String ar) => _locale.languageCode == 'ar' ? ar : en;
@override
void initState() {
super.initState();
_initialize();
}
Future<void> _initialize() async {
await _loadStoreAndLanguage();
await _initSdk();
}
Future<void> _loadStoreAndLanguage() async {
final store = await ProfileStore.create();
final prefs = await SharedPreferences.getInstance();
final localeCode = prefs.getString(_languageKey) ?? 'en';
try {
await DigifiedFlutterPlugin.setLanguage(localeCode);
} catch (_) {}
if (!mounted) return;
setState(() {
_store = store;
_locale = Locale(localeCode);
});
}
Future<void> _initSdk() async {
try {
await DigifiedFlutterPlugin.setLoggingEnabled(true);
} catch (_) {}
}
Future<void> _toggleLanguage() async {
final newLang = _locale.languageCode == 'ar' ? 'en' : 'ar';
try {
await DigifiedFlutterPlugin.setLanguage(newLang);
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_languageKey, newLang);
if (!mounted) return;
setState(() {
_locale = Locale(newLang);
});
} catch (e) {
_showMessage('Failed to set language: $e');
}
}
Future<void> _launchEkyc() async {
final profile = await _pickProfileForFlow(FlowType.ekyc);
if (profile == null) return;
if (!profile.hasEkyc) {
_showMessage('Selected profile is not configured for eKYC.');
return;
}
if (!_hasRequiredFields(
profile.ekyc.fields,
const ['apiKey', 'baseUrl'],
flowName: 'eKYC',
)) {
return;
}
try {
final ekycSessionId = await DigifiedFlutterPlugin.presentEKYC(
apiKey: profile.ekyc.value('apiKey'),
baseUrl: profile.ekyc.value('baseUrl'),
);
_showMessage('eKYC completed. Session ID: $ekycSessionId');
} on PlatformException catch (e) {
_showMessage('eKYC failed: ${e.message}');
} catch (e) {
_showMessage('eKYC error: $e');
}
}
Future<void> _launchEcontract() async {
final profile = await _pickProfileForFlow(FlowType.econtract);
if (profile == null) return;
if (!profile.hasEcontract) {
_showMessage('Selected profile is not configured for eContract.');
return;
}
if (!_hasRequiredFields(
profile.econtract.fields,
const [
'apiKey',
'baseUrl',
'faceMatchingApiKey',
'faceMatchingBaseUrl',
'eKYCSessionID',
'templateVersionID',
'variables',
],
flowName: 'eContract',
)) {
return;
}
final variables = _parseVariables(profile.econtract.value('variables'));
if (variables == null) {
_showMessage('Invalid eContract variables JSON. Use object format.');
return;
}
try {
await DigifiedFlutterPlugin.presentEContract(
apiKey: profile.econtract.value('apiKey'),
baseUrl: profile.econtract.value('baseUrl'),
faceMatchingApiKey: profile.econtract.value('faceMatchingApiKey'),
faceMatchingBaseUrl: profile.econtract.value('faceMatchingBaseUrl'),
eKYCSessionID: profile.econtract.value('eKYCSessionID'),
templateVersionID: profile.econtract.value('templateVersionID'),
variables: variables,
);
_showMessage('eContract completed successfully');
} on PlatformException catch (e) {
_showMessage('eContract failed: ${e.message}');
} catch (e) {
_showMessage('eContract error: $e');
}
}
Map<String, String>? _parseVariables(String input) {
try {
final decoded = jsonDecode(input);
if (decoded is! Map) return null;
return decoded.map(
(key, value) => MapEntry(key.toString(), value?.toString() ?? ''),
);
} catch (_) {
return null;
}
}
bool _hasRequiredFields(
Map<String, String> fields,
List<String> requiredKeys, {
required String flowName,
}) {
for (final key in requiredKeys) {
if ((fields[key] ?? '').trim().isEmpty) {
_showMessage('$flowName is missing required field: $key');
return false;
}
}
return true;
}
Future<TestProfile?> _pickProfileForFlow(FlowType flowType) async {
final store = _store;
if (store == null) return null;
final navContext = _navigatorKey.currentContext;
if (navContext == null) return null;
var profiles = store.readProfiles();
profiles = profiles.where((profile) {
if (flowType == FlowType.ekyc) return profile.hasEkyc;
return profile.hasEcontract;
}).toList();
if (profiles.isEmpty) {
_showMessage(
flowType == FlowType.ekyc
? 'No eKYC profiles configured. Use Manage to add one.'
: 'No eContract profiles configured. Use Manage to add one.',
);
return null;
}
final result = await ProfilePickerSheet.show(
navContext,
flowType: flowType,
profiles: profiles,
defaultProfileId: store.getDefaultProfileId(flowType),
onManageProfiles: () async {
await _openProfileManagement();
return store.readProfiles();
},
);
if (result == null) return null;
if (result.makeDefault) {
await store.setDefaultProfileId(flowType, result.profile.id);
}
profiles = store.readProfiles();
return profiles.firstWhere(
(p) => p.id == result.profile.id,
orElse: () => profiles.first,
);
}
Future<void> _openProfileManagement() async {
final store = _store;
if (store == null) return;
final navigator = _navigatorKey.currentState;
if (navigator == null) return;
await navigator.push(
MaterialPageRoute(
builder: (_) => ProfileManagementPage(store: store),
),
);
if (mounted) {
setState(() {});
}
}
void _showMessage(String message) {
if (!mounted) return;
_scaffoldMessengerKey.currentState?.showSnackBar(
SnackBar(content: Text(message)),
);
}
@override
Widget build(BuildContext context) {
final isReady = _store != null;
return MaterialApp(
navigatorKey: _navigatorKey,
scaffoldMessengerKey: _scaffoldMessengerKey,
locale: _locale,
supportedLocales: const [Locale('en'), Locale('ar')],
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
localeResolutionCallback: (locale, supportedLocales) {
if (locale == null) return supportedLocales.first;
for (final supported in supportedLocales) {
if (supported.languageCode == locale.languageCode) {
return supported;
}
}
return supportedLocales.first;
},
home: Scaffold(
appBar: AppBar(
title: Text(t('Digified Demo', 'عرض ديجيفايد')),
actions: [
IconButton(
onPressed: isReady ? _openProfileManagement : null,
tooltip: 'Manage test profiles',
icon: const Icon(Icons.tune),
),
],
),
body: Center(
child: isReady
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _launchEkyc,
child: Text(t('Launch eKYC', 'بدء التحقق')),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _launchEcontract,
child: Text(t('Launch eContract', 'بدء العقد الإلكتروني')),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _toggleLanguage,
child:
Text(t('Switch to Arabic', 'التبديل إلى الإنجليزية')),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
try {
await DigifiedFlutterPlugin.openAppSettings();
} catch (e) {
_showMessage('Failed to open app settings: $e');
}
},
child: Text(t('Open App Settings', 'فتح إعدادات التطبيق')),
),
],
)
: const CircularProgressIndicator(),
),
),
);
}
}