Миграция iOS из UIWebView в WKWebView для JavaScript POST

Я внедряю решение для безопасных платежей в приложении Native iOS в Swift.

В основном, когда я запускаю запрос на оплату, в ответ я получаю "PaReq" и ​​"ACSURL" в ответе, если платежная карта зарегистрирована в 3D Check.

Затем мне нужно сделать Java-скрипт POST.

И как только пользователь завершил действие, мне нужно извлечь "PaRes" и отправить его при следующем вызове службы.

Вот рабочее решение в Objective-C, использующее UIWebView. Я хочу добиться того же в Swift, используя WKWebView, поскольку UIWebView устарела.

- (void)viewDidLoad {
    [super viewDidLoad];

    UIWebView *webView=[[UIWebView alloc]initWithFrame:CGRectMake(0, 0, self.secureViewContainer.frame.size.width ,self.secureViewContainer.frame.size.height)];
    webView.delegate = self;
    [self.view addSubview:webView];

    NSString *termURL = @"https://www.apple.com";

    self.webViewURL = @"";
    self.webViewHTMLString = [NSString stringWithFormat:@"<html><body><form name='redirectToIssuerForm' id='redirectToIssuerForm' action='%@' method='post'><input type='hidden' name='PaReq' value='%@' /><input type='hidden' name='TermUrl' value='%@' /><input type='hidden' name='MD' value='' /><input type='submit' id='submitButton' value='Click here to continue' /></form><script>function submitForm(){document.getElementById('submitButton').style.display='none'; document.getElementById('submitButton').click();} window.onload = (function(){submitForm();});</script></body></html>",self.acsurl,self.pareq,termURL];

    [webView loadHTMLString:self.webViewHTMLString baseURL:nil];

}

- (void)webViewDidFinishLoad:(UIWebView *)webView{

    if([webView.request.URL.absoluteString isEqualToString:@"about:blank"]){
        [webView stringByEvaluatingJavaScriptFromString:@"submitForm()"];
    }
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

    if([ [NSString stringWithFormat:@"%@",request.URL] isEqualToString:@"https://www.apple.com/"]){ 

    NSData *data = request.HTTPBody;

    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

    NSLog(@"\n\n\n  3D Secure - dataString: %@", dataString);

        return NO;
    }
    else{

        return YES;

    }
}

Вот что я пытался перенести в Swift с помощью WKWebView:

override func viewDidLoad() {

    super.viewDidLoad()

    let webConfiguration = WKWebViewConfiguration()
    let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 0.0, height: self.secureViewContainer.frame.size.height))
    self.webView = WKWebView (frame: customFrame , configuration: webConfiguration)
    webView.uiDelegate = self
    webView.navigationDelegate = self
    self.secureViewContainer.addSubview(webView)          
}
override func viewWillAppear(_ animated: Bool) {

    super.viewWillAppear(animated)
    let termURLString = "https://www.apple.com"
    var paReqString = response.PaRequest
    var acsurlString = response.ACSURL

    // create HTML String 

    let webViewHTMLString = String(format:"<html><body><form name='redirectToIssuerForm' id='redirectToIssuerForm' action='%@' method='post'><input type='hidden' name='PaReq' value='%@' /><input type='hidden' name='TermUrl' value='%@' /><input type='hidden' name='MD' value='' /><input type='submit' id='submitButton' value='Click here to continue' /></form><script>function submitForm(){document.getElementById('submitButton').style.display='none'; document.getElementById('submitButton').click();} window.onload = (function(){submitForm();});</script></body></html>",acsurlString,paReqString,termURLString)

        // Load HTML String
        webView.loadHTMLString(webViewHTMLString, baseURL: nil)
 }

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

    if webView.url?.absoluteString == "about:blank" {

        webView.evaluateJavaScript("submitForm()", completionHandler: {
            result in

            print("\n\n\n Result - \(result)\n\n\n")

        })
    }

}

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    if let url = navigationAction.request.url,url.absoluteString.hasPrefix("https://www.apple.com/") {
        let data = navigationAction.request.httpBody

        print("\n\n  data : \(String(describing: data))")

        decisionHandler(.cancel)
        return
    }
    decisionHandler(.allow)
}

Проблема в том, что "Результат" и "данные" равны нулю.

1: получу ли я результат java-скрипта в webView(_: managePolicyFor: solutionHandler:) (или) в webView: didFinishNavigation:?

2: В рабочем решении UIWebView я могу изменить termURL на любой URL-адрес, например " https://www.apple.com/", но все же я могу получить данные в порядке, может кто-нибудь объяснить мне, как работает этот POST Javascript?

3: Пожалуйста, укажите мне руководство / учебное пособие, чтобы понять больше о взаимодействии JavaScript и родного приложения для iOS.

2 ответа

Решение

Похоже, вы на правильном пути. Я недавно написал статью на эту тему, и это должно объяснить все, что вам нужно.

Прежде всего, если вы хотите отправить что-то в нативный код из вашего кода javascript, вам нужно использовать window.webkit в вашем коде JavaScript. Вам нужно будет реализовать WKScriptMessageHandler и WKNavigationDelegate в вашем быстром коде и реализовать эту функцию:

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    //This function handles the events coming from javascript.
    //We can access properties through the message body, like this:
    guard let response = message.body as? String else { return }
    print(response)
}

Подробнее об этом в статье.

Все отправленные вами сообщения будут проходить через webview.evaluateJavascript(), Убедитесь, что функция javascript работает, потому что ошибки webkit не будут отображаться в вашей консоли Xcode. Для этого вам нужно будет реализовать собственный messageHandler.

  1. Вы получите результат в func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!), НО только внутри закрытия Завершения, а не для всей функции.

  2. Как я вижу это termURL это просто содержимое какого-то скрытого поля ввода формы. Его значение передается при отправке формы - но это не имеет никакого отношения к тому, куда она отправляется.

  3. Это кажется хорошим, но базовым введением в WkWebViews. И есть эта запись в блоге о WkWebView JavaScript Quirks.

Другие вопросы по тегам