Commit 0bd1b1cc authored by jiacheng.mao's avatar jiacheng.mao

ios new_sdk 20231127 新版本插件 part 4

parent 0c706a2e
package com.xg.idcard;
import static com.cn.qsign.jsgzlibrary.utils.QsignNotaryApi.QSIGNREGISTERCODE.NORMALREGISTER;
import android.Manifest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import android.util.Log;
import com.cn.qsign.jsgzlibrary.utils.QsignNotaryApi;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashSet;
import java.util.Set;
public class IdCardIdentifyPlugin extends CordovaPlugin {
private static final String ACTION_INIT = "init";
private static final String ACTION_REGISTER_NOTARY = "registerNotary";
private static final String ACTION_HAVE_USER = "haveUser";
private static final String ACTION_ACTIVE_USER_NOTARY = "activeUserNotary";
private static final String ACTION_SET_WRITE_IMG_NOTARY = "setWriteImgNotary";
private static final String ACTION_SET_FINGER_NOTARY = "setFingerNotary";
private static final String ACTION_FORGET_PIN_NOTARY = "forgetPINNotary";
private static final String ACTION_WEB_SIGN_NOTARY = "webSignNotary";
private static final String ACTION_GET_FINGER_OPENED = "getFingerOpened";
private static final String ACTION_QSIGN_LIVENESS_NOTARY = "qsignLivenessNotary";
private static final String ACTION_IDENTIFY_NOTARY = "identifyNotary";
private static final String ACTION_CLEAR_USER = "clearUser";
private static final String ERROR_CODE_PARAM = "ERROR_CODE_PARAM";
private static final String ERROR_CODE_INIT_SDK = "INIT_SDK_ERROR";
private static final String ERROR_CODE_PERMISSION_ERROR = "ERROR_PERMISSION_MISSING";
private static final String CODE_SUCCESS = "SUCCESS";
private static final int REQUEST_PERMISSION_CODE = 21;
private static final String[] PERMISSIONS = new String[]{
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
};
private CallbackContext globalCallbackContext = null;
private JSONArray globalArgs = null;
private String license = "";
private String tag = "xugong";
private boolean isActive = true;
private boolean isProdEnv = false;
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
String packageName = cordova.getActivity().getPackageName();
if ("com.xcmg.app.dev".equals(packageName)) {
license = "com.xcmg.app.dev-license.qsign-android";
isProdEnv = false;
} else {
license = "com.xcmg.app-license.qsign-android";
isProdEnv = true;
}
boolean result = QsignNotaryApi.getInstance().init(cordova.getActivity().getApplication(), license, tag, isActive, isProdEnv);
Log.d("IdCardIdentifyPlugin", "result = " + result);
}
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (ACTION_INIT.equals(action)) {
initSDK(args, callbackContext);
return true;
} else if (ACTION_REGISTER_NOTARY.equals(action)) {
registerNotary(args, callbackContext);
return true;
} else if (ACTION_HAVE_USER.equals(action)) {
haveUser(args, callbackContext);
return true;
} else if (ACTION_ACTIVE_USER_NOTARY.equals(action)) {
activeUserNotary(args, callbackContext);
return true;
} else if (ACTION_SET_WRITE_IMG_NOTARY.equals(action)) {
setWriteImgNotary(args, callbackContext);
return true;
} else if (ACTION_SET_FINGER_NOTARY.equals(action)) {
setFingerNotary(callbackContext);
return true;
} else if (ACTION_FORGET_PIN_NOTARY.equals(action)) {
forgetPINNotary(callbackContext);
return true;
} else if (ACTION_WEB_SIGN_NOTARY.equals(action)) {
webSignNotary(args, callbackContext);
return true;
} else if (ACTION_CLEAR_USER.equals(action)) {
clearUser(callbackContext);
return true;
} else if (ACTION_GET_FINGER_OPENED.equals(action)) {
getFingerOpened(callbackContext);
return true;
} else if (ACTION_QSIGN_LIVENESS_NOTARY.equals(action)) {
qsignLivenessNotary(args, callbackContext);
return true;
} else if (ACTION_IDENTIFY_NOTARY.equals(action)) {
identifyNotary(args, callbackContext);
return true;
}
return false;
}
private void qsignLivenessNotary(JSONArray args, final CallbackContext callbackContext) {
String name = "";
String IDNo = "";
try {
JSONObject params = args.getJSONObject(0);
name = params.getString("name");
IDNo = params.getString("IDNo");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
QsignNotaryApi.getInstance().qsignLivenessNotary(cordova.getActivity(), name, IDNo, new QsignNotaryApi.notaryCallbackListener() {
@Override
public void onSuccess() {
callbackContext.success(getResult("操作成功", CODE_SUCCESS));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name(), null));
}
});
}
private void initSDK(JSONArray args, final CallbackContext callbackContext) {
String license = "";
String tag = "";
boolean isActive = true;
boolean isProdEnv = false;
try {
JSONObject params = args.getJSONObject(0);
license = params.getString("license");
tag = params.getString("tag");
isActive = params.getBoolean("isActive");
isProdEnv = params.getBoolean("isProdEnv");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
/*
参数2 license
参数3 tag
参数4 是否激活 true
参数5 服务器环境 true:正式服务器环境 false:测试服务器环境hnsdk
*/
boolean result = QsignNotaryApi.getInstance().init(cordova.getActivity().getApplication(),
license, tag,
isActive, isProdEnv);
if (result) {
callbackContext.success(getResult("初始化成功", CODE_SUCCESS));
} else {
callbackContext.error(getResult("初始化失败,请检查参数等数据是否异常", ERROR_CODE_INIT_SDK));
}
}
/**
* 实名注册并设置PIN接口
*/
private void registerNotary(JSONArray args, final CallbackContext callbackContext) {
String bizNo = "";
String name = "";
String IDNo = "";
boolean disallowModify = true;
try {
JSONObject params = args.getJSONObject(0);
bizNo = params.getString("bizNo");
name = params.getString("name");
IDNo = params.getString("IDNo");
disallowModify = params.getBoolean("disallowModify");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
Set<String> requiredPermissions = getRequiredPermissions();
if (requiredPermissions.size() > 0) {
String[] permissions = requiredPermissions.toArray(new String[]{});
globalCallbackContext = callbackContext;
globalArgs = args;
cordova.requestPermissions(this, REQUEST_PERMISSION_CODE, permissions);
return;
}
//实名注册 并生成协同密钥 并增加签署口令设置
/*
参数2:bizNO 唯一编码 可以设置为身份证号,或唯一随机数
参数3:姓名
参数4:身份证号
参数5:是否不可修改 为true,即姓名和身份证不能修改并且不能为空
*/
QsignNotaryApi.getInstance().registerNotary(cordova.getActivity(), bizNo, name, IDNo, disallowModify, new QsignNotaryApi.registerCallbackListener() {
@Override
public void onSuccess(QsignNotaryApi.QSIGNREGISTERCODE code, String idnumber, String name, String phone) {
JSONObject data = new JSONObject();
try {
data.put("IDNo", idnumber);
data.put("name", name);
data.put("phone", phone);
} catch (JSONException ignored) {
}
String message = code == NORMALREGISTER ? "成功" : "信息提交成功,等待人工审核";
callbackContext.success(getResult(message, code.name(), data));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name(), null));
}
});
}
private void identifyNotary(JSONArray args, final CallbackContext callbackContext) {
String name = "";
String IDNo = "";
String phone = "";
try {
JSONObject params = args.getJSONObject(0);
name = params.getString("name");
IDNo = params.getString("IDNo");
phone = params.getString("phone");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
Set<String> requiredPermissions = getRequiredPermissions();
if (requiredPermissions.size() > 0) {
String[] permissions = requiredPermissions.toArray(new String[]{});
globalCallbackContext = callbackContext;
globalArgs = args;
cordova.requestPermissions(this, REQUEST_PERMISSION_CODE, permissions);
return;
}
//实名认证 并生成协同密钥
/*
参数2:bizNO 唯一编码 可以设置为身份证号,或唯一随机数
参数3:姓名
参数4:身份证号
参数5:是否不可修改 为true,即姓名和身份证不能修改并且不能为空
*/
QsignNotaryApi.getInstance().identifyNotary(cordova.getActivity(), name, IDNo, phone, new QsignNotaryApi.registerCallbackListener() {
@Override
public void onSuccess(QsignNotaryApi.QSIGNREGISTERCODE code, String idnumber, String name, String phone) {
JSONObject data = new JSONObject();
try {
data.put("IDNo", idnumber);
data.put("name", name);
data.put("phone", phone);
} catch (JSONException ignored) {
}
String message = code == NORMALREGISTER ? "成功" : "信息提交成功,等待人工审核";
callbackContext.success(getResult(message, code.name(), data));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name(), null));
}
});
}
private void activeUserNotary(JSONArray args, final CallbackContext callbackContext) {
String bizNo = "";
try {
JSONObject params = args.getJSONObject(0);
bizNo = params.getString("bizNo");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
QsignNotaryApi.getInstance().activeUserNotary(cordova.getActivity(), bizNo, new QsignNotaryApi.activeCallbackListener() {
@Override
public void onSuccess(String idnumber, String name, String phone) {
JSONObject result = new JSONObject();
try {
result.put("IDNo", idnumber);
result.put("name", name);
result.put("phone", phone);
} catch (JSONException ignored) {
}
callbackContext.success(getResult("激活成功", CODE_SUCCESS, result));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name()));
}
});
}
private void haveUser(JSONArray args, CallbackContext callbackContext) {
String bizNo = "";
try {
JSONObject params = args.getJSONObject(0);
bizNo = params.getString("bizNo");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
Boolean haveUser = QsignNotaryApi.getInstance().haveUser(cordova.getActivity(), bizNo);
JSONObject result = new JSONObject();
try {
result.put("haveUser", haveUser);
} catch (JSONException ignored) {
}
callbackContext.success(getResult("成功", CODE_SUCCESS, result));
}
private void setWriteImgNotary(JSONArray args, final CallbackContext callbackContext) {
String bizNo = "";
try {
JSONObject params = args.getJSONObject(0);
bizNo = params.getString("bizNo");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
QsignNotaryApi.getInstance().setWriteImgNotary(cordova.getActivity(), bizNo, new QsignNotaryApi.notaryCallbackListener() {
@Override
public void onSuccess() {
callbackContext.success(getResult("成功", CODE_SUCCESS));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name()));
}
});
}
private void setFingerNotary(final CallbackContext callbackContext) {
QsignNotaryApi.getInstance().setFingerNotary(cordova.getActivity(), new QsignNotaryApi.notaryCallbackListener() {
@Override
public void onSuccess() {
JSONObject result = new JSONObject();
try {
result.put("isFingerOpened", QsignNotaryApi.getInstance().getFingerOpened(cordova.getActivity()));
} catch (JSONException ignored) {
}
callbackContext.success(getResult("成功", CODE_SUCCESS, result));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name()));
}
});
}
private void forgetPINNotary(final CallbackContext callbackContext) {
QsignNotaryApi.getInstance().forgetPINNotary(cordova.getActivity(), new QsignNotaryApi.notaryCallbackListener() {
@Override
public void onSuccess() {
callbackContext.success(getResult("成功", CODE_SUCCESS));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name()));
}
});
}
private void webSignNotary(JSONArray args, final CallbackContext callbackContext) {
String url = "";
try {
JSONObject params = args.getJSONObject(0);
url = params.getString("url");
} catch (JSONException e) {
callbackContext.error(getResult("参数错误:" + e, ERROR_CODE_PARAM));
return;
}
QsignNotaryApi.getInstance().webSignNotary(cordova.getActivity(), url, new QsignNotaryApi.notaryCallbackListener() {
@Override
public void onSuccess() {
callbackContext.success(getResult("成功", CODE_SUCCESS));
}
@Override
public void onError(QsignNotaryApi.QSIGNERRORCODE code, String msg) {
callbackContext.error(getResult(msg, code.name()));
}
});
}
private void clearUser(CallbackContext callbackContext) {
QsignNotaryApi.getInstance().ClearUser(cordova.getActivity());
callbackContext.success(getResult("清除成功", CODE_SUCCESS));
}
private void getFingerOpened(CallbackContext callbackContext) {
JSONObject result = new JSONObject();
try {
result.put("isFingerOpened", QsignNotaryApi.getInstance().getFingerOpened(cordova.getActivity()));
} catch (JSONException ignored) {
}
callbackContext.success(getResult("成功", CODE_SUCCESS, result));
}
private JSONObject getResult(String message, String code) {
return getResult(message, code, null);
}
private JSONObject getResult(String message, String code, JSONObject data) {
JSONObject out = new JSONObject();
try {
if (code != null) {
out.put("code", code);
}
out.put("message", message);
if (data != null) {
out.put("data", data);
}
} catch (JSONException ignored) {
}
return out;
}
@Override
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException {
super.onRequestPermissionResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CODE) {
Set<String> requiredPermissions = getRequiredPermissions();
if (requiredPermissions.size() == 0) {
registerNotary(globalArgs, globalCallbackContext);
} else {
StringBuilder sb = new StringBuilder();
boolean hasStorageTint = false;
JSONArray missPermissionsArray = new JSONArray();
for (String s : requiredPermissions) {
if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(s) || Manifest.permission.READ_EXTERNAL_STORAGE.equals(s)) {
if (!hasStorageTint) {
sb.append("读写存储权限,");
missPermissionsArray.put("读写存储权限");
hasStorageTint = true;
}
}
if (Manifest.permission.CAMERA.equals(s)) {
sb.append("相机权限,");
missPermissionsArray.put("相机权限");
}
if (Manifest.permission.RECORD_AUDIO.equals(s)) {
missPermissionsArray.put("录音权限");
sb.append("录音权限,");
}
}
JSONObject result = new JSONObject();
result.put("missPermissions", missPermissionsArray);
globalCallbackContext.error(getResult("缺少权限:" + sb, ERROR_CODE_PERMISSION_ERROR, result));
}
}
}
private Set<String> getRequiredPermissions() {
Set<String> sets = new HashSet<String>();
for (String permission : IdCardIdentifyPlugin.PERMISSIONS) {
boolean b = cordova.hasPermission(permission);
if (!b) {
sets.add(permission);
}
}
return sets;
}
private String saveImage(String base64String) {
byte[] decode = Base64.decode(base64String, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
File appDir = new File(cordova.getActivity().getApplicationContext().getFilesDir(), "QSign_Face");
if (!appDir.exists()) {
appDir.mkdir();
}
String fileName = System.currentTimeMillis() + ".jpg";
File file = new File(appDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return file.getPath();
}
}
IyDl5pQS3o3fFUQeXbstDxTvBS/uVKYWHDf549PcITq+WrHoe4ubjzoizlu5olJs2qHqvqAW4N+tnywSWMbzhMRiQKpx2SGHy7c+egnXWl5VCA3LRVMjRPsx+XE1bUHbL9RzjSUq/BN9WVz2HEryxSmRf+YD+QAKuc2e01Ei7c8=
\ No newline at end of file
OoC6eFPZ052U9SUIKADVkMowQX8QUK6xZdzz3R8W/15nMXisPRHSccLFlLalaf5n0pYf+/A087BXOcLDOfDqlWr0d68z0S+hNbmjvovgd4Og0sJodxnBHailPIGbjJPiqPByiAzke+Z6qxN3fB3bpA1ViXilJKXBwg5/bgJPxuE=
\ No newline at end of file
repositories{
jcenter()
flatDir {
dirs 'libs'
}
}
dependencies {
compile(name:"jsgzsdk",ext: 'aar')
//必须添加如下依赖!!!
implementation 'com.android.support:appcompat-v7:28.+'
implementation 'com.android.support:support-v4:28.+'
implementation 'com.android.support:recyclerview-v7:28.+'
implementation 'com.android.support:design:28.+'
implementation 'com.google.code.gson:gson:2.8.0'
implementation 'com.alibaba:fastjson:1.2.31'
implementation 'com.tencent:mmkv:1.2.14'
implementation 'com.getkeepsafe.relinker:relinker:1.4.3'
implementation 'com.lzy.net:okgo:3.0.4'
implementation ('com.github.bumptech.glide:glide:4.8.0'){
exclude group:"com.android.support"
}
implementation 'com.github.lzyzsd:jsbridge:1.0.4'
implementation 'com.otaliastudios:cameraview:1.6.1'
implementation "com.android.support:exifinterface:28.+"
}
android {
packagingOptions {
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
}
aaptOptions {
noCompress "dat"
}
}
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")) {
details.useVersion '28.0.0'
}
}
}
}
\ No newline at end of file
//
// IdCardIdentifyCordova.h
// IdCard
//
// Created by 吴笑诚 on 2021/1/27.
//
#import <Foundation/Foundation.h>
#import <Cordova/CDV.h>
NS_ASSUME_NONNULL_BEGIN
@interface IdCardIdentifyCordova : CDVPlugin
@property (nonatomic, strong) NSURL* url;
@property (nonatomic, assign) BOOL pageLoaded;
#pragma mark - 公共部分
// 初始化
- (void) init:(CDVInvokedUrlCommand*)command;
//实名注册
- (void) registerNotary:(CDVInvokedUrlCommand*)command;
//查询用户
- (void) haveUser:(CDVInvokedUrlCommand*)command;
//人工审核激活
- (void) activeUserNotary:(CDVInvokedUrlCommand*)command;
//设置手写签名
- (void) setWriteImgNotary:(CDVInvokedUrlCommand*)command;
//开启/关闭指纹代替PIN接口
- (void) setFingerNotary:(CDVInvokedUrlCommand*)command;
//忘记PIN
- (void) forgetPINNotary:(CDVInvokedUrlCommand*)command;
//网页签署
- (void) webSignNotary:(CDVInvokedUrlCommand*)command;
// 获取指纹状态
- (void) getFingerOpened:(CDVInvokedUrlCommand*)command;
// 清除用户 iOS 不支持
- (void) clearUser:(CDVInvokedUrlCommand*)command;
#pragma mark - 原有插件接口
// 实名认证
- (void) identifyNotary:(CDVInvokedUrlCommand*)command;
// 人脸识别
- (void) qsignLivenessNotary:(CDVInvokedUrlCommand*)command;
//// 人脸识别
//- (void) faceContrast:(CDVInvokedUrlCommand*)command;
@end
NS_ASSUME_NONNULL_END
//
// QsignCordova.m
// IdCard
//
// Created by 吴笑诚 on 2023/9/26.
//
#import "IdCardIdentifyCordova.h"
#import <QsignNotarySDK/QsignNotaryApi.h>
#import <objc/message.h>
#define MY_NSString_IsEmpty(x) !(x && x.length > 0)
static NSString * const bundleId_dev = @"com.xcmg.app.dev"; //两种写法等价
static NSString * const bundleId_pro = @"com.xcmg.app"; //两种写法等价
#define CDV_PHOTO_PREFIX_ID @"cdv_photo_id_"
typedef NS_ENUM(NSInteger, NSPUIImageType)
{
NSPUIImageType_JPEG,
NSPUIImageType_PNG,
NSPUIImageType_Unknown
};
@interface IdCardIdentifyCordova () {
}
@property (nonatomic,strong) NSString* callbackId;
@property (nonatomic,assign) BOOL initRes;
@end
@implementation IdCardIdentifyCordova
/****
插件初始化
****/
- (void)pluginInitialize
{
_initRes = NO;
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationLaunchedWithUrl:) name:CDVPluginHandleOpenURLNotification object:nil];
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationPageDidLoad:) name:CDVPageDidLoadNotification object:nil];
[self initSDK];
}
- (void) initSDK {
/*
serverurl 服务器地址 为空默认测试地址,正式部署上线的地址为http://identity.qsign.com.cn
licensepath 授权文件路径,license是根据bundleid和sdktag生成
sdktag 应用标识,徐工固定为 "xugong"
active 是否激活 默认填写 NO
*/
// NSString* licensePath = [[NSBundle mainBundle] pathForResource:@"com.xcmg.app.dev-license" ofType:@"qsign-ios"];
// BOOL ok= [[QsignNotaryApi sharedInstance] initQsignNotary:@"com.xcmg.app-license" licensepath:licensePath sdktag:@"xugong" active:NO];
BOOL res = NO;
NSString* bundleid = [self getBundleID];
if ([bundleid isEqualToString:bundleId_dev]) {
NSString* licensePath = [[NSBundle mainBundle] pathForResource:@"com.xcmg.app.dev-license" ofType:@"qsign-ios"];
// res= [[QsignNotaryApi sharedInstance] initQsignNotary:@"" licensepath:licensePath sdktag:@"xugong" active:NO];
res = [[QsignNotaryApi sharedInstance] initQsignWithPath:NO licensepath:licensePath sdktag:@"xugong" active:YES];
}
else if ([bundleid isEqualToString:bundleId_pro]) {
NSString* licensePath = [[NSBundle mainBundle] pathForResource:@"com.xcmg.app-license" ofType:@"qsign-ios"];
// res= [[QsignNotaryApi sharedInstance] initQsignNotary:@"http://identity.qsign.com.cn" licensepath:licensePath sdktag:@"xugong" active:NO];
res = [[QsignNotaryApi sharedInstance] initQsignWithPath:YES licensepath:licensePath sdktag:@"xugong" active:YES];
}
else {
NSLog(@"非约定的bundle id");
// NSString* licensePath = [[NSBundle mainBundle] pathForResource:@"com.xcmg.app.dev-license" ofType:@"qsign-ios"];
// res = [[QsignNotaryApi sharedInstance] initQsignWithPath:YES licensepath:licensePath sdktag:@"xugong" active:NO];
}
_initRes = res;
}
//获取BundleID
- (NSString*) getBundleID
{
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
}
#pragma mark - Cordova接口
#pragma mark -
- (void) init:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* licensepath = param[@"license"];
NSString* sdktag = param[@"tag"];
BOOL isActive = param[@"isActive"] ;
BOOL isProdEnv = param[@"isProdEnv"];
if (MY_NSString_IsEmpty(licensepath) || MY_NSString_IsEmpty(sdktag)) {
[self checkArgcFailed];
return;
}
NSString* licensePath = [[NSBundle mainBundle] pathForResource:licensepath ofType:@"qsign-ios"];
/*
参数1:production 是否是生产环境,YES:生产服务器,NO:测试服务器
参数2:licensepath 授权文件路径,license是根据bundleid和sdktag生成,我们提供
参数3: sdktag 应用标识 我们提供
参数4:active 是否激活,默认true
*/
//result==1初始化成功
BOOL res = NO;
res = [[QsignNotaryApi sharedInstance] initQsignWithPath:isProdEnv licensepath:licensePath sdktag:sdktag active:isActive];
_initRes = res;
if (res) {
[self nativeViewDismissSuccessWithDataDict:nil msg:@"初始化成功"];
}
else {
NSMutableDictionary* retDict = [self dictWithCode:2 codeStr:@"ERROR_CODE_INIT_SDK" msg:@"初始化失败"];
[self nativeViewDismissErrorWithDict:retDict];
}
}
//实名注册
- (void) registerNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* bizNo = param[@"bizNo"]?:@"";
NSString* name = param[@"name"]?:@"";
NSString* IDNo = param[@"IDNo"]?:@"";
BOOL disallowModify = param[@"disallowModify"];
/*
参数1:bizNO 唯一编码 可以设置为身份证号,或唯一随机数,为空默认为身份证号
参数2:姓名
参数3:身份证号
参数4:是否不可修改 YES:即姓名和身份证不能修改并且不能为空
*/
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] registerNotary:bizNo name:name idnumber:IDNo lock:disallowModify successHandler:^(QsignNotaryRegisterCode code, NSString * _Nonnull idnumber, NSString * _Nonnull name, NSString * _Nonnull phone) {
NSMutableDictionary* retDict = [NSMutableDictionary dictionary];
if(code==normalRegister){//正常注册流程
NSLog(@"实名成功");
retDict = [weakSelf dictWithCode:code codeStr:@"normalRegister" msg:@"实名成功"];
}else{//人工审核流程
NSLog(@"信息提交成功,等待审核");
retDict = [weakSelf dictWithCode:code codeStr:@"personService" msg:@"信息提交成功,等待审核"];
}
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:idnumber forKey:@"IDNo"];
[data setObject:name forKey:@"name"];
[data setObject:phone forKey:@"phone"];
[retDict setObject:data forKey:@"data"];
[weakSelf nativeViewDismissSuccessWithDict:retDict];
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
- (NSString*)getErrorCodeStr:(QsignNotaryErrorCode) errorcode {
NSArray* strArray = @[
@"cancelback", //中途退出
@"fingerError",//指纹验证错误
@"nouserError",//未注册
@"faceError",//人脸比对不通过
@"personregisterError",//人工审核信息提交失败,请重新注册
@"qrError",//二维码参数有误
@"parameerror",//参数错误
@"biznoError",//缺少业务编号
@"faceTimeout",//人脸超时
@"packageerror",//未授权的应用
@"permissionError",//权限缺失
@"nofingerError",//尚无指纹请先设置
];
if (errorcode > strArray.count-1) {
return @"unknown";
} else {
NSString* retStr = [strArray objectAtIndex:errorcode];
return retStr;
}
}
//查询用户
- (void) haveUser:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* bizNo = param[@"bizNo"]?:@"";
if (MY_NSString_IsEmpty(bizNo)) {
[self checkArgcFailed];
return;
}
/*
查询是否有协同密钥,
参数:bizNO 唯一编码 可以设置为身份证号,或唯一随机数
*/
__weak __typeof(self) weakSelf = self;
if([[QsignNotaryApi sharedInstance] haveUser:bizNo]){
NSLog(@"存在此用户");
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:YES] forKey:@"haveUser"];
[self nativeViewDismissSuccessWithDataDict:data msg:@"存在此用户"];
}else{
NSLog(@"不存在");
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:NO] forKey:@"haveUser"];
[self nativeViewDismissSuccessWithDataDict:data msg:@"不存在户"];
}
}
//人工审核激活
- (void) activeUserNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* bizNo = param[@"bizNo"]?:@"";
if (MY_NSString_IsEmpty(bizNo)) {
[self checkArgcFailed];
return;
}
/*
如果实名认证走的是人工审核,则需要激活
参数:bizNO 唯一编码 可以设置为身份证号,或唯一随机数
*/
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] activeNotary:bizNo successHandler:^(NSString * _Nonnull idnumber, NSString * _Nonnull name, NSString * _Nonnull phone) {
NSLog(@"%@激活成功",name);
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:idnumber forKey:@"IDNo"];
[data setObject:name forKey:@"name"];
[data setObject:phone forKey:@"phone"];
[weakSelf nativeViewDismissSuccessWithDataDict:data msg:@"激活成功"];
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
NSLog(@"激活失败 %@", msg);
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
//设置手写签名
- (void) setWriteImgNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* bizNo = param[@"bizNo"]?:@"";
if (MY_NSString_IsEmpty(bizNo)) {
[self checkArgcFailed];
return;
}
/*
设置手写签名
参数:bizNO 唯一编码 可以设置为身份证号,或唯一随机数
*/
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] setWriteImgNotary:bizNo successHandler:^{
[self nativeViewDismissSuccessWithDataDict:nil msg:@"成功"];
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
//开启/关闭指纹代替PIN接口
- (void) setFingerNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] setFingerNotary:^{
if([[QsignNotaryApi sharedInstance] getFingerOpened]){
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:YES] forKey:@"isFingerOpened"];
[weakSelf nativeViewDismissSuccessWithDataDict:data msg:@"成功"];
}else{
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:NO] forKey:@"isFingerOpened"];
[weakSelf nativeViewDismissSuccessWithDataDict:data msg:@"成功"];
}
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
NSLog(@"%@",msg);
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
//忘记PIN
- (void) forgetPINNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] forgerPINNotary:^{
if([[QsignNotaryApi sharedInstance] getFingerOpened]){
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:YES] forKey:@"isFingerOpened"];
[weakSelf nativeViewDismissSuccessWithDataDict:data msg:@"成功"];
}else{
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:NO] forKey:@"isFingerOpened"];
[weakSelf nativeViewDismissSuccessWithDataDict:data msg:@"成功"];
}
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
NSLog(@"%@",msg);
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
//网页签署
- (void) webSignNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* url = param[@"url"]?:@"";
if (MY_NSString_IsEmpty(url)) {
[self checkArgcFailed];
return;
}
/*
参数:签署的http地址
*/
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] webSignNotary:url successHandler:^{
[weakSelf nativeViewDismissSuccessWithDataDict:nil msg:@"成功"];
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
NSLog(@"%@",msg);
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
// 获取指纹状态
- (void) getFingerOpened:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
if([[QsignNotaryApi sharedInstance] getFingerOpened]){
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:YES] forKey:@"isFingerOpened"];
[self nativeViewDismissSuccessWithDataDict:data msg:@"成功"];
}else{
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:[NSNumber numberWithBool:NO] forKey:@"isFingerOpened"];
[self nativeViewDismissSuccessWithDataDict:data msg:@"成功"];
}
}
// 清除用户
- (void) clearUser:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
[self nativeViewDismissErrorWithCode:-1 msg:@"iOS平台没有相关接口"];
}
- (void) qsignLivenessNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* idNum = [param objectForKey:@"IDNo"];
NSString* idName = [param objectForKey:@"name"];
NSLog(@"身份证号码: %@", idNum);
NSLog(@"姓名: %@" ,idName);
if (MY_NSString_IsEmpty(idNum) || MY_NSString_IsEmpty(idName) ) {
[self checkArgcFailed];
return;
}
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] qsignLivenessNotary:idName idnumber:idNum successHandler:^(NSString * _Nonnull baseimage) {
NSString* msg = [weakSelf base64ToLocalURL:baseimage];
[weakSelf nativeViewDismissSuccess:msg];
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
//1.实名认证
//cordova.plugins.IdCardPlugin.idCardIdentify({"idNum":"身份证号码","idName":"姓名","phoneNum":"手机号"}, function (success) {}, function (reason) {});
//
// 实名认证
- (void) identifyNotary:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* idNum = [param objectForKey:@"IDNo"];
NSString* idName = [param objectForKey:@"name"];
NSString* phoneNum = [param objectForKey:@"phone"];
NSLog(@"身份证号码: %@", idNum);
NSLog(@"姓名: %@" ,idName);
NSLog(@"手机号: %@" ,phoneNum);
if (MY_NSString_IsEmpty(idNum) || MY_NSString_IsEmpty(idName) || MY_NSString_IsEmpty(phoneNum) ) {
// [self nativeViewDismissFaild:@"参数不正确"];
[self checkArgcFailed];
return;
}
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] identifyNotary:idName idnumber:idNum phone:phoneNum successHandler:^(QsignNotaryRegisterCode code, NSString * _Nonnull idnumber, NSString * _Nonnull name, NSString * _Nonnull phone) {
NSMutableDictionary* retDict = [NSMutableDictionary dictionary];
if(code==normalRegister){//正常注册流程
NSLog(@"实名成功");
retDict = [weakSelf dictWithCode:code codeStr:@"normalRegister" msg:@"实名成功"];
}else{//人工审核流程
NSLog(@"信息提交成功,等待审核");
retDict = [weakSelf dictWithCode:code codeStr:@"personService" msg:@"信息提交成功,等待审核"];
}
NSMutableDictionary* data = [NSMutableDictionary dictionary];
[data setObject:idnumber forKey:@"IDNo"];
[data setObject:name forKey:@"name"];
[data setObject:phone forKey:@"phone"];
[retDict setObject:data forKey:@"data"];
[weakSelf nativeViewDismissSuccessWithDict:retDict];
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
// 人脸识别
//2.人脸对比 成功回调返回人脸照片路径
//cordova.plugins.IdCardPlugin.faceContrast({"idNum":"身份证号码","idName":"姓名"}, function (success) {}, function (reason) {
- (void) faceContrast:(CDVInvokedUrlCommand*)command {
_callbackId = [command callbackId];
if (![self checkInit]) {
return;
}
NSDictionary* param = [[command arguments] objectAtIndex:0];
NSString* idNum = [param objectForKey:@"idNum"];
NSString* idName = [param objectForKey:@"idName"];
NSLog(@"身份证号码: %@", idNum);
NSLog(@"姓名: %@" ,idName);
if (MY_NSString_IsEmpty(idNum) || MY_NSString_IsEmpty(idName) ) {
[self checkArgcFailed];
return;
}
__weak __typeof(self) weakSelf = self;
[[QsignNotaryApi sharedInstance] qsignLivenessNotary:idName idnumber:idNum successHandler:^(NSString * _Nonnull baseimage) {
NSString* msg = [weakSelf base64ToLocalURL:baseimage];
[weakSelf nativeViewDismissSuccess:msg];
} errorHandle:^(QsignNotaryErrorCode errorcode, NSString * _Nonnull msg) {
[weakSelf nativeViewDismissErrorWithCode:errorcode msg:msg];
}];
}
- (NSString*)base64ToLocalURL:(NSString*) base64Image {
NSString* result = @"";
NSData * imageData = [[NSData alloc]initWithBase64EncodedString:base64Image options:NSDataBase64DecodingIgnoreUnknownCharacters];
if (imageData) {
NSPUIImageType type = [self NSPUIImageTypeFromData:imageData];
NSString* extension = type == NSPUIImageType_PNG ? @"png" : @"jpg";
NSString* filePath = [self tempFilePath:extension];
NSError* err = nil;
// save file
if (![imageData writeToFile:filePath options:NSAtomicWrite error:&err]) {
result = [err localizedDescription];
} else {
result = [[self urlTransformer:[NSURL fileURLWithPath:filePath]] absoluteString];
}
}
return result;
}
- (BOOL) checkInit {
if (!_initRes) {
NSMutableDictionary* retDict = [self dictWithCode:1 codeStr:@"ERROR_CODE_INIT" msg:@"初始化失败或未初始化"];
[self nativeViewDismissErrorWithDict:retDict];
return NO;
}
return YES;
}
#pragma mark - 返回值
#pragma mark -
- (void) checkArgcFailed {
NSMutableDictionary* retDict = [self dictWithCode:1 codeStr:@"ERROR_CODE_PARAM" msg:@"参数不正确"];
[self nativeViewDismissErrorWithDict:retDict];
}
-(NSMutableDictionary*) dictWithCode:(BOOL)code msg:(NSString*)msg {
NSMutableDictionary* retDict = [NSMutableDictionary dictionary];
if (code) {
[retDict setValue:[NSNumber numberWithInt:1] forKey:@"code"];
}
else {
[retDict setValue:[NSNumber numberWithInt:0] forKey:@"code"];
}
[retDict setValue:msg forKey:@"message"];
return retDict;
}
-(NSMutableDictionary*) dictWithCode:(NSInteger)code codeStr:(NSString*) codeStr msg:(NSString*)msg {
NSMutableDictionary* retDict = [NSMutableDictionary dictionary];
if (code) {
[retDict setValue:[NSNumber numberWithInteger:code] forKey:@"intCode"];
}
else {
[retDict setValue:[NSNumber numberWithInt:0] forKey:@"intCode"];
}
if (codeStr) {
[retDict setValue:[codeStr uppercaseString] forKey:@"code"];
} else {
[retDict setValue:@"" forKey:@"code"];
}
[retDict setValue:msg forKey:@"message"];
return retDict;
}
-(NSString*)DataTOjsonString:(id)object
{
NSString *jsonString = nil;
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if (! jsonData) {
NSLog(@"Got an error: %@", error);
} else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return jsonString;
}
- (void) nativeViewDismissSuccess:(NSString*)resultStr {
// [self.navCtrl dismissViewControllerAnimated:YES completion:nil];
// [[BLEDeviceManager shareInstance] disConnect];
NSLog(@"插件返回 %@",resultStr);
NSMutableDictionary* dict = [self dictWithCode:YES msg:resultStr];
NSString* retStr = [self DataTOjsonString:dict];
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK
messageAsString:retStr];
[self.commandDelegate sendPluginResult:result callbackId:_callbackId];
}
- (void) nativeViewDismissFaild:(NSString*)resultStr {
// [MsgToolBox showAlert:@"nativeViewDismissFaild" content:resultStr];
// [self.navCtrl dismissViewControllerAnimated:YES completion:nil];
// [[BLEDeviceManager shareInstance] disConnect];
//
NSMutableDictionary* dict = [self dictWithCode:NO msg:resultStr];
NSString* retStr = [self DataTOjsonString:dict];
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_ERROR
messageAsString:retStr];
[self.commandDelegate sendPluginResult:result callbackId:_callbackId];
}
- (void) nativeViewDismissSuccessWithDict:(NSMutableDictionary*)dict {
// [self.navCtrl dismissViewControllerAnimated:YES completion:nil];
// [[BLEDeviceManager shareInstance] disConnect];
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:dict];
[self.commandDelegate sendPluginResult:result callbackId:_callbackId];
}
- (void) nativeViewDismissSuccessWithDataDict:(NSMutableDictionary*)dataDict msg:(NSString*) msg {
// [self.navCtrl dismissViewControllerAnimated:YES completion:nil];
// [[BLEDeviceManager shareInstance] disConnect];
NSMutableDictionary* retDict = [NSMutableDictionary dictionary];
retDict = [self dictWithCode:0 codeStr:@"SUCCESS" msg:msg];
if (dataDict) {
[retDict setObject:dataDict forKey:@"data"];
}
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:retDict];
[self.commandDelegate sendPluginResult:result callbackId:_callbackId];
}
- (void)nativeViewDismissErrorWithDict:(NSDictionary *)dict
{
// [self.navCtrl dismissViewControllerAnimated:YES completion:nil];
// [[BLEDeviceManager shareInstance] disConnect];
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_ERROR
messageAsDictionary:dict];
[self.commandDelegate sendPluginResult:result callbackId:_callbackId];
}
- (void)nativeViewDismissErrorWithCode:(NSInteger)errorcode msg: (NSString*) msg
{
// [self.navCtrl dismissViewControllerAnimated:YES completion:nil];
NSMutableDictionary* retDict = [self dictWithCode:errorcode codeStr:[self getErrorCodeStr:errorcode] msg:msg];
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_ERROR
messageAsDictionary:retDict];
[self.commandDelegate sendPluginResult:result callbackId:_callbackId];
}
- (void) nativeViewDismissSuccessWithArray:(NSArray*)array {
// [self.navCtrl dismissViewControllerAnimated:YES completion:nil];
// [[BLEDeviceManager shareInstance] disConnect];
//
NSLog(@"插件返回 %@",array);
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK
messageAsArray:array];
[self.commandDelegate sendPluginResult:result callbackId:_callbackId];
}
#pragma mark -- 工具类
- (NSPUIImageType) NSPUIImageTypeFromData:(NSData *) imageData {
if (imageData.length > 4) {
const unsigned char * bytes = [imageData bytes];
if (bytes[0] == 0xff &&
bytes[1] == 0xd8 &&
bytes[2] == 0xff)
{
return NSPUIImageType_JPEG;
}
if (bytes[0] == 0x89 &&
bytes[1] == 0x50 &&
bytes[2] == 0x4e &&
bytes[3] == 0x47)
{
return NSPUIImageType_PNG;
}
}
return NSPUIImageType_Unknown;
}
- (NSString*)tempFilePath:(NSString*)extension
{
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by Apple (vs [NSFileManager defaultManager]) to be threadsafe
NSString* filePath;
// generate unique file name
int i = 1;
do {
filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX_ID, i++, extension];
} while ([fileMgr fileExistsAtPath:filePath]);
return filePath;
}
- (NSURL*) urlTransformer:(NSURL*)url
{
NSURL* urlToTransform = url;
// for backwards compatibility - we check if this property is there
SEL sel = NSSelectorFromString(@"urlTransformer");
if ([self.commandDelegate respondsToSelector:sel]) {
// grab the block from the commandDelegate
NSURL* (^urlTransformer)(NSURL*) = ((id(*)(id, SEL))objc_msgSend)(self.commandDelegate, sel);
// if block is not null, we call it
if (urlTransformer) {
urlToTransform = urlTransformer(url);
}
}
return urlToTransform;
}
@end
//
// MsgToolBox.h
// UserExperienceDemo
//
// Created by liuzhilong on 15/3/31.
// Copyright (c) 2015年 alibaba. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface MsgToolBox : NSObject
+ (void) showAlert:(NSString *)title content:(NSString *)content;
//+ (void) showToast:(NSString *)content ;
@end
//
// MsgToolBox.m
// UserExperienceDemo
//
// Created by liuzhilong on 15/3/31.
// Copyright (c) 2015年 alibaba. All rights reserved.
//
#import "MsgToolBox.h"
@implementation MsgToolBox
+ (void) showAlert:(NSString *)title content:(NSString *)content {
return;// 不做提示
// 保证在主线程上执行
if ([NSThread isMainThread]) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:content delegate:self cancelButtonTitle:@"好的" otherButtonTitles:nil, nil];
[alertView show];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:content delegate:self cancelButtonTitle:@"好的" otherButtonTitles:nil, nil];
[alertView show];
});
}
}
//+ (void) showToast:(NSString *)content {
//
// if ([NSThread isMainThread]) {
// UIViewController* vc = [MsgToolBox getTopViewControllerWithCtrl:nil];
// [vc.view makeToast:content];
// } else {
// dispatch_async(dispatch_get_main_queue(), ^{
// UIViewController* vc = [MsgToolBox getTopViewControllerWithCtrl:nil];
// [vc.view makeToast:content];
// });
// }
//
//}
//获取当前显示的控制器
+ (UIViewController *)getTopViewControllerWithCtrl:(UIViewController *)vc{
UIViewController *current;
if(vc == nil){
vc = [UIApplication sharedApplication].keyWindow.rootViewController;
}
if([vc isKindOfClass:[UITabBarController class]]){
return [self getTopViewControllerWithCtrl:[(UITabBarController *)vc selectedViewController]];
}else if ([vc isKindOfClass:[UINavigationController class]]){
return [self getTopViewControllerWithCtrl:[(UINavigationController *)vc visibleViewController]];
}else{
current = vc;
}
return current;
}
+ (UIViewController *)currentViewControllerWithRootViewController:(UIViewController*)rootViewController
{
if(rootViewController == nil){
rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
}
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tabBarController = (UITabBarController *)rootViewController;
return [self currentViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self currentViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self currentViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
@end
//
// QsignFaceManager.h
// qsignface
//
// Created by 卖女孩的小火柴 on 2020/4/30.
// Copyright © 2020 卖女孩的小火柴. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, QsignRemindLivenesCode) {
qRemindCodeOK = 0, //检测到活体
qRemindCodeNotRealFace,//非活体
qfacetimeout,
qfacenofind,
qfacefindhanding
};
typedef void (^LivenessCompletion) (UIImage *__nullable image,QsignRemindLivenesCode remindCode);
@interface QsignFaceManager : NSObject<NSCopying>
+(instancetype)sharedInstance;
-(int)faceSdk_init;//初始化
-(BOOL)faceCanwork;//是否初始化成功
-(void)facesdk_detectLiveness:(CIImage *)originimg completionHandler:(LivenessCompletion)completion;
-(void)resetFace;//重置
@end
NS_ASSUME_NONNULL_END
//
// QsignFaceSDK.h
// QsignFaceSDK
//
// Created by 卖女孩的小火柴 on 2020/4/30.
// Copyright © 2020 卖女孩的小火柴. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for QsignFaceSDK.
FOUNDATION_EXPORT double QsignFaceSDKVersionNumber;
//! Project version string for QsignFaceSDK.
FOUNDATION_EXPORT const unsigned char QsignFaceSDKVersionString[];
#import <QsignFaceSDK/QsignFaceManager.h>
// In this header, you should import all the public headers of your framework using statements like #import <QsignFaceSDK/PublicHeader.h>
framework module QsignFaceSDK {
umbrella header "QsignFaceSDK.h"
export *
module * { export * }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/QsignFaceManager.h</key>
<data>
BrbGTY0pQ4E2I/L9JlALBC+ln40=
</data>
<key>Headers/QsignFaceSDK.h</key>
<data>
dXKD4YHfActrkeeqHTzlx8GiLMA=
</data>
<key>Info.plist</key>
<data>
gFlj1QZVewzhWaAjgaaYeX3Bug0=
</data>
<key>Modules/module.modulemap</key>
<data>
m7HSyAqBhPpVwefbBsEDq0OH2G8=
</data>
<key>qfacemodel.bundle/Root.plist</key>
<data>
jOhqEUF1/xyY+fuswiWT+ELC3dI=
</data>
<key>qfacemodel.bundle/en.lproj/Root.strings</key>
<dict>
<key>hash</key>
<data>
t4KY9Gh4uIiOv7VnHtRrKEuPRY8=
</data>
<key>optional</key>
<true/>
</dict>
<key>qfacemodel.bundle/liveness.dat</key>
<data>
sA83GQyyexPEwRVNpYRus1ioaVk=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/QsignFaceManager.h</key>
<dict>
<key>hash</key>
<data>
BrbGTY0pQ4E2I/L9JlALBC+ln40=
</data>
<key>hash2</key>
<data>
agXKZO/LJ+1nXOlbbayAW16Yi72/4ThIfcZ53CYAosQ=
</data>
</dict>
<key>Headers/QsignFaceSDK.h</key>
<dict>
<key>hash</key>
<data>
dXKD4YHfActrkeeqHTzlx8GiLMA=
</data>
<key>hash2</key>
<data>
FgfmXPWglwBlaUE2OsAp76qywGqz3UgjP4NeF99Vv8A=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash</key>
<data>
m7HSyAqBhPpVwefbBsEDq0OH2G8=
</data>
<key>hash2</key>
<data>
Kl1hpbD0hnPJNsjXO928c7mp1i1/t05lVsR4/o5Z2Mo=
</data>
</dict>
<key>qfacemodel.bundle/Root.plist</key>
<dict>
<key>hash</key>
<data>
jOhqEUF1/xyY+fuswiWT+ELC3dI=
</data>
<key>hash2</key>
<data>
m26DmegPkB5jwUJkVEtLlObYALX8He100Ny0+NNJg/g=
</data>
</dict>
<key>qfacemodel.bundle/en.lproj/Root.strings</key>
<dict>
<key>hash</key>
<data>
t4KY9Gh4uIiOv7VnHtRrKEuPRY8=
</data>
<key>hash2</key>
<data>
xUzNd7J7w99oAnMIWGe1dAGArHMuEXwQqxSziDU5vLk=
</data>
<key>optional</key>
<true/>
</dict>
<key>qfacemodel.bundle/liveness.dat</key>
<dict>
<key>hash</key>
<data>
sA83GQyyexPEwRVNpYRus1ioaVk=
</data>
<key>hash2</key>
<data>
j6ELKAO2BUH0nNrmrslAIwA4lNH8NTutNq0tuFbm2FI=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<key>Key</key>
<string>name_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<key>Key</key>
<string>enabled_preference</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
</dict>
</array>
</dict>
</plist>
B/* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */
//
// QsignNotaryApi.h
// sfrzmanage
//
// Created by 卖女孩的小火柴 on 2020/10/21.
// Copyright © 2020 卖女孩的小火柴. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, QsignNotaryErrorCode) {
cancelback = 0, //中途退出
fingerError,//指纹验证错误
nouserError,//未注册
faceError,//人脸比对不通过
personregisterError,//人工审核信息提交失败,请重新注册
qrError,//二维码参数有误
parameerror,//参数错误
biznoError,//缺少业务编号
faceTimeout,//人脸超时
packageerror,//未授权的应用
permissionError,//权限缺失
nofingerError,//尚无指纹请先设置
};
typedef NS_ENUM(NSUInteger, QsignNotaryRegisterCode) {
normalRegister = 0, //正常注册
personService//人工审核
};
//其他成功回调
typedef void (^NotarySuccessCompletion) (void);
typedef void (^NotaryErrorCompletion) (QsignNotaryErrorCode errorcode,NSString* msg);
//注册成功回调
typedef void (^RegisterSuccessCompletion) (QsignNotaryRegisterCode code,NSString* idnumber,NSString* name,NSString* phone);
//激活成功回调
typedef void (^ActiveSuccessCompletion) (NSString* idnumber,NSString* name,NSString* phone);
//活体检测
typedef void (^LivenessSuccessCompletion) (UIImage *__nullable image);
//人证比对
typedef void (^NotaryComparisionSuccessCompletion) (NSString* baseimage);
@interface QsignNotaryApi : NSObject
@property(nonatomic,strong)UIWindow* __nullable newwindow;
@property(nonatomic,strong)NSString* bizno;
@property(nonatomic,assign)BOOL actived;
@property(nonatomic,copy)RegisterSuccessCompletion registersuccess;
@property(nonatomic,copy)ActiveSuccessCompletion activesuccess;
@property(nonatomic,copy)NotarySuccessCompletion notarysuccess;
@property(nonatomic,copy)NotaryErrorCompletion notaryerror;
@property(nonatomic,copy)LivenessSuccessCompletion livenesuccess;
@property(nonatomic,copy)NotaryComparisionSuccessCompletion comparisionsuccess;
+(instancetype)sharedInstance;
-(void)signOutAllview:(Boolean)leftToRight;
/*
*sdk 初始化
production 是否是生产环境,true代表是生产环境,连接的是生产服务器
licensepath 授权文件路径
sdktag 应用标识
active 是否激活
*/
-(BOOL)initQsignWithPath:(Boolean)production licensepath:(NSString*)licensepath sdktag:(NSString*)sdktag active:(BOOL)actived;//初始化
/*
*sdk 初始化
production 是否是生产环境,true代表是生产环境,连接的是生产服务器
licenseStr 授权文件字符串
sdktag 应用标识
active 是否激活
*/
-(BOOL)initQsignWithStr:(Boolean)production licenseStr:(NSString*)licensestr sdktag:(NSString*)sdktag active:(BOOL)actived;
/*
* 获取指纹打开/关闭状态
*/
-(BOOL)getFingerOpened;
/*
* 查询是否有用户 bizno业务编号,不能为空
*/
-(BOOL)haveUser:(NSString*)bizno;
/*
* 注册
bizno 业务编号,可为空;为空就默认为身份证号;name 姓名;locknamed=true,姓名不可编辑并且不能为空,=false 姓名可为空
*/
-(void)registerNotary:(NSString*)bizno name:(NSString*)name idnumber:(NSString*)idnumber lock:(BOOL)locked successHandler:(RegisterSuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 实名认证
*/
-(void)identifyNotary:(NSString*)name idnumber:(NSString*)idnumber phone:(NSString*)phone successHandler:(RegisterSuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 人脸-人证比对
姓名 身份证号
*/
-(void)qsignLivenessNotary:(NSString*)name idnumber:(NSString*)idnumber successHandler:(NotaryComparisionSuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 获取活体人脸图片
*/
-(void)livenessDetceFace:(UIViewController*)viewcontroller successHandler:(LivenessSuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 激活
bizno 业务编号,不能为空
*/
-(void)activeNotary:(NSString*)bizno successHandler:(ActiveSuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 设置手写签名
*/
-(void)setWriteImgNotary:(NSString*)bizno successHandler:(NotarySuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 打开关闭指纹
*/
-(void)setFingerNotary:(NotarySuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 忘记PIN
*/
-(void)forgerPINNotary:(NotarySuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 修改手机号
*/
-(void)modifyPhoneNotary:(NotarySuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 扫码签署
result 二维码值,规则:KZB:2:*:*:*:*:,以KZB开头,转换为数组后,数组的count==6,数组第二个元素==2
*/
-(void)scanQrSignNotary:(NSString*)result valide:(Boolean)facevalide successHandler:(NotarySuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 网页签署
*/
-(void)webSignNotary:(NSString*)signurl successHandler:(NotarySuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 扫码登录
result 二维码值
*/
-(void)scanLogin:(NSString*)result successHandler:(NotarySuccessCompletion)successhandle errorHandle:(NotaryErrorCompletion)errorHandle;
/*
* 获取http签名
*/
-(NSString*)getSignature:(NSString*)param;
/*
* 获取token
*/
-(NSString*)getToken;
@end
NS_ASSUME_NONNULL_END
//
// QsignNotarySDK.h
// QsignNotarySDK
//
// Created by 卖女孩的小火柴 on 2020/10/23.
// Copyright © 2020 卖女孩的小火柴. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for QsignNotarySDK.
FOUNDATION_EXPORT double QsignNotarySDKVersionNumber;
//! Project version string for QsignNotarySDK.
FOUNDATION_EXPORT const unsigned char QsignNotarySDKVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <QsignNotarySDK/PublicHeader.h>
#import <QsignNotarySDK/QsignNotaryApi.h>
LICENSE ISSUES
==============
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts. Actually both licenses are BSD-style
Open Source licenses. In case of any license issues related to OpenSSL
please contact openssl-core@openssl.org.
OpenSSL License
---------------
/* ====================================================================
* Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
framework module QsignNotarySDK {
umbrella header "QsignNotarySDK.h"
export *
module * { export * }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/QsignNotaryApi.h</key>
<data>
Kgwq2VkHjn37kzONWwXOZDqx28I=
</data>
<key>Headers/QsignNotarySDK.h</key>
<data>
40z8VCIst6VOO99V7pi3t7Xk16E=
</data>
<key>Info.plist</key>
<data>
P89RvJUf1Doe35Qdnn9GWezeROk=
</data>
<key>LICENSE</key>
<data>
ycUL1Gtpq6YuYcZdirCN0ejIOzg=
</data>
<key>Modules/module.modulemap</key>
<data>
8f6nBLvQ8USiU41QzDuGT+XGIhk=
</data>
<key>SVProgressHUD.bundle/angle-mask.png</key>
<data>
oqIJzVxhZua/CZX+TGK3kylFilY=
</data>
<key>SVProgressHUD.bundle/angle-mask@2x.png</key>
<data>
3aAb8SeX29Ro7z1pt6A1yqUAaHs=
</data>
<key>SVProgressHUD.bundle/angle-mask@3x.png</key>
<data>
pPD0GLNI2PnWq2CX6UyQ9H52T9g=
</data>
<key>SVProgressHUD.bundle/error.png</key>
<data>
oP6f/Zad0pEL8xrimTdNlSXrrpA=
</data>
<key>SVProgressHUD.bundle/error@2x.png</key>
<data>
cFCuvbmEkaKmhj2RThSqw/5KUtM=
</data>
<key>SVProgressHUD.bundle/error@3x.png</key>
<data>
QSlxhLYpqk8M4tlq+X0hXbamUH0=
</data>
<key>SVProgressHUD.bundle/info.png</key>
<data>
CP1bXzRkp6v+a6oAHECMgzhmOIU=
</data>
<key>SVProgressHUD.bundle/info@2x.png</key>
<data>
yx+ZQImmZJ+j/av7X/uJpzaqomU=
</data>
<key>SVProgressHUD.bundle/info@3x.png</key>
<data>
5MgHR68ek5Ayg9vc2oGqk1wMpdQ=
</data>
<key>SVProgressHUD.bundle/success.png</key>
<data>
oQ/IlYYGw5vH/rx4pqvYiNddu8c=
</data>
<key>SVProgressHUD.bundle/success@2x.png</key>
<data>
P1jXd1XGKWq/KG50KF6pWjBVwBo=
</data>
<key>SVProgressHUD.bundle/success@3x.png</key>
<data>
hmliT+WZg212OTNmAhP+uSOyYio=
</data>
<key>com.cn.weslink.qsign.bundle/Root.plist</key>
<data>
jOhqEUF1/xyY+fuswiWT+ELC3dI=
</data>
<key>com.cn.weslink.qsign.bundle/addressicon@2x.png</key>
<data>
aBz8GyJrkwNqa+KHxpB2PX4Dvbs=
</data>
<key>com.cn.weslink.qsign.bundle/addressicon@3x.png</key>
<data>
aDoD7yPmfVjy0Jl74pooL/wv7FA=
</data>
<key>com.cn.weslink.qsign.bundle/backimg@2x.png</key>
<data>
FKFR3OhkzSchhgOyhB0e0McFfA0=
</data>
<key>com.cn.weslink.qsign.bundle/backimg@3x.png</key>
<data>
jr0ajI9lKOdQs8sbqToLnN5tFTI=
</data>
<key>com.cn.weslink.qsign.bundle/bluecheck@2x.png</key>
<data>
QNAHrhGx5iPcXa2xQkGTkeBJTo4=
</data>
<key>com.cn.weslink.qsign.bundle/bluecheck@3x.png</key>
<data>
9r2u2d7vGPj6VTDq57gtBtyBNT0=
</data>
<key>com.cn.weslink.qsign.bundle/blueuncheck@2x.png</key>
<data>
SPn9VNBq6qfQ2sJq/ZmdvW065bo=
</data>
<key>com.cn.weslink.qsign.bundle/blueuncheck@3x.png</key>
<data>
Juv1Z0qbVcQcn4JhSqgUb1vTy2s=
</data>
<key>com.cn.weslink.qsign.bundle/camerashure@2x.png</key>
<data>
Q1Meh9S703WDgXBnWi6492qxO3Q=
</data>
<key>com.cn.weslink.qsign.bundle/camerashure@3x.png</key>
<data>
uh19QAVA/lgBlLP8ML5zPKbFeXg=
</data>
<key>com.cn.weslink.qsign.bundle/cuowu.png</key>
<data>
7/ymSvB/YYh/qKAHIsomWouncjw=
</data>
<key>com.cn.weslink.qsign.bundle/delete@2x.png</key>
<data>
G9cQvANyXut7gkoI8qEGxSwhVw4=
</data>
<key>com.cn.weslink.qsign.bundle/delete@3x.png</key>
<data>
ttFS7hGysZLGX0w5A6Jy19NGCmk=
</data>
<key>com.cn.weslink.qsign.bundle/en.lproj/Root.strings</key>
<dict>
<key>hash</key>
<data>
t4KY9Gh4uIiOv7VnHtRrKEuPRY8=
</data>
<key>optional</key>
<true/>
</dict>
<key>com.cn.weslink.qsign.bundle/facecover.png</key>
<data>
r6tklqDJ+TNBCrc4s2admWyD330=
</data>
<key>com.cn.weslink.qsign.bundle/idcardback@2x.png</key>
<data>
nifqXKslkFdk9djrw9umcHnBXgc=
</data>
<key>com.cn.weslink.qsign.bundle/idcardback@3x.png</key>
<data>
eU9C+GutnqVP4skopB+GJoWZUOg=
</data>
<key>com.cn.weslink.qsign.bundle/idcardfront@2x.png</key>
<data>
EEKvSyQVgZnqVcSqc5/4GRo1svc=
</data>
<key>com.cn.weslink.qsign.bundle/idcardfront@3x.png</key>
<data>
z/Ti8/MWQWiY9ANtzvGEVPh8S+U=
</data>
<key>com.cn.weslink.qsign.bundle/jiantoudown@2x.png</key>
<data>
O2TUdrbglbK9Q5ml9WG7LGTakzM=
</data>
<key>com.cn.weslink.qsign.bundle/jiantoudown@3x.png</key>
<data>
Sfh/gffrcuDiVNAnp5Dt4/8i5xU=
</data>
<key>com.cn.weslink.qsign.bundle/jiantouright@2x.png</key>
<data>
+iQK6DKjKUfUxGjOUwODB0b+Gb8=
</data>
<key>com.cn.weslink.qsign.bundle/jiantouright@3x.png</key>
<data>
E+ZXps9HyGCoW/ww66pRiSpIF2k=
</data>
<key>com.cn.weslink.qsign.bundle/lizi.png</key>
<data>
xwAqPCF1pphjvp3lb0CLbWQQsnI=
</data>
<key>com.cn.weslink.qsign.bundle/personbac.png</key>
<data>
SfuxbjXkLImh4ceua0D6K5ls88c=
</data>
<key>com.cn.weslink.qsign.bundle/phonenoreal@2x.png</key>
<data>
6AquNHhRO5nx+T3nKjDAoLJSklI=
</data>
<key>com.cn.weslink.qsign.bundle/phonenoreal@3x.png</key>
<data>
bnLBZf0A2ocSk5e48E7X1qsu1z4=
</data>
<key>com.cn.weslink.qsign.bundle/qsign_area.txt</key>
<data>
rl1C/kYve6kJfD2nQhgIP6CFzHw=
</data>
<key>com.cn.weslink.qsign.bundle/quan.png</key>
<data>
CTkPmB7Z7Bo6hwkqj6t+o6UgcEw=
</data>
<key>com.cn.weslink.qsign.bundle/randicon@2x.png</key>
<data>
FdEMjLfbklXfZJkI9bpuPVaX4Ak=
</data>
<key>com.cn.weslink.qsign.bundle/randicon@3x.png</key>
<data>
uJ5+El+vb3838zHoz+zToMYG9rQ=
</data>
<key>com.cn.weslink.qsign.bundle/registercode@2x.png</key>
<data>
Oj2arOm1P5yDbqo9NPUtXb3Wpso=
</data>
<key>com.cn.weslink.qsign.bundle/registercode@3x.png</key>
<data>
yvr6bCacUMjur86r7GriCFYHlYg=
</data>
<key>com.cn.weslink.qsign.bundle/registererror@2x.png</key>
<data>
qgkoluuBFWtpwyLmyG4N/olrMfY=
</data>
<key>com.cn.weslink.qsign.bundle/registererror@3x.png</key>
<data>
NuCd4HWhbVsMyFNYgKZWlbixw5I=
</data>
<key>com.cn.weslink.qsign.bundle/registeridcardback@2x.png</key>
<data>
cstoW7gLECUf1tXYHw33XpcGkbI=
</data>
<key>com.cn.weslink.qsign.bundle/registeridcardback@3x.png</key>
<data>
QI8x0KUNheszG6Q1djF7i2CF5oI=
</data>
<key>com.cn.weslink.qsign.bundle/registeridcardfont@2x.png</key>
<data>
AxIRAO7VwDjfhm9AlMuz5WVFKP8=
</data>
<key>com.cn.weslink.qsign.bundle/registeridcardfont@3x.png</key>
<data>
nsam5VNFKXIfLlrBFr6YL1KN1sI=
</data>
<key>com.cn.weslink.qsign.bundle/registeridnum@2x.png</key>
<data>
3Sa+Rcy7Uj+TASXcHrjVDV9twKI=
</data>
<key>com.cn.weslink.qsign.bundle/registeridnum@3x.png</key>
<data>
pRDSl0O8zAe5nwWrNiBBksVoTKk=
</data>
<key>com.cn.weslink.qsign.bundle/registerlab@2x.png</key>
<data>
swy9hxFVls7TjDX/nhAQ/N4Q2CU=
</data>
<key>com.cn.weslink.qsign.bundle/registerlab@3x.png</key>
<data>
wYpN+nZ+ht1BMlayelVxZQWktp0=
</data>
<key>com.cn.weslink.qsign.bundle/registername@2x.png</key>
<data>
SIz2Y5sEV+brX9Sr5JeWfxVsAWw=
</data>
<key>com.cn.weslink.qsign.bundle/registername@3x.png</key>
<data>
yKRNi0S8GvVP9MpcY/+9m4GOW1o=
</data>
<key>com.cn.weslink.qsign.bundle/registerphone@2x.png</key>
<data>
HokJ7WUJhYXZdf6Kdrmv/oQbLeg=
</data>
<key>com.cn.weslink.qsign.bundle/registerphone@3x.png</key>
<data>
ZWo22ShaQtj6PmuGbuaxu6TneZ8=
</data>
<key>com.cn.weslink.qsign.bundle/registersuccess@2x.png</key>
<data>
4mhlsQBJ9uaYVeiPBk6Icf3kJGM=
</data>
<key>com.cn.weslink.qsign.bundle/registersuccess@3x.png</key>
<data>
gSbsV8isCtWqGdIh9O+4s7BT49c=
</data>
<key>com.cn.weslink.qsign.bundle/renz.png</key>
<data>
apZ2x84FD1Zi69KTkGjEiO0p8iM=
</data>
<key>com.cn.weslink.qsign.bundle/shili.png</key>
<data>
nWuqhuhDmhTB1ipqEGF0oFDW4mM=
</data>
<key>com.cn.weslink.qsign.bundle/smalldelete@2x.png</key>
<data>
BNj8BHbrJlYORogsE3/q7HcT7pQ=
</data>
<key>com.cn.weslink.qsign.bundle/smalldelete@3x.png</key>
<data>
ZDaf4DjmLXJKZo+s2468MEyMA3U=
</data>
<key>com.cn.weslink.qsign.bundle/successimg@2x.png</key>
<data>
twJkw7/jc1WqJ7N+/n1cSxTdKiI=
</data>
<key>com.cn.weslink.qsign.bundle/successimg@3x.png</key>
<data>
ZYr2AjNsICL3tvfKVqerk87/qjo=
</data>
<key>com.cn.weslink.qsign.bundle/upfileadd@2x.png</key>
<data>
xZwuldQDySSG+NaAoiPxoVZY0Pw=
</data>
<key>com.cn.weslink.qsign.bundle/upfileadd@3x.png</key>
<data>
fueW0icV2hb38/zE5mXtXLCa1cU=
</data>
<key>com.cn.weslink.qsign.bundle/upfileexcemp@2x.png</key>
<data>
B7PE6WafNQx/Iof0lQVDkZud+wg=
</data>
<key>com.cn.weslink.qsign.bundle/upfileexcemp@3x.png</key>
<data>
17D/Ng5YdNlWQrGVJ5yWJ9HM93E=
</data>
<key>com.cn.weslink.qsign.bundle/upfileotherside@2x.png</key>
<data>
BbxjKeWsDzoSx+haqLnpOYb6xtM=
</data>
<key>com.cn.weslink.qsign.bundle/upfileotherside@3x.png</key>
<data>
LntJI514KmqEqq8iaCU+Vgr+fAE=
</data>
<key>com.cn.weslink.qsign.bundle/upfilepositive@2x.png</key>
<data>
3xU4qRXDka7+NzCUZqrSzrE9kWE=
</data>
<key>com.cn.weslink.qsign.bundle/upfilepositive@3x.png</key>
<data>
jxCesVnrZhLz0ftNataigDKIVKU=
</data>
<key>com.cn.weslink.qsign.bundle/upfileuser@2x.png</key>
<data>
VFqG3Sad0nfDgUItb6mXY3aPDhk=
</data>
<key>com.cn.weslink.qsign.bundle/upfileuser@3x.png</key>
<data>
zfVmld3V0arfLFYRSBTmhVPSWak=
</data>
<key>com.cn.weslink.qsign.bundle/upfileuserandnumb@2x.png</key>
<data>
ez+iZOdBWAqV2ItO+daRU9ju8c4=
</data>
<key>com.cn.weslink.qsign.bundle/upfileuserandnumb@3x.png</key>
<data>
cOGWltbvk7kkKrKPNCC1agGmiTY=
</data>
<key>com.cn.weslink.qsign.bundle/upfilevideo@2x.png</key>
<data>
Xvk5yIGP2xoDeAF1keuAClIv4jY=
</data>
<key>com.cn.weslink.qsign.bundle/upfilevideo@3x.png</key>
<data>
Q5bib22WSbp3md6hp3k97LtCEeE=
</data>
<key>com.cn.weslink.qsign.bundle/ushead@2x.png</key>
<data>
h5s7a8xYBV/1+t0CxsY7EdWbrR8=
</data>
<key>com.cn.weslink.qsign.bundle/ushead@3x.png</key>
<data>
doXvIYSDikXd+raHihmowRI+5Nk=
</data>
<key>com.cn.weslink.qsign.bundle/usheadwithid@2x.png</key>
<data>
fiOoX2BZ9xXs//1TGHF4Ts93zyQ=
</data>
<key>com.cn.weslink.qsign.bundle/usheadwithid@3x.png</key>
<data>
dEvMJzoYoy/flInaZOReyW3AKVQ=
</data>
<key>com.cn.weslink.qsign.bundle/validp.png</key>
<data>
Bl2P5+72uj3xjmyDCb9M8/QhG4o=
</data>
<key>com.cn.weslink.qsign.bundle/videoagain3x.png</key>
<data>
4+GcZbMIr3FKcr86PldhOHHM/DU=
</data>
<key>com.cn.weslink.qsign.bundle/videoagain@2x.png</key>
<data>
ecKA5Bnj4eO3lJKjSg0lnlB4Loc=
</data>
<key>com.cn.weslink.qsign.bundle/videoshure@2x.png</key>
<data>
tcgbbrBdTu575I0jRHdqO9ADVEA=
</data>
<key>com.cn.weslink.qsign.bundle/videoshure@3x.png</key>
<data>
xedh0Ns+T417AMD+l6bTKCW2Zvs=
</data>
<key>com.cn.weslink.qsign.bundle/warn2@2x.png</key>
<data>
mdv7rwnPqbJ0pdvPAUJOVGhgJ9U=
</data>
<key>com.cn.weslink.qsign.bundle/warn2@3x.png</key>
<data>
8Pfr0Xzr7M79QTK9FvBiNI+FpM8=
</data>
<key>com.cn.weslink.qsign.bundle/warnred@2x.png</key>
<data>
EmgFcvrPAhm0gwl03u3Ml1d8OTY=
</data>
<key>com.cn.weslink.qsign.bundle/warnred@3x.png</key>
<data>
tSq3iwB3YvrpatheiJI0YF1uKco=
</data>
<key>com.cn.weslink.qsign.bundle/whitedelete@2x.png</key>
<data>
bysVp3pMYZ257InOmSGiqasJNdA=
</data>
<key>com.cn.weslink.qsign.bundle/whitedelete@3x.png</key>
<data>
2yyVtv72nBdH6CF6oLBGcis2vHo=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/QsignNotaryApi.h</key>
<dict>
<key>hash</key>
<data>
Kgwq2VkHjn37kzONWwXOZDqx28I=
</data>
<key>hash2</key>
<data>
1rDMMmDXPukmhAmkAW+sfnyQzMPw3u/isJ25J5bySqE=
</data>
</dict>
<key>Headers/QsignNotarySDK.h</key>
<dict>
<key>hash</key>
<data>
40z8VCIst6VOO99V7pi3t7Xk16E=
</data>
<key>hash2</key>
<data>
u2oOv4+ybS5poVltDqvBmZ6RBkYqi+pyD1qOcme8NAI=
</data>
</dict>
<key>LICENSE</key>
<dict>
<key>hash</key>
<data>
ycUL1Gtpq6YuYcZdirCN0ejIOzg=
</data>
<key>hash2</key>
<data>
NW5CJe0HffJYaGeVeXhBBLG3pXUuusxzBKLU7A8Z6Wg=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash</key>
<data>
8f6nBLvQ8USiU41QzDuGT+XGIhk=
</data>
<key>hash2</key>
<data>
2czIAKaG7Y5YeLtWTvZVJkMNumgFEV6PI3JM5jFx/WQ=
</data>
</dict>
<key>SVProgressHUD.bundle/angle-mask.png</key>
<dict>
<key>hash</key>
<data>
oqIJzVxhZua/CZX+TGK3kylFilY=
</data>
<key>hash2</key>
<data>
DDw2jnXp1WjofT+IkD6qy3+dLIzDE9vrxNSPoeQO4jo=
</data>
</dict>
<key>SVProgressHUD.bundle/angle-mask@2x.png</key>
<dict>
<key>hash</key>
<data>
3aAb8SeX29Ro7z1pt6A1yqUAaHs=
</data>
<key>hash2</key>
<data>
6QAJXoYU7vQpTdzUcb2HrKhSj6gCcrZb9r6z0J5yK+w=
</data>
</dict>
<key>SVProgressHUD.bundle/angle-mask@3x.png</key>
<dict>
<key>hash</key>
<data>
pPD0GLNI2PnWq2CX6UyQ9H52T9g=
</data>
<key>hash2</key>
<data>
iwwAX8HeeU70vQudb1L6z80VbnuVeJ+zn94jLMovmKs=
</data>
</dict>
<key>SVProgressHUD.bundle/error.png</key>
<dict>
<key>hash</key>
<data>
oP6f/Zad0pEL8xrimTdNlSXrrpA=
</data>
<key>hash2</key>
<data>
UDk/X+yyN+USnDW9JFp7P9O5irCLZkeybVB1BEDVunA=
</data>
</dict>
<key>SVProgressHUD.bundle/error@2x.png</key>
<dict>
<key>hash</key>
<data>
cFCuvbmEkaKmhj2RThSqw/5KUtM=
</data>
<key>hash2</key>
<data>
Xc9fgzh3g2FX8j9dYqux/gm+73IDul7Vb0KaMAQZo+E=
</data>
</dict>
<key>SVProgressHUD.bundle/error@3x.png</key>
<dict>
<key>hash</key>
<data>
QSlxhLYpqk8M4tlq+X0hXbamUH0=
</data>
<key>hash2</key>
<data>
P6wK1oxOL6vyD7o9q9+hP9jctZaTyluZgm1zpKgw0dM=
</data>
</dict>
<key>SVProgressHUD.bundle/info.png</key>
<dict>
<key>hash</key>
<data>
CP1bXzRkp6v+a6oAHECMgzhmOIU=
</data>
<key>hash2</key>
<data>
GeypxgyrUdKQ8Nyqc9w0q9XLCdtRbk4cJi9EE5QXXs8=
</data>
</dict>
<key>SVProgressHUD.bundle/info@2x.png</key>
<dict>
<key>hash</key>
<data>
yx+ZQImmZJ+j/av7X/uJpzaqomU=
</data>
<key>hash2</key>
<data>
KLsrQZrjUwrsUtZSul1bJbNH8OTb5+YrjaVW+rbl64Q=
</data>
</dict>
<key>SVProgressHUD.bundle/info@3x.png</key>
<dict>
<key>hash</key>
<data>
5MgHR68ek5Ayg9vc2oGqk1wMpdQ=
</data>
<key>hash2</key>
<data>
eer51e9B3uVrPmnlKfYiqok7LLlR6cnUt8JBmo2oG3Y=
</data>
</dict>
<key>SVProgressHUD.bundle/success.png</key>
<dict>
<key>hash</key>
<data>
oQ/IlYYGw5vH/rx4pqvYiNddu8c=
</data>
<key>hash2</key>
<data>
ZneDtnotiia14nbyRklrCVgGmnlPcjpSwUjyHSfPeXc=
</data>
</dict>
<key>SVProgressHUD.bundle/success@2x.png</key>
<dict>
<key>hash</key>
<data>
P1jXd1XGKWq/KG50KF6pWjBVwBo=
</data>
<key>hash2</key>
<data>
hbpOiBtrYWqPZJYnEBIf/dZWn+6rFwHRPp0WzU9gA18=
</data>
</dict>
<key>SVProgressHUD.bundle/success@3x.png</key>
<dict>
<key>hash</key>
<data>
hmliT+WZg212OTNmAhP+uSOyYio=
</data>
<key>hash2</key>
<data>
EMic5PZw5ab7sBUjL5t1YMrH5WnRAJCbgeMLFJgZQ/Q=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/Root.plist</key>
<dict>
<key>hash</key>
<data>
jOhqEUF1/xyY+fuswiWT+ELC3dI=
</data>
<key>hash2</key>
<data>
m26DmegPkB5jwUJkVEtLlObYALX8He100Ny0+NNJg/g=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/addressicon@2x.png</key>
<dict>
<key>hash</key>
<data>
aBz8GyJrkwNqa+KHxpB2PX4Dvbs=
</data>
<key>hash2</key>
<data>
2E6dSsOeAH3i7YtrEW0ekOzB8Mc5QVViET97APvohRM=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/addressicon@3x.png</key>
<dict>
<key>hash</key>
<data>
aDoD7yPmfVjy0Jl74pooL/wv7FA=
</data>
<key>hash2</key>
<data>
agT1JSnhyax+gb6wGjgh337Nlf3GbvZoncYe3XjNMek=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/backimg@2x.png</key>
<dict>
<key>hash</key>
<data>
FKFR3OhkzSchhgOyhB0e0McFfA0=
</data>
<key>hash2</key>
<data>
ux2VN+8GvJSrh44ZzVpkQ2ycW4nwid6UIkEFImUyojw=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/backimg@3x.png</key>
<dict>
<key>hash</key>
<data>
jr0ajI9lKOdQs8sbqToLnN5tFTI=
</data>
<key>hash2</key>
<data>
9ImUpE5U/NewFdToozBrG8VIv5vZIzgSkFYsBY3gfqQ=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/bluecheck@2x.png</key>
<dict>
<key>hash</key>
<data>
QNAHrhGx5iPcXa2xQkGTkeBJTo4=
</data>
<key>hash2</key>
<data>
bO1frl46Cnyan4C6ZcNHtnpQsVJjyJa7O68+DfFC9uU=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/bluecheck@3x.png</key>
<dict>
<key>hash</key>
<data>
9r2u2d7vGPj6VTDq57gtBtyBNT0=
</data>
<key>hash2</key>
<data>
h976flefeWjHGuWLsp/uX7JXf/HzgFaHE6E6gcZlxrY=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/blueuncheck@2x.png</key>
<dict>
<key>hash</key>
<data>
SPn9VNBq6qfQ2sJq/ZmdvW065bo=
</data>
<key>hash2</key>
<data>
iTHmo85ATa5gN9KReICGmP6/+P7iBu+xZCBbf7jzJpk=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/blueuncheck@3x.png</key>
<dict>
<key>hash</key>
<data>
Juv1Z0qbVcQcn4JhSqgUb1vTy2s=
</data>
<key>hash2</key>
<data>
xsHpFu2ZKG8tqUtDMML7TSVZKFedlT1FZvPWzwvD8VQ=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/camerashure@2x.png</key>
<dict>
<key>hash</key>
<data>
Q1Meh9S703WDgXBnWi6492qxO3Q=
</data>
<key>hash2</key>
<data>
9yt1hpE78hneR4+jPksVJ52oOeOkTijf8d6bPbcfYp4=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/camerashure@3x.png</key>
<dict>
<key>hash</key>
<data>
uh19QAVA/lgBlLP8ML5zPKbFeXg=
</data>
<key>hash2</key>
<data>
K1owm6Bx0vA5tNwSE5WLV1ljXlcrbHKGRku1tcOkw5Q=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/cuowu.png</key>
<dict>
<key>hash</key>
<data>
7/ymSvB/YYh/qKAHIsomWouncjw=
</data>
<key>hash2</key>
<data>
wimqAENwg7jHczhfkOmVhgGxSPpTUCIyDQSO52e1NZ0=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/delete@2x.png</key>
<dict>
<key>hash</key>
<data>
G9cQvANyXut7gkoI8qEGxSwhVw4=
</data>
<key>hash2</key>
<data>
e4bFlRFDq5/Jt88W3kRflUzQKRqQDSWPHAIBotJdjEE=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/delete@3x.png</key>
<dict>
<key>hash</key>
<data>
ttFS7hGysZLGX0w5A6Jy19NGCmk=
</data>
<key>hash2</key>
<data>
/buOH3/qArypQvKr692BNEyQx2Xum9y5Odf6LPE8mzw=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/en.lproj/Root.strings</key>
<dict>
<key>hash</key>
<data>
t4KY9Gh4uIiOv7VnHtRrKEuPRY8=
</data>
<key>hash2</key>
<data>
xUzNd7J7w99oAnMIWGe1dAGArHMuEXwQqxSziDU5vLk=
</data>
<key>optional</key>
<true/>
</dict>
<key>com.cn.weslink.qsign.bundle/facecover.png</key>
<dict>
<key>hash</key>
<data>
r6tklqDJ+TNBCrc4s2admWyD330=
</data>
<key>hash2</key>
<data>
MOTtU7cwg4f8hSv3dnbABq3MgnkKGWStzLLOQpxCn1o=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/idcardback@2x.png</key>
<dict>
<key>hash</key>
<data>
nifqXKslkFdk9djrw9umcHnBXgc=
</data>
<key>hash2</key>
<data>
rGfh6QAVpFPb8+6NKqP3GZHUc9INheyayRsE50N1B2A=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/idcardback@3x.png</key>
<dict>
<key>hash</key>
<data>
eU9C+GutnqVP4skopB+GJoWZUOg=
</data>
<key>hash2</key>
<data>
Hz+PZqBHwxYdOBBjTJboK2VdjAWw+XgL3l4iL3z7YVc=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/idcardfront@2x.png</key>
<dict>
<key>hash</key>
<data>
EEKvSyQVgZnqVcSqc5/4GRo1svc=
</data>
<key>hash2</key>
<data>
589vaZotF6yrtpgOIr101HAxX0nkkQR64n4ReA5WtlI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/idcardfront@3x.png</key>
<dict>
<key>hash</key>
<data>
z/Ti8/MWQWiY9ANtzvGEVPh8S+U=
</data>
<key>hash2</key>
<data>
zxHDgXrnVE/x9ARXrulmQkCkOov7OnF/eAGeZ5EgJ7s=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/jiantoudown@2x.png</key>
<dict>
<key>hash</key>
<data>
O2TUdrbglbK9Q5ml9WG7LGTakzM=
</data>
<key>hash2</key>
<data>
RErjw4A7nED9ok4ohZLbXI+/JjgMXwG9nZNSPbUBr9k=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/jiantoudown@3x.png</key>
<dict>
<key>hash</key>
<data>
Sfh/gffrcuDiVNAnp5Dt4/8i5xU=
</data>
<key>hash2</key>
<data>
kvxEsTQRqW8JEjS5tIebCrtvucfFOzFCpf9/010NuWI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/jiantouright@2x.png</key>
<dict>
<key>hash</key>
<data>
+iQK6DKjKUfUxGjOUwODB0b+Gb8=
</data>
<key>hash2</key>
<data>
3S/Q5rvmtx/0GsGXwLZZqrTZV52rCM63m+0QT5Zukgg=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/jiantouright@3x.png</key>
<dict>
<key>hash</key>
<data>
E+ZXps9HyGCoW/ww66pRiSpIF2k=
</data>
<key>hash2</key>
<data>
ii4erDrI+Phgr8AjV73yR2KfGibW3mui9bk+C9A2ed8=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/lizi.png</key>
<dict>
<key>hash</key>
<data>
xwAqPCF1pphjvp3lb0CLbWQQsnI=
</data>
<key>hash2</key>
<data>
0O44E2Z2FM09Ubjg+Grk1tRy//KWeCY8EBu0JnLYjqI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/personbac.png</key>
<dict>
<key>hash</key>
<data>
SfuxbjXkLImh4ceua0D6K5ls88c=
</data>
<key>hash2</key>
<data>
hDflWFB/0EJIxAOOXzXql74KwY+IKIY3doEnG7dQIWY=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/phonenoreal@2x.png</key>
<dict>
<key>hash</key>
<data>
6AquNHhRO5nx+T3nKjDAoLJSklI=
</data>
<key>hash2</key>
<data>
/ypPTiQBq5Ha/TgUf0KtsIUa/wD7xkm3jSIPdh9+Zo4=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/phonenoreal@3x.png</key>
<dict>
<key>hash</key>
<data>
bnLBZf0A2ocSk5e48E7X1qsu1z4=
</data>
<key>hash2</key>
<data>
KWf4ZtMOqNcs/4CiftMg8jZsDqQbr+ftN4avU5y9kqI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/qsign_area.txt</key>
<dict>
<key>hash</key>
<data>
rl1C/kYve6kJfD2nQhgIP6CFzHw=
</data>
<key>hash2</key>
<data>
Iyc9iNLTOeTua3QqGIFkwCOuOAN4K2ok6YZDnbIFHKA=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/quan.png</key>
<dict>
<key>hash</key>
<data>
CTkPmB7Z7Bo6hwkqj6t+o6UgcEw=
</data>
<key>hash2</key>
<data>
yr4F47w9HopC7BemqEvCtyKW9MAzj9LM746awxL0J7Q=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/randicon@2x.png</key>
<dict>
<key>hash</key>
<data>
FdEMjLfbklXfZJkI9bpuPVaX4Ak=
</data>
<key>hash2</key>
<data>
ohUkzVsQxFaJEhNJAiSppySlNoULhKYh39QUahJsG8Q=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/randicon@3x.png</key>
<dict>
<key>hash</key>
<data>
uJ5+El+vb3838zHoz+zToMYG9rQ=
</data>
<key>hash2</key>
<data>
K29UK6QK4NyH87je8qJt3yCw14/soVPoPhyI4GrpWTo=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registercode@2x.png</key>
<dict>
<key>hash</key>
<data>
Oj2arOm1P5yDbqo9NPUtXb3Wpso=
</data>
<key>hash2</key>
<data>
d95EBR1xSUYeVwNcdn1Au2U9zR8wwVL+2ccYOalsbUk=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registercode@3x.png</key>
<dict>
<key>hash</key>
<data>
yvr6bCacUMjur86r7GriCFYHlYg=
</data>
<key>hash2</key>
<data>
VpGIwvupmMwM981hue667+erHjPoqFPlWZ6zDQK1x2U=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registererror@2x.png</key>
<dict>
<key>hash</key>
<data>
qgkoluuBFWtpwyLmyG4N/olrMfY=
</data>
<key>hash2</key>
<data>
RzxCn3535upNYhHyt4H+kj0wYzMhKAEzekrwGF9Bd1U=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registererror@3x.png</key>
<dict>
<key>hash</key>
<data>
NuCd4HWhbVsMyFNYgKZWlbixw5I=
</data>
<key>hash2</key>
<data>
JsMUxIJwyw7gL1rhdTIToKEIB6jdqGSuhNig7eycIFo=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registeridcardback@2x.png</key>
<dict>
<key>hash</key>
<data>
cstoW7gLECUf1tXYHw33XpcGkbI=
</data>
<key>hash2</key>
<data>
ORNtsjiakfUxdQExqTxicc2IredsIAaz8ArlsYKivg4=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registeridcardback@3x.png</key>
<dict>
<key>hash</key>
<data>
QI8x0KUNheszG6Q1djF7i2CF5oI=
</data>
<key>hash2</key>
<data>
Qhp/qWb96MQAnqWhRI1aVX0dhbuQLQv4vH5UHA4ZuvI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registeridcardfont@2x.png</key>
<dict>
<key>hash</key>
<data>
AxIRAO7VwDjfhm9AlMuz5WVFKP8=
</data>
<key>hash2</key>
<data>
EyU0K9N2WAhzofSUK8M6gj01tmQNj+tuJHjpMJY83p0=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registeridcardfont@3x.png</key>
<dict>
<key>hash</key>
<data>
nsam5VNFKXIfLlrBFr6YL1KN1sI=
</data>
<key>hash2</key>
<data>
bzSMU5k5LxhvORqRZZnVx/Unqy9dZ8toXumeMEJjK/8=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registeridnum@2x.png</key>
<dict>
<key>hash</key>
<data>
3Sa+Rcy7Uj+TASXcHrjVDV9twKI=
</data>
<key>hash2</key>
<data>
hO15BBzC6qjnQq5H6chHdp6b0BCmSED06/F2pfhHzz0=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registeridnum@3x.png</key>
<dict>
<key>hash</key>
<data>
pRDSl0O8zAe5nwWrNiBBksVoTKk=
</data>
<key>hash2</key>
<data>
FUTokXyIhB5gLMP9DvAahtIbkq+Q0OrdCZjY6Mqj9hE=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registerlab@2x.png</key>
<dict>
<key>hash</key>
<data>
swy9hxFVls7TjDX/nhAQ/N4Q2CU=
</data>
<key>hash2</key>
<data>
+FPFmOrOuyiSc8cdATiDAJyFHn2UII6/rcuZDAjiA+s=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registerlab@3x.png</key>
<dict>
<key>hash</key>
<data>
wYpN+nZ+ht1BMlayelVxZQWktp0=
</data>
<key>hash2</key>
<data>
nOs2Y4tQlSPBdONQMkyh1fL8ch5ayKOetxo/cUMzi58=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registername@2x.png</key>
<dict>
<key>hash</key>
<data>
SIz2Y5sEV+brX9Sr5JeWfxVsAWw=
</data>
<key>hash2</key>
<data>
tYgiJLqg/mKHxEJnbMoOk1IMqJEfUZFhc/d+kRUBeTQ=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registername@3x.png</key>
<dict>
<key>hash</key>
<data>
yKRNi0S8GvVP9MpcY/+9m4GOW1o=
</data>
<key>hash2</key>
<data>
F2vot0k0m2W3dZmF0X0pTA/hHVhRXZvGgEWjWF8v5DI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registerphone@2x.png</key>
<dict>
<key>hash</key>
<data>
HokJ7WUJhYXZdf6Kdrmv/oQbLeg=
</data>
<key>hash2</key>
<data>
YEDvDJfv3HAPM7w6Pzux5JhvfA5Q6x0une1PSIv2b0w=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registerphone@3x.png</key>
<dict>
<key>hash</key>
<data>
ZWo22ShaQtj6PmuGbuaxu6TneZ8=
</data>
<key>hash2</key>
<data>
FNuw6NLq1NRcgtZsvZqwGfj9zoS4sMjiskvSysup2kM=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registersuccess@2x.png</key>
<dict>
<key>hash</key>
<data>
4mhlsQBJ9uaYVeiPBk6Icf3kJGM=
</data>
<key>hash2</key>
<data>
QbHHkze3L4yMdvUZGDde01uO3RrWTo6Xz6BVE8G81DE=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/registersuccess@3x.png</key>
<dict>
<key>hash</key>
<data>
gSbsV8isCtWqGdIh9O+4s7BT49c=
</data>
<key>hash2</key>
<data>
XCIYE1zaRA0outnlgQ1xD33/GfAtqXlK9xghnpAtJRU=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/renz.png</key>
<dict>
<key>hash</key>
<data>
apZ2x84FD1Zi69KTkGjEiO0p8iM=
</data>
<key>hash2</key>
<data>
6UtOrmQQrUkLrXhJxDZUgmBvdsMFETunJ+1432rnHx8=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/shili.png</key>
<dict>
<key>hash</key>
<data>
nWuqhuhDmhTB1ipqEGF0oFDW4mM=
</data>
<key>hash2</key>
<data>
e5nNJWhqT1aS0PVjIy/nQ6fR3phnidHN7VjyUxAxsaI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/smalldelete@2x.png</key>
<dict>
<key>hash</key>
<data>
BNj8BHbrJlYORogsE3/q7HcT7pQ=
</data>
<key>hash2</key>
<data>
z5BBiNgwdrvcRd3SzW+FzHFQVniC7TSG+DPyaa7lL9U=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/smalldelete@3x.png</key>
<dict>
<key>hash</key>
<data>
ZDaf4DjmLXJKZo+s2468MEyMA3U=
</data>
<key>hash2</key>
<data>
AqsSmdGkAMHdsbp6TEesoIjxA+ji5qMMghdhSp5rT3c=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/successimg@2x.png</key>
<dict>
<key>hash</key>
<data>
twJkw7/jc1WqJ7N+/n1cSxTdKiI=
</data>
<key>hash2</key>
<data>
5nVnhmpt8TJYaXuTycwzcq4gS8Fg2YKmkLoh3XcFdQI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/successimg@3x.png</key>
<dict>
<key>hash</key>
<data>
ZYr2AjNsICL3tvfKVqerk87/qjo=
</data>
<key>hash2</key>
<data>
D9CYN8CwESrv/O8pT1ATmFvIY8IIIIaaQoTxCgIkd4Y=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileadd@2x.png</key>
<dict>
<key>hash</key>
<data>
xZwuldQDySSG+NaAoiPxoVZY0Pw=
</data>
<key>hash2</key>
<data>
J1eTaEe+FAo+i7cu2fE0mMfWmxbYsGCumO0qocO+dPM=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileadd@3x.png</key>
<dict>
<key>hash</key>
<data>
fueW0icV2hb38/zE5mXtXLCa1cU=
</data>
<key>hash2</key>
<data>
NvFO5HY92/f9cW+xIzqPFu2d7h0TTOP+c3R+5ZconnM=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileexcemp@2x.png</key>
<dict>
<key>hash</key>
<data>
B7PE6WafNQx/Iof0lQVDkZud+wg=
</data>
<key>hash2</key>
<data>
pvFqvwr+GH2s1jLHTW7MiP/lC4YFO6lv06xHe48xMy4=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileexcemp@3x.png</key>
<dict>
<key>hash</key>
<data>
17D/Ng5YdNlWQrGVJ5yWJ9HM93E=
</data>
<key>hash2</key>
<data>
5WXQCgEIEUKhO9ZGPHuPfIXOv/tNfZaVCFt5kUiozds=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileotherside@2x.png</key>
<dict>
<key>hash</key>
<data>
BbxjKeWsDzoSx+haqLnpOYb6xtM=
</data>
<key>hash2</key>
<data>
VgLavx6lrIu0/ZKLpPpNRalAdCAvaqesfLw+tZfeszk=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileotherside@3x.png</key>
<dict>
<key>hash</key>
<data>
LntJI514KmqEqq8iaCU+Vgr+fAE=
</data>
<key>hash2</key>
<data>
LfiX16VJQ/dMFt7sxsFOkLayMya8D4aFaqTgo5wfIUA=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfilepositive@2x.png</key>
<dict>
<key>hash</key>
<data>
3xU4qRXDka7+NzCUZqrSzrE9kWE=
</data>
<key>hash2</key>
<data>
2RMJWv/Npx/BHuIGk/z7kcveh/lDAx/0Brp39qbc8ow=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfilepositive@3x.png</key>
<dict>
<key>hash</key>
<data>
jxCesVnrZhLz0ftNataigDKIVKU=
</data>
<key>hash2</key>
<data>
mkC5CkQPKChLwMuJmkLGFlBP2DRmufmvSgdpzwZvo8k=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileuser@2x.png</key>
<dict>
<key>hash</key>
<data>
VFqG3Sad0nfDgUItb6mXY3aPDhk=
</data>
<key>hash2</key>
<data>
C+/i+++M1L9+nCsg+Pto+lvt17VtXFpjypC0Nj05oY8=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileuser@3x.png</key>
<dict>
<key>hash</key>
<data>
zfVmld3V0arfLFYRSBTmhVPSWak=
</data>
<key>hash2</key>
<data>
rKnkCSmqoe8FtniPHy3umh7SpOi+ZjcUGfPJROfc8+E=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileuserandnumb@2x.png</key>
<dict>
<key>hash</key>
<data>
ez+iZOdBWAqV2ItO+daRU9ju8c4=
</data>
<key>hash2</key>
<data>
+6JqGIj4HQRFO5cYO1slAwSSi7JptUNCaepBh98AKsc=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfileuserandnumb@3x.png</key>
<dict>
<key>hash</key>
<data>
cOGWltbvk7kkKrKPNCC1agGmiTY=
</data>
<key>hash2</key>
<data>
/OyJNGnZkzQF3P4RO3EZtPobMmhhST3ITis7vEaPb9A=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfilevideo@2x.png</key>
<dict>
<key>hash</key>
<data>
Xvk5yIGP2xoDeAF1keuAClIv4jY=
</data>
<key>hash2</key>
<data>
GdDNRmZaqLLInFS4WZb7b7V6xIyj0uOAzN6kbI+551A=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/upfilevideo@3x.png</key>
<dict>
<key>hash</key>
<data>
Q5bib22WSbp3md6hp3k97LtCEeE=
</data>
<key>hash2</key>
<data>
gnYcrtq/85vpG5pF4m0p1RfK5suJ9AUwas7JSO9bCRQ=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/ushead@2x.png</key>
<dict>
<key>hash</key>
<data>
h5s7a8xYBV/1+t0CxsY7EdWbrR8=
</data>
<key>hash2</key>
<data>
/VIRf6wUf0FA5wfux2KmAVBpDL0nyUVbHTubx2PeP8c=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/ushead@3x.png</key>
<dict>
<key>hash</key>
<data>
doXvIYSDikXd+raHihmowRI+5Nk=
</data>
<key>hash2</key>
<data>
BO3b0o+HB/aZI8k08Rsn4GxTFe8ZuuveP7fB6B6hpBY=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/usheadwithid@2x.png</key>
<dict>
<key>hash</key>
<data>
fiOoX2BZ9xXs//1TGHF4Ts93zyQ=
</data>
<key>hash2</key>
<data>
YVWN47keaXupgodkgtnNhHD4+xo9bj6lPzLHmQ1x6jk=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/usheadwithid@3x.png</key>
<dict>
<key>hash</key>
<data>
dEvMJzoYoy/flInaZOReyW3AKVQ=
</data>
<key>hash2</key>
<data>
g8bUGj+TgBtEXk7ZVhQD1GMxu8SbJo95opbqZ+WWQRU=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/validp.png</key>
<dict>
<key>hash</key>
<data>
Bl2P5+72uj3xjmyDCb9M8/QhG4o=
</data>
<key>hash2</key>
<data>
2cp2Q5aNY0QMUy2d5NsrfABAE9Sl7eUmjY+pA8DK64U=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/videoagain3x.png</key>
<dict>
<key>hash</key>
<data>
4+GcZbMIr3FKcr86PldhOHHM/DU=
</data>
<key>hash2</key>
<data>
S7OD9pwuv/2LZWYuQ0IndmDpAhPIt+CqaMHIr+y94wc=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/videoagain@2x.png</key>
<dict>
<key>hash</key>
<data>
ecKA5Bnj4eO3lJKjSg0lnlB4Loc=
</data>
<key>hash2</key>
<data>
TtCmvldclzuzKNzYqDwoQtiyJ4991qIik5XcygUIFEo=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/videoshure@2x.png</key>
<dict>
<key>hash</key>
<data>
tcgbbrBdTu575I0jRHdqO9ADVEA=
</data>
<key>hash2</key>
<data>
s1a7gp+i+x5lKmhIoRkCuGdeH6rtKWeuLAd+cEL2c64=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/videoshure@3x.png</key>
<dict>
<key>hash</key>
<data>
xedh0Ns+T417AMD+l6bTKCW2Zvs=
</data>
<key>hash2</key>
<data>
UXU4jGcViMxBcXOfH1zQzete9lBN2GKwSj0r+F7F0eE=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/warn2@2x.png</key>
<dict>
<key>hash</key>
<data>
mdv7rwnPqbJ0pdvPAUJOVGhgJ9U=
</data>
<key>hash2</key>
<data>
32yDVL7gt8al9+ZdfJzMc1+VWelsJJd1gz0kVwOFLgg=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/warn2@3x.png</key>
<dict>
<key>hash</key>
<data>
8Pfr0Xzr7M79QTK9FvBiNI+FpM8=
</data>
<key>hash2</key>
<data>
uO9lnyZiFSrCLRpKgDqjHK4v7xHSa+laO/MGbLmUckI=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/warnred@2x.png</key>
<dict>
<key>hash</key>
<data>
EmgFcvrPAhm0gwl03u3Ml1d8OTY=
</data>
<key>hash2</key>
<data>
J1NmMgvD1GZY8YATrQSE7BTSwt7or1zk6oZE46pRwaw=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/warnred@3x.png</key>
<dict>
<key>hash</key>
<data>
tSq3iwB3YvrpatheiJI0YF1uKco=
</data>
<key>hash2</key>
<data>
N23LXw+4NNWgebmRkok6zwT2ZLlucF3GZxVCBap+QMg=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/whitedelete@2x.png</key>
<dict>
<key>hash</key>
<data>
bysVp3pMYZ257InOmSGiqasJNdA=
</data>
<key>hash2</key>
<data>
/n65anpwPotqRxqwDADCUqlYlnQzSX9m0kl5EZSnNO8=
</data>
</dict>
<key>com.cn.weslink.qsign.bundle/whitedelete@3x.png</key>
<dict>
<key>hash</key>
<data>
2yyVtv72nBdH6CF6oLBGcis2vHo=
</data>
<key>hash2</key>
<data>
PG9GQBByDW//0U6SzI3BvMABmTuRWTCau94Xfqn7PvA=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<key>Key</key>
<string>name_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<key>Key</key>
<string>enabled_preference</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
</dict>
</array>
</dict>
</plist>
B/* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */
//
// QsignSafeKeyApi.h
// QsignSafeKey
//
// Created by 卖女孩的小火柴 on 2021/3/18.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger,TouchIDErrorCode){
Error_notopentouchid=1,//没有打开touchid
Error_pinerror=2,//pin输入错误
Error_getpinerror=3//从keychain获取pin失败
};
typedef void (^OpenTIDSuccessBlock)(void);
typedef void (^OpenTIDFailBlock)(TouchIDErrorCode error);
typedef void (^SignSuccessBlock)(NSString* signdata);
typedef void (^SignFailBlock)(TouchIDErrorCode error);
@interface QsignSafeKeyApi : NSObject
+(instancetype)shareInstance;
-(BOOL)initIGM:(NSString*)url tag:(NSString*)tag;
/*
*生成公私钥对 参数:auxi(唯一特征值 身份证号) userid(用户身份证号) PIN是明文不能加密 如123456(sdk内部已有加密)
*返回NSString对象数组NSMutableDictionary 私钥键值为:pri 公钥键值为:pub
*/
-(NSMutableDictionary*)general_SM2Key:(NSString*)auxi userid:(NSString*)userid pin:(NSString*)pin;
/*
*判断输入的私钥和pin是否匹配 参数:私钥为16进制字符串 PIN是明文不能加密 如123456(sdk内部已有加密) 公钥16进制、 userid用户唯一标识
*/
-(BOOL)validePIN:(NSString*)pin pri:(NSString*)prikey pub:(NSString*)pubkey user:(NSString*)userid;
/*
*修改PIN返回新的私钥密文 参数:私钥为16进制字符串 新老PIN是明文不能加密 如123456(sdk内部已有加密) 公钥16进制、 userid用户唯一标识
*/
-(NSString*)modifyPIN:(NSString*)oldpin newpin:(NSString*)newpin pri:(NSString*)prikey pub:(NSString*)pubkey user:(NSString*)userid;
/*
*数据裸签名 参数:origindata(源数据) PIN是明文不能加密 如123456(sdk内部已有加密) userid(用户身份证号)
*/
-(NSString*)signData:(NSString*)origindata pin:(NSString*)pinstr pri:(NSString*)prikey pub:(NSString*)pubkey user:(NSString*)userid;
//关闭或打开指纹代替PIN
-(void)setTouchID:(NSString *)prikey pub:(NSString*)pubkey user:(NSString*)userid successBlock:(OpenTIDSuccessBlock)successblock errorBlock:(OpenTIDFailBlock)failedblock;
//强制关闭touchID
-(void)forcedCloseTouchID;
//弹出口令框或指纹并签名数据 jsondata源数据
-(void)signDataAlert:(NSString*)origindata pri:(NSString*)prikey pub:(NSString*)pubkey user:(NSString*)userid successBlock:(SignSuccessBlock)successblock errorBlock:(SignFailBlock)failedblock;
-(void)signOpenIdAlert:(NSString*)origindata pri:(NSString*)prikey pub:(NSString*)pubkey user:(NSString*)userid openID:(NSString*)openid successBlock:(SignSuccessBlock)successblock errorBlock:(SignFailBlock)failedblock;
//查询是否开启指纹或faceID
-(BOOL)touchIDIsopen;
@end
NS_ASSUME_NONNULL_END
//
// QsignSafeSDK.h
// QsignSafeSDK
//
// Created by 卖女孩的小火柴 on 2022/9/16.
//
#import <Foundation/Foundation.h>
//! Project version number for QsignSafeSDK.
FOUNDATION_EXPORT double QsignSafeSDKVersionNumber;
//! Project version string for QsignSafeSDK.
FOUNDATION_EXPORT const unsigned char QsignSafeSDKVersionString[];
#import <QsignSafeSDK/QsignSafeKeyApi.h>
// In this header, you should import all the public headers of your framework using statements like #import <QsignSafeSDK/PublicHeader.h>
framework module QsignSafeSDK {
umbrella header "QsignSafeSDK.h"
export *
module * { export * }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<key>Key</key>
<string>name_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<key>Key</key>
<string>enabled_preference</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
</dict>
</array>
</dict>
</plist>
B/* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/QsignSafeKeyApi.h</key>
<data>
BgfBn/+aTUdrrVIYbDUy5khEYGU=
</data>
<key>Headers/QsignSafeSDK.h</key>
<data>
xRVIWD4U+rLDUxK85aba+oH3xNY=
</data>
<key>Info.plist</key>
<data>
N/FSqodrDck3YA+fq2XcQaJxii8=
</data>
<key>Modules/module.modulemap</key>
<data>
gc0R5ZZtr60iaB4RS1wWdr7MOFQ=
</data>
<key>Qsignsafekey.bundle/Root.plist</key>
<data>
jOhqEUF1/xyY+fuswiWT+ELC3dI=
</data>
<key>Qsignsafekey.bundle/delete@2x.png</key>
<data>
bn7f8LWSMgHj05hFraX5g2X2nVw=
</data>
<key>Qsignsafekey.bundle/delete@3x.png</key>
<data>
YQivYSc04xJzjWLtdKCKizf8xYg=
</data>
<key>Qsignsafekey.bundle/en.lproj/Root.strings</key>
<dict>
<key>hash</key>
<data>
t4KY9Gh4uIiOv7VnHtRrKEuPRY8=
</data>
<key>optional</key>
<true/>
</dict>
<key>Qsignsafekey.bundle/password_loading_a@2x.png</key>
<data>
KJ0J29Kmc9G1My8eKBLXZocAhpg=
</data>
<key>Qsignsafekey.bundle/password_loading_b@2x.png</key>
<data>
vdk5gwErtXtbwVKQJBL/DvFlBaE=
</data>
<key>Qsignsafekey.bundle/password_success@2x.png</key>
<data>
JwVBpUMfAybYoDPkuLcyrStoacE=
</data>
<key>Qsignsafekey.bundle/x@2x.png</key>
<data>
BNj8BHbrJlYORogsE3/q7HcT7pQ=
</data>
<key>Qsignsafekey.bundle/x@3x.png</key>
<data>
ZDaf4DjmLXJKZo+s2468MEyMA3U=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/QsignSafeKeyApi.h</key>
<dict>
<key>hash</key>
<data>
BgfBn/+aTUdrrVIYbDUy5khEYGU=
</data>
<key>hash2</key>
<data>
HLceeax1OmPG4F1HXifG3/ejifWO8ogkowCtvyfAP5Y=
</data>
</dict>
<key>Headers/QsignSafeSDK.h</key>
<dict>
<key>hash</key>
<data>
xRVIWD4U+rLDUxK85aba+oH3xNY=
</data>
<key>hash2</key>
<data>
OegEuAtr3G3wnajU6xi16iCthbO+mZTWZW7lbxlGPg0=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash</key>
<data>
gc0R5ZZtr60iaB4RS1wWdr7MOFQ=
</data>
<key>hash2</key>
<data>
xh9mIF2HIE5Ls5NkyCcH7WkEqxafbF7mfSr5cR7SzB8=
</data>
</dict>
<key>Qsignsafekey.bundle/Root.plist</key>
<dict>
<key>hash</key>
<data>
jOhqEUF1/xyY+fuswiWT+ELC3dI=
</data>
<key>hash2</key>
<data>
m26DmegPkB5jwUJkVEtLlObYALX8He100Ny0+NNJg/g=
</data>
</dict>
<key>Qsignsafekey.bundle/delete@2x.png</key>
<dict>
<key>hash</key>
<data>
bn7f8LWSMgHj05hFraX5g2X2nVw=
</data>
<key>hash2</key>
<data>
u3KSZ4b/GSG1l28C3lNZ7u6PPYk8mAS9/0ArqEkuHaU=
</data>
</dict>
<key>Qsignsafekey.bundle/delete@3x.png</key>
<dict>
<key>hash</key>
<data>
YQivYSc04xJzjWLtdKCKizf8xYg=
</data>
<key>hash2</key>
<data>
Z30/OWBBSXWlD/oF+gLNl9pY2m2er8k667DejvIoXac=
</data>
</dict>
<key>Qsignsafekey.bundle/en.lproj/Root.strings</key>
<dict>
<key>hash</key>
<data>
t4KY9Gh4uIiOv7VnHtRrKEuPRY8=
</data>
<key>hash2</key>
<data>
xUzNd7J7w99oAnMIWGe1dAGArHMuEXwQqxSziDU5vLk=
</data>
<key>optional</key>
<true/>
</dict>
<key>Qsignsafekey.bundle/password_loading_a@2x.png</key>
<dict>
<key>hash</key>
<data>
KJ0J29Kmc9G1My8eKBLXZocAhpg=
</data>
<key>hash2</key>
<data>
GGlM8e1SoN7W0XeAy91lE2C0RcIMHWa35v6uVW4m70c=
</data>
</dict>
<key>Qsignsafekey.bundle/password_loading_b@2x.png</key>
<dict>
<key>hash</key>
<data>
vdk5gwErtXtbwVKQJBL/DvFlBaE=
</data>
<key>hash2</key>
<data>
CwxtFh9bJ04/Gcmr68PcxREYbnPnv9WIg0H/RfUwp/c=
</data>
</dict>
<key>Qsignsafekey.bundle/password_success@2x.png</key>
<dict>
<key>hash</key>
<data>
JwVBpUMfAybYoDPkuLcyrStoacE=
</data>
<key>hash2</key>
<data>
vEv8I60vXR+f90lej99ocDY+/s3qnt1AcoJEByJaX+M=
</data>
</dict>
<key>Qsignsafekey.bundle/x@2x.png</key>
<dict>
<key>hash</key>
<data>
BNj8BHbrJlYORogsE3/q7HcT7pQ=
</data>
<key>hash2</key>
<data>
z5BBiNgwdrvcRd3SzW+FzHFQVniC7TSG+DPyaa7lL9U=
</data>
</dict>
<key>Qsignsafekey.bundle/x@3x.png</key>
<dict>
<key>hash</key>
<data>
ZDaf4DjmLXJKZo+s2468MEyMA3U=
</data>
<key>hash2</key>
<data>
AqsSmdGkAMHdsbp6TEesoIjxA+ji5qMMghdhSp5rT3c=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
O4jLlq5vhAaV522Aq4BFXu6MHpbWqLFlkY9n4Vmkzmagd0Q+JuuXG5fk7SzXk7h4futhisBTjuTm64DpVhNX1NkRpT9Vig/XS4VrzHfSkW0u41miZ03nCWPIxyMybJZn3aKWGw+48qrcckH4LGgv2FXdkpMWWjyKpR4jUq987MA=
PScF7Z4b96xw2Nk6UKZbAy8IZMRiWLck9duBHboPcmTRHj7AUBsRUxaB6xK6SvMQQ9Lt+yrlA9GHAGK5quVTWAvkzWtfTATvz8TM59uCWDzTnI1ChKJecO9ZQ8Bkvd8SI83BfBSfu6I2RBQ4gVZK1aBALnBMYBHbW7clpHlJU3w=
\ No newline at end of file
MPhgMrZQRTQB7RVvI/kqPwHQvlM0ku+gXoz4phR3o9TiNzUJ9UfoKEQ16HRsexw9Abs9YrcG8TkeVgTwHvEWU4fE35SaPWMsxdwdJ02StdO7cxohIgAdOIRHiEELQWzU1R5x9FdUdPtniZ0IVRJyA2RvOzwzOsHewhHp95ADQmI=
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment