Introduction
Integrate Volley's hosted payment page into your native app using a WebView.
Using a WebView, you can embed Volley's hosted payment page into your native app. Your app creates a payment request then opens a WebView with the hosted payment page. Your customer selects their bank and is redirected to their bank app to approve the payment. Once configured, Volley returns the customer to your app.
Why a WebView?
The simplest integration is to redirect the customer to the hosted payment page in their default mobile browser - it's just a link. The customer leaves your app, completes the payment, and returns - either manually, or through the success and failure redirect URLs on the payment request, which your app handles as deep links.
For an improved UX, you can embed the hosted payment page in a WebView — WebView on Android, WKWebView on iOS. This keeps the customer in your app while they view the request. They're sent to their bank app to approve the payment and returned to your app, where the hosted page shows success or failure. The WebView integration takes more upfront work, but reduces the number of redirects and gives your customers a smoother experience.
This guide covers the WebView integration.
Try out the example
Grab the example apps to get straight to working code for both platforms:
git clone https://github.com/volley-payments/volley-example-webviewHow it works
There are two redirect methods for the payment flow:
- App-to-app. The customer is automatically redirected from your app to their bank app to approve the payment, is returned to their default browser and is then sent back to your app via a deep link.
- Decoupled. The customer receives a push notification from their bank app. Nothing redirects.
Because the decoupled flow never automaticaly redirects, the hosted page polls the payment to completion and delivers the result to your app as a message over the bridge. The redirect flow uses the same message. So regardless of flow, your app gets the result from one place: the completion message.
The flow looks like this:
┌─────────────────────────────────────────────────────────────┐
│ Your app │
│ │ │
│ ▼ │
│ WebView (hosted page) ──── customer selects bank │
│ │ │
│ │ "redirect" message ──▶ your app opens the bank app │
└────┼────────────────────────────────────────────────────────┘
▼
Bank app ──── customer approves
│
▼
Device browser ──── payment executes, then redirects back
│
│ deep link
▼
┌─────────────────────────────────────────────────────────────┐
│ Your app (foreground) │
│ │ │
│ ▼ │
│ WebView (still open, polling) ──▶ payment resolves │
│ │ │
│ │ "complete" message ──▶ you close the WebView │
└─────────────────────────────────────────────────────────────┘The message protocol
The hosted page emits event messages your app can listen to using a bridge. There are two event types, redirect and complete.
The redirect event passes the bank redirect URL which your app must use to initiate the app-to-app redirects. The WebView cannot redirect to the bank app itself, it must be managed by your app.
The complete event is emitted at the end of the payment consent flow. Your app may listen to these events to close the WebView and update the UI.
// Open this URL natively so the bank app launches (a WebView can't do this itself).
{
"type": "redirect",
"url": "https://..."
}
// The payment reached a terminal state.
{
"type": "complete",
"status": "succeeded", // "failed" | "cancelled"
"bank": "anz",
"paymentId": "payment_..."
}Prerequisites
- A payment request created with a redirect URL that deep-links back to your app.
- The redirect domain added as an allowed domain in the Volley Dashboard. Redirects to domains that aren't allowed are rejected.
- For production: a verified association file hosted on your redirect domain. A custom scheme is fine for local development.