项目中有实名认证的需求,用户上传身份证反正面,进行人脸核验,后台集成的是阿里云的金融级实名认证SDK,巧合的是阿里云没有packages 需要自己造轮子。
废话不多少,直接上代码:
新建项目 ProjectType = Plugin
创建完成后,会自动为我们搭建好通信结构
编写Dart中间件
在项目下的 lib下的dart文件中定义我们的通信方法。
实名认证 需要两个方法 分别是:
获取本机信息发送给服务器 返回ID
调用实名认证,以及返回结果
import 'dart:async'; import 'package:flutter/services.dart'; class AliAuthPerson { static const MethodChannel _channel = MethodChannel('ali_auth_person'); static Future<String?> get platformVersion async { final String? version = await _channel.invokeMethod('getPlatformVersion'); return version; } static const EventChannel _eventChannel = EventChannel("ali_auth_person_plugin_event"); ///认证结果返回监听 static addListen(Function(String resData) onEvent) { _eventChannel.receiveBroadcastStream().listen((data) { onEvent(data); }); } ///实名认证 static Future<void> verify(String certifyId) async { await _channel.invokeMethod("verify", certifyId); } ///获取本机参数 static Future<String> getMetaInfos() async { return await _channel.invokeMethod("getMetaInfos"); } }
Andriod 集成
参考:阿里云官方解说:https://help.aliyun.com/document_detail/163105.html
复制粘贴 AAR文件
将SDK的中的 AAR放入项目内
image.png
导入声明
dependencies { compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar") //阿里云实人认证SDK implementation(name:'android-aliyunbasicstl-sdk-release-1.6.0-20220414192835', ext:'aar') implementation(name:'android-aliyuncomm-sdk-release-1.6.0-20220414192835', ext:'aar') implementation(name:'Android-AliyunDevice-FG-10022.2', ext:'aar') implementation(name:'android-aliyunface-sdk-release-1.6.0-20220414192835', ext:'aar') implementation(name:'android-aliyunocr-sdk-release-1.6.0-20220414192835', ext:'aar') implementation(name:'APSecuritySDK-DeepSec-7.0.1.20211220', ext:'aar') implementation(name:'photinus-1.0.1.220217162928', ext:'aar') implementation(name:'tygerservice-1.0.0.220407164130', ext:'aar') //三方依赖库 implementation 'com.squareup.okhttp3:okhttp:3.11.0' implementation 'com.squareup.okio:okio:1.14.0' implementation 'com.alibaba:fastjson:1.2.62' implementation 'com.aliyun.dpa:oss-android-sdk:+' }
编写Android 适配方法
代码如下
package com.lrs.ali_auth_person.ali_auth_person; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; import androidx.annotation.NonNull; import com.aliyun.aliyunface.api.ZIMCallback; import com.aliyun.aliyunface.api.ZIMFacade; import com.aliyun.aliyunface.api.ZIMFacadeBuilder; import com.aliyun.aliyunface.api.ZIMResponse; import org.json.JSONException; import org.json.JSONObject; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry; /** * AliAuthPersonPlugin */ public class AliAuthPersonPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware { /// The MethodChannel that will the communication between Flutter and native Android /// /// This local reference serves to register the plugin with the Flutter Engine and unregister it /// when the Flutter Engine is detached from the Activity private MethodChannel channel; // 上下文 Context private Context context; private Activity activity; private EventChannel.EventSink eventSink; @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "ali_auth_person"); channel.setMethodCallHandler(this); context = flutterPluginBinding.getApplicationContext(); final EventChannel eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "ali_auth_person_plugin_event"); eventChannel.setStreamHandler(new EventChannel.StreamHandler() { @Override public void onListen(Object o, EventChannel.EventSink eventSink) { AliAuthPersonPlugin.this.eventSink = eventSink; } @Override public void onCancel(Object o) { AliAuthPersonPlugin.this.eventSink = null; } }); } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { if (call.method.equals("getPlatformVersion")) { result.success("Android " + android.os.Build.VERSION.RELEASE); } else if (call.method.equals("getMetaInfos")) { //获取本机参数 String metaInfo = ZIMFacade.getMetaInfos(context); result.success(metaInfo); } else if (call.method.equals("verify")) { //进行实名认证 String certifyId = call.arguments(); if (certifyId == null || certifyId.isEmpty()) { Toast.makeText(context, "certifyId 不能为空!", Toast.LENGTH_SHORT).show(); return; } Toast.makeText(context, "" + certifyId, Toast.LENGTH_SHORT).show(); ZIMFacade.install(context); ZIMFacade zimFacade = ZIMFacadeBuilder.create(activity); zimFacade.verify(certifyId, true, new ZIMCallback() { @Override public boolean response(ZIMResponse response) { // TODO:根据实人认证回调结果处理自身的业务。 JSONObject jsonObject = new JSONObject(); try { jsonObject.put("code", response.code); jsonObject.put("msg", response.msg); jsonObject.put("deviceToken", response.deviceToken); jsonObject.put("videoFilePath", response.videoFilePath); } catch (JSONException e) { e.printStackTrace(); } eventSink.success(jsonObject.toString()); return true; } }); } else { result.notImplemented(); } } @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { channel.setMethodCallHandler(null); } @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { activity = binding.getActivity(); } @Override public void onDetachedFromActivityForConfigChanges() { } @Override public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { } @Override public void onDetachedFromActivity() { } }
Ios集成
参考:阿里云官方解说:https://help.aliyun.com/document_detail/163106.html
复制粘贴 frameworks
image.png
导入声明
编写 .podspec文件 如下
# # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. # Run `pod lib lint ali_auth_person.podspec` to validate before publishing. # Pod::Spec.new do |s| s.name = 'ali_auth_person' s.version = '0.0.1' s.summary = 'A new Flutter project.' s.description = <<-DESC A new Flutter 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/**/*' s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' s.platform = :ios, '9.0' s.vendored_frameworks = 'frameworks/AliyunIdentityManager.framework','frameworks/AliyunOSSiOS.framework','frameworks/APBToygerFacade.framework','frameworks/APPSecuritySDK.framework','frameworks/BioAuthAPI.framework','frameworks/BioAuthEngine.framework','frameworks/deviceiOS.framework','frameworks/MPRemoteLogging.framework','frameworks/OCRDetectSDKForTech.framework','frameworks/ToygerNative.framework','frameworks/ToygerService.framework','frameworks/ZolozIdentityManager.framework','frameworks/ZolozMobileRPC.framework','frameworks/ZolozOpenPlatformBuild.framework','frameworks/ZolozSensorServices.framework','frameworks/ZolozUtility.framework' s.frameworks = 'CoreGraphics','Accelerate','SystemConfiguration','AssetsLibrary','CoreTelephony','QuartzCore','CoreFoundation','CoreLocation','ImageIO','CoreMedia','CoreMotion','AVFoundation','WebKit','AudioToolbox','CFNetwork','MobileCoreServices','AdSupport' s.libraries = 'resolv','z','c++.1','c++abi','z.1.2.8' s.resource_bundles = { 'Resources' => 'frameworks/*.framework/*.bundle' } # 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' # s.ios.deployment_target = '9.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } s.pod_target_xcconfig = {'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } end
编写IOS适配方法
import Flutter import UIKit import AliyunIdentityManager //当前视图 ViewController; var controller : UIViewController?; //method管道 var channel : FlutterMethodChannel?; //event管道 var eventChannel : FlutterEventChannel?; //回调flutter let eventStreamHandler = EventStreamHandler() public class SwiftAliAuthPersonPlugin: NSObject, FlutterPlugin{ public static func register(with registrar: FlutterPluginRegistrar) { channel = FlutterMethodChannel(name: "ali_auth_person", binaryMessenger: registrar.messenger()) let instance = SwiftAliAuthPersonPlugin() registrar.addMethodCallDelegate(instance, channel: channel!) eventChannel = FlutterEventChannel(name: "ali_auth_person_plugin_event", binaryMessenger: registrar.messenger()) eventChannel?.setStreamHandler((eventStreamHandler as! FlutterStreamHandler & NSObjectProtocol)) //初始化阿里SDK AliyunSdk.`init`(); } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { //获取本机参数 if(call.method == "getMetaInfos"){ let info = AliyunIdentityManager.getMetaInfo(); var jsonData: Data? = nil do { if info != nil { jsonData = try JSONSerialization.data(withJSONObject: info!, options: .prettyPrinted) } } catch _ { print("(parseError.localizedDescription)"); } var infoData : String? = ""; if let jsonData = jsonData { infoData = String(data: jsonData, encoding: .utf8) }; result(infoData); }else if(call.method == "verify"){ controller = UIApplication.shared.delegate?.window??.rootViewController; //进行实名认证 let certifyId : String = String(describing: call.arguments!); print(certifyId); let extParams: [String : Any] = ["currentCtr": controller!]; AliyunIdentityManager.sharedInstance()?.verify(with: certifyId, extParams: extParams, onCompletion: { (response) in DispatchQueue.main.async { var resString = "" switch response?.code { case .ZIMResponseSuccess: resString = "认证成功" break; case .ZIMInterrupt: resString = "初始化失败" break case .ZIMTIMEError: resString = "设备时间错误" break case .ZIMNetworkfail: resString = "网络错误" break case .ZIMInternalError: resString = "用户退出" break case .ZIMResponseFail: resString = "刷脸失败" default: resString = "未知异常" break } eventStreamHandler.sendEvent(event: "{'code':\(response?.code)},'msg':\(resString),'deviceToken':\(response?.deviceToken),'videoFilePath':\(response?.videoFilePath)"); } }) }else{ result("") } } } class EventStreamHandler: FlutterStreamHandler { private var eventSink:FlutterEventSink? = nil func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { eventSink = events return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { eventSink = nil return nil } public func sendEvent(event:Any) { eventSink?(event) } }
就此完成啦
https://github.com/lurongshuang/ali_auth_person
IOS集成的时候遇见几个问题,我截图列一下,有其他问题,联系我,我们共同成长。
问题一 和解决
image.png
image.png
问题二
image.png
问题三
image.png
image.png