Created
March 17, 2025 16:44
-
-
Save adityadaniel/bdc3ad6e6bfe2b847f27fdeaaf18daf9 to your computer and use it in GitHub Desktop.
Webview Midtrans blob
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MyWebViewController.swift | |
// midtrans-snap-WebView-sample | |
// | |
// Created by Zaki Ibrahim on 14/09/21. | |
// | |
import UIKit | |
import WebKit | |
class MyWebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler { | |
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { | |
if message.name == "imageHandler", let base64String = message.body as? String { | |
saveBase64Image(base64String) | |
} | |
} | |
var selectedName: String = "" | |
var webView: WKWebView! | |
private var activityIndicatorContainer: UIView! | |
private var activityIndicator: UIActivityIndicatorView! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
var urlS : URL | |
// Get URL from text field, if empty get Snap URL from Sample web | |
if !selectedName.isEmpty { | |
urlS = URL(string: selectedName)! | |
} else { | |
urlS = URL(string: "https://sample-demo-dot-midtrans-support-tools.et.r.appspot.com/snap-redirect")! | |
} | |
let contentController = WKUserContentController() | |
contentController.add(self, name: "imageHandler") | |
let config = WKWebViewConfiguration() | |
config.userContentController = contentController | |
self.webView = WKWebView(frame: .zero, configuration: config) | |
self.webView.navigationDelegate = self | |
view.addSubview(webView) | |
webView.translatesAutoresizingMaskIntoConstraints = false | |
NSLayoutConstraint.activate([ | |
webView.topAnchor.constraint(equalTo: view.topAnchor), | |
webView.bottomAnchor.constraint(equalTo: view.bottomAnchor), | |
webView.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
webView.trailingAnchor.constraint(equalTo: view.trailingAnchor) | |
]) | |
webView.load(URLRequest(url: urlS)) | |
} | |
func saveBase64Image(_ base64String: String) { | |
guard let imageData = Data(base64Encoded: base64String.replacingOccurrences(of: "data:image/png;base64,", with: "")) else { | |
print("Failed to decode base64") | |
return | |
} | |
do { | |
UIImageWriteToSavedPhotosAlbum(UIImage(data: imageData)!, nil, nil, nil) | |
print("image saved to photo") | |
} catch { | |
print("Failed to save image: \(error.localizedDescription)") | |
} | |
} | |
// WKWebView Configuration | |
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { | |
let url = navigationAction.request.url | |
if let url = url, url.absoluteString.contains("blob") { | |
print("URL", url) | |
let jsCode = """ | |
(async function() { | |
try { | |
let response = await fetch("\(url)"); // Ensure this is a valid string | |
let blob = await response.blob(); | |
let reader = new FileReader(); | |
reader.readAsDataURL(blob); | |
reader.onloadend = function() { | |
window.webkit.messageHandlers.imageHandler.postMessage(reader.result); | |
}; | |
} catch (error) { | |
window.webkit.messageHandlers.imageHandler.postMessage("JavaScript Error: " + error.message); | |
} | |
})(); | |
""" | |
print("jscode", jsCode) | |
webView.evaluateJavaScript(jsCode) { result, error in | |
if let error = error { | |
print("JavaScript Error: \(error)") | |
} | |
} | |
decisionHandler(.cancel) | |
} | |
// detect these specified deeplinks and e_money simulator to be handled by OS | |
if url!.absoluteString.hasPrefix("https://simulator.sandbox.midtrans.com/gopay/partner/") | |
|| url!.absoluteString.hasPrefix("https://simulator.sandbox.midtrans.com/shopeepay/") | |
|| url!.absoluteString.hasPrefix("shopeeid://") | |
|| url!.absoluteString.hasPrefix("gojek://") | |
|| url!.absoluteString.hasPrefix("//wsa.wallet.airpay.co.id/") { | |
decisionHandler(.cancel) | |
UIApplication.shared.open(url!) | |
// any other url will be loaded normally by the WebView | |
} else { | |
decisionHandler(.allow) | |
} | |
} | |
// Loading animator | |
fileprivate func setActivityIndicator() { | |
activityIndicatorContainer = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80)) | |
activityIndicatorContainer.center.x = webView.center.x | |
activityIndicatorContainer.center.y = webView.center.y - 44 | |
activityIndicatorContainer.backgroundColor = UIColor.black | |
activityIndicatorContainer.alpha = 0.8 | |
activityIndicatorContainer.layer.cornerRadius = 10 | |
// Configure the activity indicator | |
activityIndicator = UIActivityIndicatorView() | |
activityIndicator.hidesWhenStopped = true | |
activityIndicator.style = UIActivityIndicatorView.Style.whiteLarge | |
activityIndicator.translatesAutoresizingMaskIntoConstraints = false | |
activityIndicatorContainer.addSubview(activityIndicator) | |
webView.addSubview(activityIndicatorContainer) | |
// Constraints | |
activityIndicator.centerXAnchor.constraint(equalTo: activityIndicatorContainer.centerXAnchor).isActive = true | |
activityIndicator.centerYAnchor.constraint(equalTo: activityIndicatorContainer.centerYAnchor).isActive = true | |
} | |
// Helper function to control activityIndicator's animation | |
fileprivate func showActivityIndicator(show: Bool) { | |
if show { | |
activityIndicator.startAnimating() | |
} else { | |
activityIndicator.stopAnimating() | |
activityIndicatorContainer.removeFromSuperview() | |
} | |
} | |
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | |
if let url = webView.url?.absoluteString, url.contains("blob") { | |
print("Found blob") | |
} | |
self.showActivityIndicator(show: false) | |
} | |
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { | |
// Set the indicator everytime webView started loading | |
self.setActivityIndicator() | |
self.showActivityIndicator(show: true) | |
} | |
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { | |
self.showActivityIndicator(show: false) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment