>
>
移动端iOS常见问题解答
iOS 设备在使用 H5 时出现文字点选验证位置错位
文字出现错位是由于 iOS 点击了软键盘顶起了页面,输入框失去焦点后不能恢复导致页面 clientY 变化的原因,提供以下方案:
加长整个页面
H5 中添加如下代码:
html,body { width: 100%; height: 100%; }
|
国际化多语言模式,验证页面语言未跟随系统语言变化,或未按照设置的语言变化
首先检查工程中是否有添加 GT3Captcha.bundle 文件,并确认 GT3Captcha.bundle 中是否包含对应的语言
检查主工程的 Info.plist 文件中是否有设置 CFBundleLocalizations,并查看是否有添加对应语言的英文简称,如下图所示:
如何进行异步任务方式的集成?
自定义一个类,该类需要实现 GT3AsyncTaskProtocol
协议
在该类中实现 GT3AsyncTaskProtocol
协议中的如下两个方法,在第一个方法中,进行自定义的 api1 的请求,拿到对应的 gt
、 challenge
、 success
参数,并通过 completion
回调将参数传给 SDK,在第二个方法中,进行 api2 的验证,并通过 completion
回调将 api2 的验证结果传给 SDK
- (void)executeRegisterTaskWithCompletion:(void (^)(GT3RegisterParameter * _Nullable, GT3Error * _Nullable))completion {
}
- (void)executeValidationTaskWithValidateParam:(GT3ValidationParam *)param completion:(void (^)(BOOL, GT3Error * _Nullable))completion {
}
|
实例化一个 GT3CaptchaManager
,并通过 registerCaptchaWithCustomAsyncTask:completion:
方法注册异步任务,最后调用 startGTCaptchaWithAnimated:
方法即可开启验证
详细可参考如下代码:
@interface DemoAyncTask : NSObject <GT3AsyncTaskProtocol>
@property (nonatomic, weak) id<DemoAyncTaskDelegate> delegate;
- (void)executeValidationTaskWithValidateParam:(GT3ValidationParam *)param completion:(void (^)(BOOL, GT3Error * _Nullable))completion; - (void)executeRegisterTaskWithCompletion:(void (^)(GT3RegisterParameter * _Nullable, GT3Error * _Nullable))completion;
- (void)cancel;
@end
@implementation DemoAyncTask
- (void)executeValidationTaskWithValidateParam:(GT3ValidationParam *)param completion:(void (^)(BOOL, GT3Error * _Nullable))completion {
__block NSMutableArray *postArray = [[NSMutableArray alloc] init]; [param.result enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL * stop) { NSString *paramItem = [NSString stringWithFormat:@"%@=%@", key, obj]; [postArray addObject:paramItem]; }]; NSString *postForm = [postArray componentsJoinedByString:@"&"]; EnvModel *model = [EnvSettingCenter defaultCenter].currentEnv; NSDictionary *headerFields = @{@"Content-Type":@"application/x-www-form-urlencoded;charset=UTF-8"}; NSMutableURLRequest *secondaryRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:model.validateAPI] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0]; secondaryRequest.HTTPMethod = @"POST"; secondaryRequest.allHTTPHeaderFields = headerFields; secondaryRequest.HTTPBody = [postForm dataUsingEncoding:NSUTF8StringEncoding]; NSURLSession *session = [NSURLSession sharedSession]; self.validateDataTask = [session dataTaskWithRequest:secondaryRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if (!error && httpResponse.statusCode == 200) { NSError *err; NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&err]; if (!err) { NSString *status = [dict objectForKey:@"status"]; if ([status isEqualToString:@"success"]) { NSLog(@"通过业务流程"); if (completion) { completion(YES, nil); } if (_delegate && [_delegate respondsToSelector:@selector(asyncTaskDidFinish:error:)]) { [_delegate asyncTaskDidFinish:YES error:nil]; } } else { if (completion) { completion(NO, nil); } NSLog(@"无法通过业务流程"); if (_delegate && [_delegate respondsToSelector:@selector(asyncTaskDidFinish:error:)]) { [_delegate asyncTaskDidFinish:NO error:nil]; } } } else { GT3Error *anErr = [GT3Error errorWithDomainType:GT3ErrorTypeExtern originalError:err withGTDesciption:@"Error occur."]; if (completion) { completion(NO, anErr); } if (_delegate && [_delegate respondsToSelector:@selector(asyncTaskDidFinish:error:)]) { [_delegate asyncTaskDidFinish:NO error:anErr]; } NSLog(@"error:\n%@", err.localizedDescription); } } else { GT3Error *err = [GT3Error errorWithDomainType:GT3ErrorTypeExtern originalError:error withGTDesciption:@"Error occur."]; if (completion) { completion(NO, err); } if (_delegate && [_delegate respondsToSelector:@selector(asyncTaskDidFinish:error:)]) { [_delegate asyncTaskDidFinish:NO error:err]; } NSLog(@"error:\n%@", error.localizedDescription); } }]; [self.validateDataTask resume]; }
- (void)executeRegisterTaskWithCompletion:(void (^)(GT3RegisterParameter * _Nullable, GT3Error * _Nullable))completion { EnvModel *model = [EnvSettingCenter defaultCenter].currentEnv;
NSString *ts = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970] * 1000]; NSURLQueryItem *queryItem = [NSURLQueryItem queryItemWithName:@"t" value:ts]; NSURLComponents *comp = [NSURLComponents componentsWithURL:[NSURL URLWithString:model.registerAPI] resolvingAgainstBaseURL:NO]; comp.queryItems = @[queryItem]; NSURLRequest *request = [NSURLRequest requestWithURL:comp.URL]; NSURLSession *session = [NSURLSession sharedSession]; self.registerDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (!error) { NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingOptions)0 error:&error]; if (!error && dict) { NSString *geetest_id = [dict objectForKey:@"gt"]; NSString *geetest_challenge = [dict objectForKey:@"challenge"]; NSNumber *geetest_success = [dict objectForKey:@"success"]; if (geetest_id && geetest_challenge && geetest_success) { GT3RegisterParameter *param = [[GT3RegisterParameter alloc] init]; param.gt = geetest_id; param.challenge = geetest_challenge; param.success = geetest_success; if (completion) { completion(param, nil); } } } } else { GT3Error *err = [GT3Error errorWithDomainType:GT3ErrorTypeExtern originalError:error withGTDesciption:@"Error occur."]; if (completion) { completion(nil, err); } NSLog(@"error:\n%@", error.localizedDescription); } }]; [self.registerDataTask resume]; }
- (void)cancel { if (self.registerDataTask) { [self.registerDataTask cancel]; }
if (self.validateDataTask) { [self.validateDataTask cancel]; } }
@end
- (GT3CaptchaManager *)manager { if (!_manager) { BOOL debugable = [EnvSettingCenter defaultCenter].debugEnable; BOOL httpsEnable = [EnvSettingCenter defaultCenter].httpsEnable; BOOL naEnable = [EnvSettingCenter defaultCenter].naNodeEnable; GT3LanguageType langType = [EnvSettingCenter defaultCenter].langType; EnvModel *model = [EnvSettingCenter defaultCenter].currentEnv; _manager = [[GT3CaptchaManager alloc] initWithAPI1:model.registerAPI API2:model.validateAPI timeout:5.0]; _manager.delegate = self; _manager.viewDelegate = self; [_manager enableDebugMode:debugable]; [_manager disableSecurityAuthentication:!httpsEnable]; [_manager useLanguage:langType]; if (naEnable) [_manager useServiceNode:GT3CaptchaServiceNodeNA]; [_manager useVisualViewWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]]; } return _manager; }
- (void)_init { DemoAyncTask *asyncTask = [[DemoAyncTask alloc] init]; asyncTask.delegate = self; [self.manager registerCaptchaWithCustomAsyncTask:asyncTask completion:nil]; self.asyncTask = asyncTask; }
- (void)startCaptcha { [self.manager startGTCaptchaWithAnimated:YES]; }
- (void)stopCaptcha { [self.manager stopGTCaptcha]; }
|
如何查看 SDK 版本?
找到 GT3Captcha.framework 文件,选中 -> 双击进入目录 -> 找到 Info.plist -> 双击打开,找到 Bundle version string (short) 对应的值,即为 SDK 的版本,如下图所示:
如何获取二次验证的参数?
异步任务集成时,二次验证的参数在 - (void)executeValidationTaskWithValidateParam:(GT3ValidationParam *)param completion:(void (^)(BOOL, GT3Error * _Nullable))completion
回调方法中的 param
参数的 result
中,param.result
,如下图所示:
非异步任务集成时,二次验证的参数在 - (void)gtCaptcha:(GT3CaptchaManager *)manager didReceiveCaptchaCode:(NSString *)code result:(NSDictionary *)result message:(NSString *)message
回调方法的 result
中,如下图所示:
如何排查 3840 及 101603 错误?
出现这两个错误码,一般是 api1 请求返回的数据格式有问题,请检查 api1 接口返回的数据格式:
返回的数据不是 json 格式
返回的 json 格式与极验官方要求的不一致
正确的 json 格式为下面两种:
{ "challenge": "90977bef1d2c8a8efaea1e41b1d7b19b", "gt": "4faf9dd37eb683586977947ce87a866a", "new_captcha": 1, "success": 1 }
{"data": { "challenge": "90977bef1d2c8a8efaea1e41b1d7b19b", "gt": "4faf9dd37eb683586977947ce87a866a", "new_captcha": 1, "success": 1 } }
|
registerCaptcha: 在什么时候回调
- 回调仅在首次注册成功后回调,且根据验证状态,并不一定每次回调
- 流程和方法之间的关系见下图
gtCaptcha:didReceiveCaptchaCode:result:message: 中 code 返回 0,建议作何处理?
只要终端用户没有完成验证,返回就是0;只有完成通过,才会返回 code = 1 以及相应的二次校验
result 数据。code = 0 的具体场景,比如在滑动验证的时候,没有滑动正确。当 code = 0 时,验证码会自动刷新,终端用户充实即可。并且重试有最大的重试次数,根据验证类型不同,最大重试次数默认是 5-6 次。
Xcode 编译报 GT3Captcha 相关的符号无法找到(symbol not found)
Xcode 编译错误提示 symbol not found,说明相关的符号无法被链接器访问到。排查方式:先确认缺失库的名称,再确认相关的库是否正确导入(手动导入时勾选 Copy items if need 等)。否则可以尝试重启 Xcode 或者系统。
Xcode 编译报符号重复(Duplicated symbol)
如果 Xcode 提示 Duplicated symbol,说明有符号冲突(代码冲突)。排查方式:确实冲突的符号所属的库,在确认不同的库怎么被同时引入,并反馈给极验。
Xcode 编译报 No such module ‘GT3Captcha’
请检查 GT3Captcha.framework 是否正确被导入工程,且 Xcode 的 Build Setting 中的 Search Path 进行了正确的配置。
验证 3.0 是否有 Flutter 2.0 支持示例
极验官方已提供官方 Flutter 插件:
在工程 pubspec.yaml
中 dependencies
块中添加下列配置
Github 集成
dependencies: gt3_flutter_plugin: git: url: https://github.com/GeeTeam/gt3_flutter_plugin.git ref: master
|
或
pub 集成
dependencies: gt3_flutter_plugin: ^0.0.6
|
Github:gt3_flutter_plugin
验证 3.0 NA 亚马逊节点、NG 谷歌云节点的使用说明
- NG 节点已经销毁,已不再使用
- 使用海外接口需要跟极验技术沟通并进行报备
- 海外终端用户并不是必须使用海外节点,也可以访问国内节点
- 当国内终端用户较多的时候建议,还是以国内节点为主
- 使用海外节点必须配套使用海外集群的 register 接口,同时在 Android 和 iOS 的 SDK 中设置 serviceNode 为相应节点
验证 3.0 加载耗时较长或报错,这个该如何处理?
- 网络请求时间较长,但能成功:可能当前网络质量不好,建议更换网络重试。
- 网络请求超时而失败:建议检查超时的请求。如果是极验的接口,检查一下终端用户所在网络到极验接口的可达性。简单的自检工具可以访问 http://webtest.geetest.com。
- 网络相关的报错:请查看相应产品各个端对应的错误码清单,进行排查和处理。如果在国内区域性的报SSL证书错误,可能是遇到了区域性的 DNS 劫持。
项目目标最低版本在 9.0 以下时,使用 Xcode 14.3 运行报链接不到 ARC 库的错
原因是 Xcode 14.3 移除了 ARC 相关的库,iOS 9.0 及以上系统内置了ARC 库,所以有两种解决方案:
- 将项目目标最低版本设置为 9.0 或以上
- 将在 14.3 以下的 Xcode 版本中的 ARC 库拷贝到 Xcode 14.3 版本对应路径上