Flutter身份验证插件inapp_flutter_kyc的使用
Flutter身份验证插件inapp_flutter_kyc的使用
简介
inapp_flutter_kyc
是一个强大且易于使用的插件,为您的Flutter应用程序带来了必要的“了解您的客户”(KYC)功能。
功能
- 活体检测:通过设备摄像头进行实时活体检测,确保用户在KYC过程中实际存在,防止欺诈企图。
- 身份证扫描:利用先进的计算机视觉技术从护照、驾照、国家身份证等官方识别文件中提取信息,加速KYC过程。
- 面部匹配:通过比较扫描身份证图像和用户提供的自拍图像之间的面部特征来增强身份验证。
- 可定制UI:根据您应用的品牌和设计无缝定制用户界面。可以自定义颜色、字体和布局,以创建一致的用户体验。
- 隐私和安全:优先考虑用户的隐私和安全。该插件实施了行业标准的安全措施,以保护KYC过程中的敏感用户数据。
开始使用
要开始使用 inapp_flutter_kyc
插件,请按照以下简单步骤操作:
-
添加插件到项目中:
flutter pub add inapp_flutter_kyc
-
对于Android平台:
- 在
android/app/src/main/AndroidManifest.xml
文件中的<application></application>
标签之前添加以下内容:<uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-permission android:name="android.permission.CAMERA" />
- 在
<activity>
标签中添加:android:requestLegacyExternalStorage="true"
- 在
android/app/build.gradle
中设置minSdkVersion
为 23:defaultConfig { minSdkVersion 23 }
- 在
android/build.gradle
中将 kotlin 版本设置为 1.8.0:buildscript { ext.kotlin_version = '1.8.0' }
- 在
身份证扫描
对于身份证扫描,有两种情况需要考虑:关键字和值在同一行(如图1所示)和关键字与值在下一行(如图2所示)。
在 EkycServices().openImageScanner()
函数中,传递关键字名称和布尔值:
- 如果关键字和值在同一行,则传递
true
- 如果关键字和值不在同一行,则传递
false
例如:
Map<String, bool> keyWordData = {
'Name': false,
'Date of Birth': true,
'NID No': false
};
现在将 keyWordData
传递给 EkycServices().openImageScanner()
:
ExtractedDataFromId? extractedDataFromId;
extractedDataFromId = await EkycServices().openImageScanner(keyWordData);
ExtractedDataFromId
还包含 extractedText
。如果OCR文本没有从这些情况解析出来,您也可以从 extractedText
操作文本。
面部匹配
为了运行面部匹配,请执行以下步骤:
- 下载并解压相关文件夹。
- 在文件夹目录中运行以下命令(针对Ubuntu):
python3 face_match.py
- 对于Windows:
python face_match.py
- 您将在控制台中看到类似以下输出:
* Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:5000 * Running on http://10.0.3.50:5000
- 复制最后一个地址(例如
http://10.0.3.50:5000
),并在EkycServices().runFaceMatch
函数中传递它以及两个图片路径(自拍照和身份证照片):await EkycServices().runFaceMatch("http://10.0.3.50:5000", selfieImage?.path, imageAndText?.imagePath);
完整示例Demo
以下是完整的示例代码,展示了如何使用 inapp_flutter_kyc
插件进行活体检测、身份证扫描和面部匹配:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:inapp_flutter_kyc/inapp_flutter_kyc.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'EKYC Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File? selfieImage;
ExtractedDataFromId? extractedDataFromId;
bool? isMatchFace;
bool isloading = false;
bool faceMatchButtonPressed = false;
Map<String, bool> keyWordData = {
'Name': false,
'Date of Birth': true,
'NID No': false
};
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 活体检测按钮
TextButton(
onPressed: () {
EkycServices().livenessDetct().then((result) {
if (result != null) {
print("File path: $result");
setState(() {
selfieImage = result;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ShowImage(selfieImage: selfieImage)),
);
});
} else {
print("Liveness detection failed.");
}
}).catchError((error) {
print("Error occurred during liveness detection: $error");
});
},
style: TextButton.styleFrom(
foregroundColor: Colors.white,
padding: const EdgeInsets.all(16.0),
backgroundColor: Colors.blue,
elevation: 9.0,
textStyle: const TextStyle(fontSize: 20),
),
child: Text("活体检测"),
),
SizedBox(height: 10),
// 扫描身份证按钮
TextButton(
onPressed: () async {
extractedDataFromId =
await EkycServices().openImageScanner(keyWordData);
if (extractedDataFromId?.extractedText != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ShowScannedText(
scannedText: extractedDataFromId!.extractedText!,
keyNvalue: extractedDataFromId?.keywordNvalue,
)),
);
}
},
style: TextButton.styleFrom(
foregroundColor: Colors.white,
padding: const EdgeInsets.all(16.0),
backgroundColor: Colors.blue,
elevation: 9.0,
textStyle: const TextStyle(fontSize: 20),
),
child: Text("扫描你的身份证"),
),
SizedBox(height: 10),
// 面部匹配按钮
TextButton(
onPressed: () async {
if (selfieImage == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('请先使用活体检测拍摄一张自拍照'),
duration: Duration(seconds: 3),
),
);
} else if (extractedDataFromId?.imagePath == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('身份证上没有检测到人脸'),
duration: Duration(seconds: 3),
),
);
} else {
isloading = true;
setState(() {
faceMatchButtonPressed = true;
});
isMatchFace = await EkycServices().runFaceMatch(
"http://10.255.187.82:5000",
selfieImage?.path,
extractedDataFromId?.imagePath);
setState(() {
isloading = false;
});
}
},
style: TextButton.styleFrom(
foregroundColor: Colors.white,
padding: const EdgeInsets.all(16.0),
backgroundColor: Colors.blue,
elevation: 9.0,
textStyle: const TextStyle(fontSize: 20),
),
child: Text("将身份证与自拍照进行面部匹配")),
Visibility(
visible: faceMatchButtonPressed,
child: Container(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15))),
color: Color(0xFFe3e6f5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 10),
(isloading == true)
? SizedBox(
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor:
AlwaysStoppedAnimation(Colors.white),
),
height: 50.0,
width: 50.0,
)
: (isMatchFace == true)
? Icon(
Icons.check_circle_sharp,
size: 40,
color: Color(0xFF9677eca),
)
: Transform.rotate(
angle: 45 * pi / 180,
child: Icon(
Icons.add_circle,
size: 40,
color: Colors.red,
),
),
SizedBox(width: 5),
Expanded(
child: Text(
(isloading == true)
? ' 正在运行面部匹配...'
: (isMatchFace == true)
? "成功!身份证与自拍照匹配"
: (isMatchFace == false)
? "出错了!请重试!"
: '身份证与自拍照不匹配',
maxLines: 3,
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 17,
height: 1.5,
fontWeight: FontWeight.w400)),
),
const SizedBox(width: 10),
],
),
SizedBox(height: 20),
],
),
),
),
),
],
),
),
);
}
}
class ShowImage extends StatelessWidget {
File? selfieImage;
ShowImage({this.selfieImage});
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("活体检测成功!"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.file(selfieImage!),
SizedBox(height: 20),
TextButton(
onPressed: () {
Navigator.pop(context);
},
style: TextButton.styleFrom(
foregroundColor: Colors.white,
padding: const EdgeInsets.all(16.0),
backgroundColor: Colors.blue,
elevation: 9.0,
textStyle: const TextStyle(fontSize: 20),
),
child: Text("重新拍摄"),
),
],
),
),
);
}
}
class FormFieldData {
final String label;
String value;
FormFieldData({required this.label, required this.value});
}
class ShowScannedText extends StatefulWidget {
String scannedText;
Map<String, dynamic>? keyNvalue;
ShowScannedText({required this.scannedText, this.keyNvalue});
[@override](/user/override)
State<ShowScannedText> createState() => _ShowScannedTextState();
}
class _ShowScannedTextState extends State<ShowScannedText> {
List<FormFieldData> formFields = [];
[@override](/user/override)
void initState() {
super.initState();
if (widget.keyNvalue != null) {
widget.keyNvalue?.forEach((key, value) {
formFields.add(FormFieldData(label: key, value: value.toString()));
});
}
print(widget.keyNvalue);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("已扫描文本"),
),
body: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Visibility(
visible: widget.keyNvalue != null,
child: Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: formFields.length,
itemBuilder: (context, index) {
FormFieldData fieldData = formFields[index];
return Padding(
padding: EdgeInsets.all(16),
child: TextFormField(
initialValue: fieldData.value,
decoration: InputDecoration(labelText: fieldData.label),
onChanged: (value) {
formFields[index].value = value;
},
),
);
},
),
),
),
Text("完整提取文本", style: TextStyle(fontSize: 20)),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Text(widget.scannedText),
),
],
),
);
}
}
更多关于Flutter身份验证插件inapp_flutter_kyc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter身份验证插件inapp_flutter_kyc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 inapp_flutter_kyc
插件进行身份验证的示例代码。这个插件通常用于在Flutter应用中实现用户身份验证流程,特别是“了解你的客户”(KYC)流程。以下示例假设你已经在 pubspec.yaml
文件中添加了 inapp_flutter_kyc
依赖,并且已经运行了 flutter pub get
。
1. 安装依赖
首先,确保你的 pubspec.yaml
文件包含以下依赖:
dependencies:
flutter:
sdk: flutter
inapp_flutter_kyc: ^最新版本号 # 请替换为实际最新版本号
然后运行 flutter pub get
。
2. 导入插件并初始化
在你的 Dart 文件中导入插件:
import 'package:flutter/material.dart';
import 'package:inapp_flutter_kyc/inapp_flutter_kyc.dart';
3. 配置插件
在你的应用初始化时,配置 InAppFlutterKyc
插件。这通常在你的 main.dart
文件中完成。
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化插件,这里需要替换为你的实际配置信息
InAppFlutterKyc.initialize(
apiKey: '你的API_KEY',
environment: 'sandbox', // 或 'production'
clientUserId: '用户唯一标识符', // 例如用户ID
onKYCCompleted: (result) {
// KYC流程完成后的回调
print('KYC completed with result: $result');
},
onError: (error) {
// 错误回调
print('KYC error: $error');
},
);
runApp(MyApp());
}
4. 启动KYC流程
在你的应用中的某个按钮点击事件中启动KYC流程:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('KYC Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
try {
// 启动KYC流程
await InAppFlutterKyc.startKYC();
} catch (e) {
// 处理异常
print('Error starting KYC: $e');
}
},
child: Text('Start KYC'),
),
),
),
);
}
}
5. 处理回调
在 main
函数中,我们已经设置了 onKYCCompleted
和 onError
回调。这些回调将在KYC流程完成或出现错误时被调用。
注意事项
- 确保你已经从
inapp_flutter_kyc
的服务提供者那里获得了正确的apiKey
和其他必要的配置信息。 - 在生产环境中,请确保将
environment
设置为'production'
。 - 根据你的业务需求,你可能需要在用户完成KYC后更新你的用户数据或执行其他操作。
这个示例提供了一个基本框架,你可以根据实际需求进一步定制和扩展。