腾讯云 人脸核身 Flutter 插件功能开发(一 IOS 端实现)

86 阅读4分钟

前言

项目中需要使用到 腾讯云的人脸核身功能,但是官方没有提供对应的flutter plugin ,所以需要我们自己构建一个flutter plugin ,用于实现IOS 端人脸核身功能

  1. 进入官方网站,下载 SDK 工具包

  2. 创建 tencent_cloud_face_verify 插件

  3. 在Plugin 的 ios 目录中 创建Framework 文件夹,将第一步中SDK 中的 TencentCloudHuiyanSDKFace_framework 放置到 Framework 文件夹中

  4. 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
  1. Classes目录中创建OC和Swift 的桥接文件(因为人脸核身库使用OC 开发的,Swift 调用需要桥接文件指定.h头文件才能在Swift中正常调用OC 函数) TencentCloudFaceVerifyPlugin-Bridging-Header.h
#import <TencentCloudHuiyanSDKFace/WBFaceVerifyCustomerService.h>
  1. 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")
//  }
}
  1. 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.');

  }
}
  1. 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,
    });
  }
}
  1. 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,
    );
  }
}
  1. 使用方式
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("拉起实名认证")),
        ],
      ),
    );
  }
}