美文网首页
腾讯云验证码iOS端实现

腾讯云验证码iOS端实现

作者: 辉过来辉过去 | 来源:发表于2020-07-15 19:00 被阅读0次

iOS端APP之前使用了腾讯云验证码的低版本SDK,随着苹果开始拒绝使用UIWebView的APP,整改提上日程。

官网找到升级方案, 官方已经弃用了SDK,实现方式为在ios端调用WKWebview加载本地或远程包含腾讯验证码js的页面,通过html页面与native层的交互完成整个流程。
详见 腾讯防水墙-iOS接入文档

以下是对接入的实现,包含了js回调native方法,仅供参考

#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>

typedef void(^DSWebCodeViewDismissCallback)(void);
typedef void(^DSWebCodeViewVerifySucessCallback)(NSString *ticket);
typedef void(^DSWebCodeViewVerifyFailCallback)(void);

@interface DSWebCodeView : UIView<WKNavigationDelegate, WKScriptMessageHandler>

@property (nonatomic, copy) DSWebCodeViewDismissCallback dismissCallback;
@property (nonatomic, copy) DSWebCodeViewVerifySucessCallback verifySuccessCallback;
@property (nonatomic, copy) DSWebCodeViewVerifyFailCallback verifyFailCallback;

- (void)loadTencentCaptcha;

@end

#import "DSWebCodeView.h"

@interface DSVerifyResultModel : DSBaseModel

@property (nonatomic, copy) NSString *appid;
@property (nonatomic, copy) NSString *randstr;
@property (nonatomic, assign) NSInteger ret;
@property (nonatomic, copy) NSString *ticket;

@end

@implementation DSVerifyResultModel

@end

@interface DSWebCodeView ()

@property (nonatomic, strong) WKWebView *webView;

@end

@implementation DSWebCodeView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (void)setup {
    [self addSubview:self.webView];
}

- (void)dismiss {
    [self removeFromSuperview];
    if (self.dismissCallback) {
        self.dismissCallback();
    }
}

// 加载入口方法
- (void)loadTencentCaptcha {
    NSString *randomstr = [self randomPassword];
    NSString* htmlText = [NSString stringWithFormat:DSWebBridge_html_js(), randomstr];
    [self.webView loadHTMLString:htmlText baseURL:nil];
}

//自动生成8位随机密码
-(NSString *)randomPassword{
    NSTimeInterval random = [NSDate timeIntervalSinceReferenceDate];
    NSString *randomString = [[NSString stringWithFormat:@"%.8f",random] MD5];
    NSString *randompassword = [randomString substringWithRange:NSMakeRange(6, 8)];
    return randompassword;
}

//js调用原生回调
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"loadAction"]) {
        //加载成功, 更新webview的frame
        NSDictionary *jsData =  message.body;
        self.webView.frame = CGRectMake(0, 0, [jsData[@"sdkView"][@"width"] doubleValue], [jsData[@"sdkView"][@"height"] doubleValue]);
        self.webView.center = CGPointMake(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
    }else if([message.name isEqualToString:@"verifiedAction"]) {
        //划动验证
        DSVerifyResultModel *model = [DSVerifyResultModel yy_modelWithJSON:message.body];
        if (model.ret == 0) {//验证成功
            [self removeFromSuperview];
            !self.verifySuccessCallback ? :self.verifySuccessCallback(model.ticket);
        }else if (model.ret == 2) {//点击关闭
            [self dismiss];
        }
    }else if([message.name isEqualToString:@"errorAction"]) {//加载失败
        [self removeFromSuperview];
        !self.verifyFailCallback?:self.verifyFailCallback();
    }
}

- (WKWebView *)webView {
    if (!_webView) {
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
        configuration.userContentController = [WKUserContentController new];
        //注册果断回调方法
        [configuration.userContentController addScriptMessageHandler:self name:@"loadAction"];
        [configuration.userContentController addScriptMessageHandler:self name:@"errorAction"];
        [configuration.userContentController addScriptMessageHandler:self name:@"verifiedAction"];
        
        WKWebView* webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
        webView.navigationDelegate = self;
        _webView = webView;
    }
    return _webView;
}

NSString * DSWebBridge_html_js() {
#define __wvjb_js_func__(x) #x
    static NSString * html = @__wvjb_js_func__(
                                               <!DOCTYPE html>
                                               <html>
                                               <head>
                                               <script  src="https://ssl.captcha.qq.com/TCaptcha.js?v=%@" type="text/javascript"></script>
                                               <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
                                               </head>
                                               <body>
                                               <script type="text/javascript">
                                               (function(){
        // 验证成功返回ticket
        window.SDKTCaptchaVerifyCallback = function (retJson) {
            if (retJson){
                window.webkit.messageHandlers.verifiedAction.postMessage(retJson)
            }
        };
        // 验证码加载完成的回调,用来设置webview尺寸
        window.SDKTCaptchaReadyCallback = function (retJson) {
            if (retJson && retJson.sdkView && retJson.sdkView.width && retJson.sdkView.height &&  parseInt(retJson.sdkView.width) >0 && parseInt(retJson.sdkView.height) >0 ){
                window.webkit.messageHandlers.loadAction.postMessage(retJson)
            }
        };
        window.onerror = function (msg, url, line, col, error) {
            if (window.TencentCaptcha == null) {
                window.webkit.messageHandlers.errorAction.postMessage(error)
            }
        };
        var sdkOptions = {"sdkOpts": {"width": 265, "height": 265}};
        sdkOptions.ready = window.SDKTCaptchaReadyCallback;
        window.onload = function () {
           //此处需要替换xxxxxx为appid
            new TencentCaptcha("xxxxxxxx", SDKTCaptchaVerifyCallback, sdkOptions).show();
        };
    })();
     </script></body></html>
    );
#undef __wvjb_js_func__
    return html;
};

@end

相关文章

网友评论

      本文标题:腾讯云验证码iOS端实现

      本文链接:https://www.haomeiwen.com/subject/azmjhktx.html