videokyc_flutter 1.5.1
videokyc_flutter: ^1.5.1 copied to clipboard
A Flutter SDK for integrating SurePass Video KYC verification.
example/lib/main.dart
// Minimal example for the SurePass Video KYC Flutter SDK.
//
// Replace `your_surepass_api_token` and `your_workflow_id` with your SurePass
// credentials, then run the app. See the package README for the required
// Android/iOS platform setup (manifest permissions, Info.plist keys, and the
// permission_handler Podfile macros).
//
// This example also shows how to pass an optional selfie image: the app
// picks it (via `image_picker`, from the gallery or camera) and hands the
// raw bytes to the SDK, which base64-encodes them and sends them as
// `advance_parameters.user_image`. Picking from the gallery on iOS requires
// adding `NSPhotoLibraryUsageDescription` to Info.plist — see this example's
// own README.
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:videokyc_flutter/videokyc_flutter.dart';
void main() => runApp(const ExampleApp());
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video KYC Example',
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _status = 'Not started';
Uint8List? _userImageBytes;
Future<void> _pickImage(ImageSource source) async {
final picked = await ImagePicker().pickImage(
source: source,
imageQuality: 85,
);
if (picked == null) return;
final bytes = await picked.readAsBytes();
if (!mounted) return;
setState(() => _userImageBytes = bytes);
}
Future<void> _startKyc() async {
final messenger = ScaffoldMessenger.of(context);
final result = await startSurepassVideoKyc(
context: context,
token: 'your_surepass_api_token',
env: Env.sandbox, // or Env.prod
workflowId: 'your_workflow_id',
// These three are optional — drop any you don't collect and the SDK
// sends a placeholder in its place, since the API requires all three.
email: 'user@example.com',
fullName: 'John Doe',
mobileNumber: '9876543210', // 10-digit number, no country-code prefix
userImage: _userImageBytes, // optional selfie, picked below
onInitialized: (VideoKycModel model) {
debugPrint(
'Initialized: user=${model.userId} session=${model.sessionId}');
},
);
final outcome = switch (result?.status) {
VideoKycStatus.success => 'success (session ${result!.sessionId})',
VideoKycStatus.cancelled => 'cancelled by the user',
VideoKycStatus.failed => 'failed',
VideoKycStatus.error => 'error: ${result!.errorMessage}',
null => 'dismissed before a terminal status',
};
if (!mounted) return;
setState(() => _status = outcome);
messenger.showSnackBar(SnackBar(content: Text('Result: $outcome')));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Video KYC Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Status: $_status'),
const SizedBox(height: 16),
if (_userImageBytes != null) ...[
ClipOval(
child: Image.memory(
_userImageBytes!,
width: 96,
height: 96,
fit: BoxFit.cover,
),
),
TextButton(
onPressed: () => setState(() => _userImageBytes = null),
child: const Text('Remove photo'),
),
] else
const Text('No selfie selected (optional)'),
const SizedBox(height: 8),
Row(
mainAxisSize: MainAxisSize.min,
children: [
OutlinedButton.icon(
onPressed: () => _pickImage(ImageSource.camera),
icon: const Icon(Icons.camera_alt_outlined),
label: const Text('Camera'),
),
const SizedBox(width: 8),
OutlinedButton.icon(
onPressed: () => _pickImage(ImageSource.gallery),
icon: const Icon(Icons.photo_library_outlined),
label: const Text('Gallery'),
),
],
),
const SizedBox(height: 16),
FilledButton(
onPressed: _startKyc,
child: const Text('Start Video KYC'),
),
],
),
),
);
}
}