腾讯云 人脸核身 Flutter 插件功能开发(一 IOS 端实现)
前言
项目中需要使用到 腾讯云的人脸核身功能,但是官方没有提供对应的flutter plugin ,所以需要我们自己构建一个flutter plugin ,用于实现IOS 端人脸核身功能,plugin 插件地址github.com/qiangzengli…
-
进入官方网站,下载 SDK 工具包
-
创建 tencent_cloud_face_verify 插件
-
在Plugin 的 ios 目录中 创建Framework 文件夹,将第一步中SDK 中的 TencentCloudHuiyanSDKFace_framework 放置到 Framework 文件夹中
-
Plugin 中 tencent_cloud_face_verify.podspec文件引入Framework tencent_cloud_face_verify.podspec
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint tencent_cloud_face_verify.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'tencent_cloud_face_verify'
s.version = '0.0.1'
s.summary = 'A new Flutter plugin project.'
s.description = <<-DESC
A new Flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
#.framework文件路径
s.vendored_frameworks = 'Framework/TencentCloudHuiyanSDKFace_framework/Libs/*framework'
#.bundle资源文件路径
# 推荐方式 - 创建独立的资源bundle
# s.resource_bundles = {
# 'TencentCloudFaceVerifyPluginResources' => ['Framework/TencentCloudHuiyanSDKFace_framework/Resources/*bundle']
}
s.ios.resource = 'Framework/TencentCloudHuiyanSDKFace_framework/Resources/*bundle'
# s.resource = ['Framework/TencentCloudHuiyanSDKFace_framework/Resources/*.bundle']
# s.resource_bundles ='Framework/TencentCloudHuiyanSDKFace_framework/Resources/*.bundle'
# s.resource_bundles = {
# 'TencentCloudHuiyanSDKFace' => ['Framework/TencentCloudHuiyanSDKFace_framework/Resources/*bundle']
# }
#swift _oc Header 桥接文件
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.platform = :ios, '12.0'
# 1. 添加所有腾讯云认证需要的系统 Framework
s.frameworks = [
'UIKit',
'AVFoundation',
'CoreVideo',
'Security',
'SystemConfiguration',
'CoreMedia',
'CoreTelephony',
'ImageIO',
'VideoToolbox',
'Accelerate',
'WebKit' # 注意:WebKit.framework(不是 webkit.framework)
]
# 2. 添加腾讯云认证需要的系统库(.tbd)
s.libraries = 'c++', 'z' # libc++.tbd 和 libz.tbd
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
# If your plugin requires a privacy manifest, for example if it uses any
# required reason APIs, update the PrivacyInfo.xcprivacy file to describe your
# plugin's privacy impact, and then uncomment this line. For more information,
# see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
# s.resource_bundles = {'tencent_cloud_face_verify_privacy' => ['Framework/Resources/PrivacyInfo.xcprivacy']}
end
- Classes目录中创建OC和Swift 的桥接文件(因为人脸核身库使用OC 开发的,Swift 调用需要桥接文件指定.h头文件才能在Swift中正常调用OC 函数) TencentCloudFaceVerifyPlugin-Bridging-Header.h
#import <TencentCloudHuiyanSDKFace/WBFaceVerifyCustomerService.h>
- TencentCloudFaceVerifyPlugin.swift
import Flutter
import UIKit
public class TencentCloudFaceVerifyPlugin: NSObject, FlutterPlugin, WBFaceVerifyCustomerServiceDelegate {
private var flutterResult: FlutterResult?
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "tencent_cloud_face_verify", binaryMessenger: registrar.messenger())
let instance = TencentCloudFaceVerifyPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
case "launchVerify":
self.flutterResult = result
if let dict = call.arguments as? Dictionary<String, String?> {
let userId:String = dict["userId"] as? String ?? ""
let sign:String = dict["sign"] as? String ?? ""
let appId:String = dict["appId"] as? String ?? ""
let orderNo:String = dict["orderNo"] as? String ?? ""
let apiVersion:String = dict["apiVersion"] as? String ?? ""
let licence:String = dict["licence"] as? String ?? ""
let faceId:String = dict["faceId"] as? String ?? ""
let nonce:String = dict["nonce"] as? String ?? ""
let config = WBFaceVerifySDKConfig()
config.theme = WBFaceVerifyTheme.lightness
config.language = WBFaceVerifyLanguage.ZH_CN
// 设置 bundlePath
if let bundlePath = Bundle(for: TencentCloudFaceVerifyPlugin.self).path(forResource: "TencentCloudHuiyanSDKFace", ofType: "bundle") {
config.bundlePath = (bundlePath as NSString).deletingLastPathComponent
print("Successfully set bundlePath: (config.bundlePath)")
}
// 设置代理
WBFaceVerifyCustomerService.sharedInstance().delegate = self
WBFaceVerifyCustomerService.sharedInstance().initSDK(withUserId: userId, nonce: nonce, sign: sign, appid: appId, orderNo: orderNo, apiVersion: apiVersion, licence: licence, faceId: faceId,sdkConfig: config) {
DispatchQueue.main.async {
WBFaceVerifyCustomerService.sharedInstance().startWbFaceVeirifySdk()
}
} failure: { error in
// print("SDK initialization failed: (error.domain), code: (error.code), description: (error.localizedDescription)")
// self.flutterResult?(FlutterError(code: String(error.code),
// message: error.localizedDescription,
// details: error.domain))
}
}
default:
result(FlutterMethodNotImplemented)
}
}
// MARK: - WBFaceVerifyCustomerServiceDelegate Methods
public func wbfaceVerifyCustomerServiceDidFinished(with result: WBFaceVerifyResult) {
// 人脸验证完成的回调
if result.isSuccess {
// 验证成功
let resultDict: [String: Any] = [
"success": true,
"orderNo": result.orderNo ?? "",
"sign": result.sign ?? "",
"isSuccess": result.isSuccess
]
self.flutterResult?(resultDict)
} else {
// 验证失败
let resultDict: [String: Any] = [
"success": false,
"orderNo": result.orderNo ?? "",
"sign": result.sign ?? "",
"isSuccess": result.isSuccess
]
self.flutterResult?(resultDict)
}
}
// // 可选:添加即将上传最佳照片的回调
// public func wbfaceVerifyCustomerServiceWillUploadBestImage(_ bestImage: UIImage) {
// print("Will upload best image")
// }
}
- tencent_cloud_face_verify_platform_interface.dart
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'tencent_cloud_face_verify_method_channel.dart';
abstract class TencentCloudFaceVerifyPlatform extends PlatformInterface {
/// Constructs a TencentCloudFaceVerifyPlatform.
TencentCloudFaceVerifyPlatform() : super(token: _token);
static final Object _token = Object();
static TencentCloudFaceVerifyPlatform _instance = MethodChannelTencentCloudFaceVerify();
/// The default instance of [TencentCloudFaceVerifyPlatform] to use.
///
/// Defaults to [MethodChannelTencentCloudFaceVerify].
static TencentCloudFaceVerifyPlatform get instance => _instance;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [TencentCloudFaceVerifyPlatform] when
/// they register themselves.
static set instance(TencentCloudFaceVerifyPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Future<String?> getPlatformVersion() {
throw UnimplementedError('platformVersion() has not been implemented.');
}
Future<Map<Object?, Object?>> launchVerify({
required String userId,
required String sign,
required String appId,
required String orderNo,
required String apiVersion,
required String licence,
required String faceId,
required String nonce,
}){
throw UnimplementedError('launchVerify() has not been implemented.');
}
}
- tencent_cloud_face_verify_method_channel.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'tencent_cloud_face_verify_platform_interface.dart';
/// An implementation of [TencentCloudFaceVerifyPlatform] that uses method channels.
class MethodChannelTencentCloudFaceVerify
extends TencentCloudFaceVerifyPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
final methodChannel = const MethodChannel('tencent_cloud_face_verify');
@override
Future<String?> getPlatformVersion() async {
final version =
await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
@override
Future<Map<Object?, Object?>> launchVerify({
required String userId,
required String sign,
required String appId,
required String orderNo,
required String apiVersion,
required String licence,
required String faceId,
required String nonce,
}) async {
return await methodChannel.invokeMethod('launchVerify', {
"userId": userId,
"sign": sign,
"appId": appId,
"orderNo": orderNo,
"apiVersion": apiVersion,
"licence": licence,
"faceId": faceId,
"nonce": nonce,
});
}
}
- tencent_cloud_face_verify.dart
import 'tencent_cloud_face_verify_platform_interface.dart';
class TencentCloudFaceVerify {
Future<Map<Object?, Object?>> launchVerify({
required String userId,
required String sign,
required String appId,
required String orderNo,
required String apiVersion,
required String licence,
required String faceId,
required String nonce,
}) {
return TencentCloudFaceVerifyPlatform.instance.launchVerify(
userId: userId,
sign: sign,
appId: appId,
orderNo: orderNo,
apiVersion: apiVersion,
licence: licence,
faceId: faceId,
nonce: nonce,
);
}
}
- 使用方式
import 'package:flutter/material.dart';
import 'package:tencent_cloud_face_verify/tencent_cloud_face_verify.dart';
class VerifyPage extends StatefulWidget {
const VerifyPage({super.key});
@override
State<VerifyPage> createState() => _VerifyPageState();
}
class _VerifyPageState extends State<VerifyPage> {
final TencentCloudFaceVerify tencentCloudFaceVerify =
TencentCloudFaceVerify();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("实名认证"),
),
body: Column(
children: [
TextButton(
onPressed: () async {
final Map<String, String> a = {"orderNo":"orderNum0000000001","appId":"TIDAuFAT","sign":"39299F4E10C61481A30CE4B7E257BE1467DA72C7","faceId":"tx011818046f90367f8413489ebfe270","version":"1.0.0","nonce":"pok0utbgOyTY5k71bI1DUk1DnHuSGOvD","userId":"userId000000000001"};
final Map<Object?, Object?> result =
await tencentCloudFaceVerify.launchVerify(
userId: a["userId"] ?? "",
sign: a["sign"] ?? "",
appId: a["appId"] ?? "",
orderNo: a["orderNo"] ?? "",
apiVersion: a["version"] ?? "",
licence:
"Q5sBOcmVygfQJjdMcItosSpbz9ivBiY4RiMPpoogd9xpOjUQk9uqkxE/w9h8yTPR8pklsNZjOXT3ikedc9UEDNHKmP2qFVc8oFQotqOu5fCTC3iFTodmJ5TQ6Mh6hjqgD+rIXBQcztoQb8EpEQc0msh9oCpFVsMp1EcU+j4OcJwR0yFkqvU+aLnXQ7mhhWX2779bTejo59+V2SeM6xrE27gdrC7J4BCgu21vCIsiX/4VmMSJp0QkQzPDHK6EeMaLsZ2Hjn5u6r05YoTR/ROh8ie5E0B0vv3Qk9Sc0J8vgnkzdEW+HUtfR/1+twbHUcwWtoPZ+cM/h5ht3xC8bD4d5Q==",
faceId: a["faceId"] ?? "",
nonce: a["nonce"] ?? "",
);
print(result.toString());
},
child: Text("拉起实名认证")),
],
),
);
}
}