Mobile redirects (app-to-app)

Nowadays, more and more banks offer a way for their customers to verify and approve payments using their online banking app or other specific apps installed on their mobile device. This method is usually the easiest and most familiar for users to grant permission and make payments. This process is referred to as “app-to-app” or “app2app redirection”.

General implementation

  1. Set the payment URLs to the views in your mobile app
  2. Load the checkout URL in the web view
  3. Open the bank URL in the standard browser
  4. The user returns to any of the payment URLs from (1.)

1. Set payment URLs to the views in your mobile app

This step allows the user to return back to your intended flow in your app after the authorisation with their bank. This is ideally a URL or an app link.

Example

"paymentSuccessUrl":"https://your-domain.com/checkout/success"
"paymentSuccessUrl":"your-app://checkout/success"

Note that when using URLs, your app needs to claim the URL schema in the OS for a successful redirection.

2. Load the checkout URL in the web view

Typically the OS will support this by using the standard load method for the web view element.

Android (Java)
webView.loadUrl("https://www.example.com");

3. Open the bank URL in the standard browser

Volt Checkout opens the URL of the bank (https://bank.com/). The bank URL has to be opened in the standard browser (Chrome on Android; Safari on iOS) for the app-to-app redirection to work. Other browsers, e.g. Firefox on Android, might not have the permissions, configuration or open the links incorrectly.
Note that any Volt Checkout URL (https://checkout.volt.io/…) should still be opened inside the web view, meaning the additional handling is only required for other URLs.

We recommend closing the web view once the user was redirected.  This way, they can continue with the next step in the checkout process once they return from their mobile bank app.

Android

To catch the event when a webpage tries to open another webpage in a WebView, you can use the WebViewClient class and override its shouldOverrideUrlLoading method.

Example
WebView myWebView = findViewById(R.id.my_webview);
myWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        // Here, you should open the bank URL in Chrome
        return false; // This will allow the WebView to handle the URL itself
    }
});

In the shouldOverrideUrlLoading method, you can put your own code to handle the event when the webpage tries to open another webpage. You can return true to indicate that you’ve handled the URL loading, or false to allow the WebView to handle the URL itself.

Note that the shouldOverrideUrlLoading method was deprecated in API level 24. Instead, you should use the shouldOverrideUrlLoading method that takes a WebResourceRequest parameter, as shown in the example above.

iOS

To catch the event when a webpage tries to open another webpage in a UIWebView or WKWebView on iOS, you can use the UIWebViewDelegate or WKNavigationDelegate respectively, and implement the shouldStartLoadWithRequest or decidePolicyForNavigationAction method.

Here are examples for UIWebView and WKWebView

  • UIWebView
  • WKWebView
class MyViewController: UIViewController, UIWebViewDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let webView = UIWebView(frame: self.view.bounds)
        webView.delegate = self
        self.view.addSubview(webView)
        let url = URL(string: "https://checkout.volt.io/...")
        let request = URLRequest(url: url!)
        webView.loadRequest(request)
    }
    
    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        // Here, you should open the bank URL in Safari
        return true // Return true to allow the WebView to handle the URL itself, or false to cancel the navigation
    }
}

In the shouldStartLoadWith method, you can put your own code to handle the event when the webpage tries to open another webpage. You can return true to allow the WebView to handle the URL itself, or false to cancel the navigation.

class MyViewController: UIViewController, WKNavigationDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let webView = WKWebView(frame: self.view.bounds)
        webView.navigationDelegate = self
        self.view.addSubview(webView)
        let url = URL(string: "https://checkout.volt.io/...")
        let request = URLRequest(url: url!)
        webView.load(request)
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // Here, you should open the bank URL in Safari
        decisionHandler(.allow) // Call the decisionHandler with .allow to allow the navigation, or .cancel to cancel the navigation
    }
}

In the decidePolicyFor method, you can put your own code to handle the event when the webpage tries to open another webpage. You can call the decisionHandler with .allow to allow the navigation, or .cancel to cancel the navigation.

Frameworks
  • Cordova
  • React Native
const INJECTED_JAVASCRIPT = `
window.voltRedirectCallback = function({url, type}) {
 if (!webkit.messageHandlers.cordova_iab) {
   throw 'Cordova IAB postMessage API not found!';
 } else {
   webkit.messageHandlers.cordova_iab.postMessage(JSON.stringify({url, type}));
 }
}`;


function openInAppBrowser() {
 /* Open URL */
 inAppBrowserRef = cordova.InAppBrowser.open(
   "https://checkout.volt.io/...",
   "_blank",
   "location=yes"
 );


 /* Inject JavaScript, make sure that JS is injected on the checkout.volt.io page */
 inAppBrowserRef.addEventListener("loadstop", function () {
   ref.executeScript({ code: INJECTED_JAVASCRIPT });
 });


 inAppBrowserRef.addEventListener("message", messageCallback);
}


/* Handle message from the injected JS */
function messageCallback(params) {
 if (!params.data || typeof params.data !== "object") {
   throw "Invalid message received";
 }
 if (params.data.type == "bank_redirect") {
   cordova.InAppBrowser.open(params.data.url, "_system");
 }
}
import { WebView } from "react-native-webview";
import { StyleSheet, Linking, View } from "react-native";


const checkoutURL = "https://checkout.volt.io/...";


const INJECTED_JAVASCRIPT = `
window.voltRedirectCallback = function({url, type}) {
 window.ReactNativeWebView.postMessage(JSON.stringify({
   type: type,
   url: url
 }));
}`;


export default function App() {
 function messageCallback(event) {
   const data = JSON.parse(event.nativeEvent.data);


   if (typeof data !== "object") {
     throw "Invalid message received";
   }
   if (data.type === "bank_redirect") {
     Linking.openURL(data.url);
   }
 }


 return (
   <View style={styles.container}>
     <WebView
       style={styles.webView}
       source={{ uri: checkoutURL }}
       injectedJavaScript={INJECTED_JAVASCRIPT}
       onMessage={messageCallback}
     />
   </View>
 );
}


const styles = StyleSheet.create({
 container: {
   flex: 1,
 },
 webView: {
   flex: 1,
 },
});
What if we use a different framework for our mobile application?

The logic of the implementation remains the same for any other framework.

4. Payer returns to one of the payment URLs

When the payer returns from their mobile banking app, they are ready to continue the checkout.

We recommend closing the web view once the user was redirected, so that they can continue with the next step in the checkout process.

Follow our implementation guide for returning the payer to you.