> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Loading the Checkout Inside My Own App (WebView, App Launch, Coming Back)

> The App-side questions the WebView integration guide does not answer: whether Waffo detects a WebView and warns the customer, which domains to allow, how your App learns the payment result when the customer never returns, whether the checkout refreshes itself after a wallet App round trip, whether a payment redirect link can be opened twice, what to capture when the wallet does not open, why App launch cannot be tested in sandbox, and whether a payment method can be hidden only in the App environment.

The mechanics of embedding the checkout in an App WebView — what your WebView
has to allow, how to intercept a non-HTTP(S) scheme on Android and iOS, and how
to triage `net::ERR_UNKNOWN_URL_SCHEME` — are in
[Checkout integration steps](/docs/en/developer-docs/integration/checkout/steps#app-webview-integration-considerations),
and the per-payment-method exceptions are in
[Payment method integration notes](/docs/en/developer-docs/tools-and-references/references/payment-method-integration-notes).
Read those first. This page answers the questions that come up around them.

## Is there a checklist I can run before I ship the WebView integration?

Yes — these are the capabilities a payment flow can depend on. Each one that
your App blocks removes payment methods rather than degrading gracefully.

| Capability | Why a payment flow needs it | Where the detail is |
| - | - | - |
| Open an external App from a non-HTTP(S) scheme | Wallet methods that authorize inside their own App | [Steps → custom schemes](/docs/en/developer-docs/integration/checkout/steps#handle-wallet-app-custom-schemes) |
| Open an external browser | Methods that state their flow cannot run in a merchant App WebView | [Payment method integration notes](/docs/en/developer-docs/tools-and-references/references/payment-method-integration-notes) |
| Download, copy and long-press save | QR codes, payment codes, bank details | Steps → WebView considerations |
| Preserve the URL and every query parameter | Some methods append required values to the redirect | Steps → WebView considerations |
| `allow="payment"` and a `strict-origin-when-cross-origin` referrer, if you also embed in an iframe | Browser payment APIs and referrer-sensitive methods | [Steps → iframe](/docs/en/developer-docs/integration/checkout/steps#iframe-embedding-considerations) |
| Send `userInfo.userTerminal` honestly | Terminal type decides which methods are eligible at all | [Redirects and `actionType`](/docs/en/support/cashier-redirect-and-action-type-faq) |

## Can I detect from the checkout whether I am inside a WebView? Does Waffo warn the customer?

The checkout does not attempt to detect App WebViews in general, and it does not
show a "please open in a browser" prompt for them. There is one exception: when
the checkout is opened inside a **messaging app's built-in browser** where the
payment flow is known not to work, it shows a blocking dialog that asks the
customer to open the link elsewhere, displays the full link, and offers a copy
button. The dialog cannot be dismissed, because continuing on that page would
fail anyway.

For your own App, detection belongs on your side: you control the WebView, so
you already know. Use that knowledge when you create the order — see the
question on hiding a method in the App environment below.

## Which domains do I have to allow in my WebView?

Allow the Waffo checkout domain, and do not use a domain allowlist as your
control on the payment flow.

The checkout URL is HTTPS on a Waffo domain, but the payment step afterwards
navigates to the payment method's own domain, and for wallet launches to a
non-HTTP(S) scheme that the payment page decides at runtime. That downstream set
is a property of each payment method and changes without any change on your
side, so there is no list you can pin. An App that only permits a fixed set of
hosts will pass integration testing and then fail on a method you did not test.

The supported shape is the one in
[Steps → custom schemes](/docs/en/developer-docs/integration/checkout/steps#handle-wallet-app-custom-schemes):
keep HTTP(S) navigation in the WebView, hand validated non-HTTP(S) navigation to
the operating system.

## The customer left my WebView to pay in a wallet App. How does my App learn the result?

Through your server, not through the WebView. The order of reliability is fixed
and does not change in an App context:

| Signal | Use it for |
| - | - |
| Payment notification to your `notifyUrl` | The authoritative result. Your server tells your App |
| `POST /api/v1/order/inquiry` | Confirming or catching up — on App resume, for example |
| `successRedirectUrl` / `failedRedirectUrl` / `cancelRedirectUrl` | Navigating the customer's screen only |

A practical App pattern: when your App returns to the foreground, ask your own
backend for the order state (which it knows from the notification, or by
inquiring) rather than reading anything out of the WebView. This is also the
pattern that survives the customer switching back to your App by hand instead of
following the redirect.

For the full reasoning on why a redirect is not a result, see
[Payment results](/docs/en/support/payment-results-faq).

## The customer switched straight back to my App without going through the redirect. What do I do with that order?

Nothing special — and specifically, do not treat it as a failure. From the
platform's point of view the order is in exactly the state the payment method
left it in, and the redirect being skipped tells you nothing about that state.

* Query the order, or wait for the notification. Both give the real state.
* Do not close, cancel or re-create the order because the customer did not
  come back. That is how duplicate payments happen.
* If the payment is still pending, the customer may well complete it later, in
  the wallet App, inside the order's validity window.

## The customer came back into the WebView. Does the checkout page refresh the result by itself?

Yes. While the checkout is on any pending state — waiting on a redirect, waiting
on an instruction such as a QR code, or processing — it polls the order state on
a backing-off interval and advances the page on its own when a result lands.
Certain QR-code methods, where customers typically pay very quickly, are polled
more aggressively right after the code is shown.

The redirect page also carries an explicit re-check action. Pressing it queries
the order immediately; if the payment still has not gone through, the page says
so rather than pretending to be finished.

So the customer does not have to reload anything, and your App should not
force-reload the WebView on resume — that can restart a flow that was fine.

## Can the same payment redirect link be opened twice? Will it stop working if the customer taps pay again?

It depends on the payment method, and you cannot control it. Some payment
methods issue a redirect URL that is **single-use** — once consumed, opening it
again does not work. Others allow it to be reopened.

The hosted checkout knows which case applies and reflects it: where reopening is
allowed, the page keeps offering a **Pay** button so the customer can go back
out to the wallet; where it is not, the page offers only the re-check action, so
the customer is not sent to a URL that will fail.

Two consequences:

* On the hosted checkout you do not have to do anything — the page already
  handles both cases.
* On a merchant-built checkout, **treat the redirect URL as single-use**. This
  property is deliberately not part of the merchant-facing `orderAction`, so
  there is nothing for you to branch on. Present the redirect once, then fall
  back to querying the order.

## The customer tapped pay in the WebView and nothing happened. What do I capture before contacting support?

Capture these five things at the moment of failure. Without them the report
cannot be separated from a normal "customer changed their mind".

1. The **last navigation URL** the WebView received, complete and unmodified —
   including its scheme and every query parameter
2. Whether your WebView navigation callback fired at all for that URL
3. Whether any installed App on the device can handle that scheme
4. The order ID and the timestamp
5. Whether the customer was in your App's WebView, an external browser, or an
   in-app browser of another App

The triage table in
[Steps → troubleshooting](/docs/en/developer-docs/integration/checkout/steps#troubleshoot-err_unknown_url_scheme-and-forbidden)
maps the common symptoms onto causes. Note the rule there: diagnose from the
failed URL's scheme and your WebView's handling of it, not from the device model
or the OS version. The same App build behaving differently across OS versions is
almost always a difference in how the navigation callback is reached, not a
platform-level block.

## Why can I not reproduce the wallet App launch in sandbox?

Because the sandbox does not connect to real payment methods. The sandbox
checkout is a simulator: you press a button to declare the outcome, and there is
no real payment-method selection, no card entry and no wallet App handover. See
[Sandbox simulator](/docs/en/developer-docs/tools-and-references/developer-tools/sandbox-simulator).

So the App-launch part of your integration — scheme interception, handing the URL
to the operating system, coming back — has to be verified in production with a
small real payment. What sandbox *is* good for is everything around it: order
creation, notification handling, App resume logic, and your own
order-state-on-resume flow.

Plan a production smoke test per payment method that involves an App handover,
and budget for the fact that it needs a real wallet account.

## Can I hide a payment method only in my App environment?

Not through a setting, and there is no "environment" parameter on the checkout.
What you can do — and what the platform is designed around — is decide per order:

* Your App knows it is your App. Have your server pass `payMethodType` and, for
  a specific wallet, `payMethodName` on `/api/v1/order/create` so the order only
  ever offers what works in that environment.
* Send `userInfo.userTerminal` truthfully. Methods that do not support the
  terminal type you sent are not offered at all.

Filtering per order is more robust than an account-level switch anyway, because
the same account usually serves a web flow that has no such restriction. The
parameter rules are in
[Checkout customization](/docs/en/developer-docs/integration/checkout/customization#payment-method-filtering).

## Should I just open the checkout in an external browser from the start?

It is a legitimate design, and for some payment methods it is the only one that
works — the per-method notes list the cases where a method's own flow cannot run
inside a merchant App WebView.

The trade-offs to weigh:

| | In-App WebView | External browser from the start |
| - | - | - |
| Customer stays in your App | Yes | No — a visible App switch |
| Wallet App launch | Needs scheme interception in your App | Handled by the browser |
| Download / copy / long-press save | Needs explicit support in your WebView | Works |
| Returning to your App after payment | Your redirect handling | Depends on the customer, or a deeplink redirect URL |
| Methods that refuse a merchant App WebView | Must be hidden or opened externally | No special handling |

A middle path many integrations settle on: keep the WebView for the flows that
work in it, and open the external browser only for the orders whose payment
method requires it — which you know at create time, because you chose the method.

Note that `successRedirectUrl`, `failedRedirectUrl` and `cancelRedirectUrl`
accept deeplinks as well as HTTPS URLs, so an external-browser flow can still
hand the customer back to your App.

## Is there an SDK that wraps the App-side launch for me?

The Waffo front-end SDK covers the web surface — rendering card fields, and
embedding the checkout in your page. The App-side pieces — intercepting a
non-HTTP(S) navigation in your WebView and handing it to the operating system —
are platform APIs in your own App, and there is no Waffo library that replaces
them. The platform documentation links for both Android and iOS are in
[Steps → custom schemes](/docs/en/developer-docs/integration/checkout/steps#handle-wallet-app-custom-schemes).

## Can I send the checkout link to the customer directly, by SMS or email?

That is what a payment link is for, and it is a separate product surface with
its own expiry and reuse rules — see [Payment links](/docs/en/support/payment-link-faq).
Do not repurpose a checkout URL from an API-created order as a link you send
out: it belongs to one order, it expires with that order, and once the order
reaches a final state the link shows the expired screen.

***

Hitting a WebView failure you cannot place? [Contact support](mailto:support@waffo.com)
with the five items from the capture list above.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.