iOS JavaScript POST 从 UIWebView 迁移到 WKWebView
iOS Migration from UIWebView to WKWebView for JavaScript POST
我正在 Swift 中的原生 iOS 应用程序中实施安全支付解决方案。
基本上当我开始付款请求时,如果支付卡已注册 3D 支票,我会在响应中收到 "PaReq" 和 "ACSURL"。
然后我需要做 java 脚本 POST。
一旦用户完成操作,我需要提取 "PaRes" 并在下一次服务调用中发送。
这是 Objective-C 中的工作解决方案,使用 UIWebView.I 想要在 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;
}
}
这是我尝试使用 WKWebView 迁移到 Swift 的内容:
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)
}
问题是 "Result" 和 "data" 都为零。
1:我会在 webView(_:decidePolicyFor:decisionHandler:)(或)webView:didFinishNavigation 中得到 java 脚本结果吗?
2:在 UIWebView 工作解决方案中,我可以将 termURL 更改为任何 url,例如“https://www.apple.com”,但我仍然可以很好地获取数据,有人可以向我解释一下这个 Javascript POST 有效吗?
3:请指向 guide/tutorial 以了解有关 JavaScript 和本机 iOS 应用交互的更多信息。
您在 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
中得到结果,但 仅在 completionHandler 闭包中 ,而不是 function-wide。
如我所见,termURL
只是表单的一些隐藏输入字段的内容。它的值在提交表单时传递 - 但它与提交到的位置无关。
这个好像不错,但是基本intro into WkWebViews. And there's this blog post about WkWebView JavaScript Quirks.
看来您的方向是正确的。 I recently wrote an article on this subject, and that should explain everything you need.
首先,如果您想从 javascript 代码向本机代码发送内容,您需要在 javascript 代码中使用 window.webkit
。您需要在 swift 代码中实现 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。
我正在 Swift 中的原生 iOS 应用程序中实施安全支付解决方案。
基本上当我开始付款请求时,如果支付卡已注册 3D 支票,我会在响应中收到 "PaReq" 和 "ACSURL"。
然后我需要做 java 脚本 POST。
一旦用户完成操作,我需要提取 "PaRes" 并在下一次服务调用中发送。
这是 Objective-C 中的工作解决方案,使用 UIWebView.I 想要在 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;
}
}
这是我尝试使用 WKWebView 迁移到 Swift 的内容:
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)
}
问题是 "Result" 和 "data" 都为零。
1:我会在 webView(_:decidePolicyFor:decisionHandler:)(或)webView:didFinishNavigation 中得到 java 脚本结果吗?
2:在 UIWebView 工作解决方案中,我可以将 termURL 更改为任何 url,例如“https://www.apple.com”,但我仍然可以很好地获取数据,有人可以向我解释一下这个 Javascript POST 有效吗?
3:请指向 guide/tutorial 以了解有关 JavaScript 和本机 iOS 应用交互的更多信息。
您在
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
中得到结果,但 仅在 completionHandler 闭包中 ,而不是 function-wide。如我所见,
termURL
只是表单的一些隐藏输入字段的内容。它的值在提交表单时传递 - 但它与提交到的位置无关。这个好像不错,但是基本intro into WkWebViews. And there's this blog post about WkWebView JavaScript Quirks.
看来您的方向是正确的。 I recently wrote an article on this subject, and that should explain everything you need.
首先,如果您想从 javascript 代码向本机代码发送内容,您需要在 javascript 代码中使用 window.webkit
。您需要在 swift 代码中实现 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。