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

# Embedded Checkout

> Open the checkout in an overlay on your own page instead of redirecting the customer to a payment page.

Embedded Checkout opens the PayBridgeNP checkout in an overlay on your own page
instead of sending the customer to a payment page. Your page stays behind it and
its address bar never changes, and when the payment finishes the overlay closes
and hands the customer back to you.

Paying still involves the wallet the customer picks. Fonepay is completed inside
the overlay, and so is eSewa when your project is on the eSewa Intent rail.
Khalti sends the customer to its own app or website and brings them back. So the
overlay removes the redirect to *us*, not every hand-off to a wallet.

It is the same checkout you get from the [quickstart](/quickstart), the same
providers, and the same verification. Only the way the customer reaches it
differs.

<Note>
  Embedded Checkout requires a **Growth plan or higher**, because it is
  delivered through a [payment button](/guides/payment-buttons) and those are
  not available on the Free plan.
</Note>

<Note>
  Embedded Checkout is live. Nothing changes for an existing button until you
  tick **Open over my own page** on it and add your origin to the embed
  allowlist, so buttons keep redirecting until you opt them in.
</Note>

## Hosted or Embedded

|                           | Hosted Checkout              | Embedded Checkout          |
| ------------------------- | ---------------------------- | -------------------------- |
| Where the customer pays   | On a PayBridgeNP page        | In an overlay on your page |
| Address bar               | Changes to the checkout URL  | Never changes              |
| Integration               | Redirect to the returned URL | Add the button script      |
| Payment methods           | eSewa, Khalti, Fonepay       | eSewa, Khalti, Fonepay     |
| Verification and webhooks | Identical                    | Identical                  |
| Settlement                | Your own merchant accounts   | Your own merchant accounts |

## How it works

<Steps>
  <Step title="Create a payment button and turn the overlay on">
    Configure it as you would a normal
    [payment button](/guides/payment-buttons), then tick **Open over my own
    page** under "Where the checkout opens". Buttons redirect to a
    PayBridgeNP checkout page until you do, so an existing button never
    changes behaviour on its own.
  </Step>

  <Step title="Add your origin to the allowlist">
    Register your web page origin under **Project -> Embed domains** in your
    merchant dashboard.
  </Step>

  <Step title="Add the script to your page">
    The same one-line embed. No separate SDK.
  </Step>

  <Step title="The customer taps it">
    The overlay opens over your page. Your page is never navigated.
  </Step>

  <Step title="They pay and come back">
    The overlay closes and returns them to your return URL at the top level, not
    inside the frame.
  </Step>
</Steps>

```html theme={null}
<script
  src="https://api.paybridgenp.com/js/v1/button.js"
  data-button-id="btn_your_button_id"
></script>
```

## If your shopper is already signed in

Pass what you know and the overlay opens with it filled in:

```html theme={null}
<script
  src="https://api.paybridgenp.com/js/v1/button.js"
  data-button-id="btn_your_button_id"
  data-customer-name="Ramesh Shrestha"
  data-customer-email="ramesh@example.com"
  data-customer-phone="9812345678"
></script>
```

This matters more in the overlay than anywhere else. The overlay collects
contact details itself, so without this a signed-in shopper would retype
details your site already had. See
[payment buttons](/guides/payment-buttons) for the full rules.

## Registering allowed embed domains

To protect your site and your customers from clickjacking, Embedded Checkout uses an explicit origin allowlist.

A page attempting to embed your checkout whose origin is not registered on your allowlist will be blocked by the browser.

### The symptom of an unallowed domain

If your site origin is not registered on your project allowlist:

* The checkout overlay opens as a blank frame and silently refuses to load.
* Your browser developer console displays a Content Security Policy error:
  `Refused to frame 'https://checkout.paybridgenp.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors ..."`

To fix this, register your page's exact web origin under **Project -> Embed domains** in your merchant dashboard.

### Domain allowlist rules

* **Exact origins only**: Enter full origins such as `https://shop.example.com` or `http://localhost:3000`. Do not include paths (`/checkout`), query parameters (`?ref=1`), fragment identifiers, or trailing slashes. Wildcards (like `*.example.com`) are not permitted.
* **Apex and WWW are distinct**: `https://example.com` and `https://www.example.com` are two separate web origins. If your customers access your shop on both forms, register both origins in your allowlist.
* **Scheme and environment rules**: Live mode requires secure `https://` origins. Unencrypted `http://` schemes and private or loopback IP addresses are rejected in Live mode. Sandbox mode permits `https://` as well as `http://` for local testing on `localhost` and `127.0.0.1`.
* **Domain capacity**: Each project can register up to 25 allowed embed domain origins per mode (Sandbox and Live).
* **The two-key system**: Registering your origin in the embed domain allowlist is required, but it is only half of enabling embedded checkout. The payment button itself **ALSO** needs **Open over my own page** ticked in its button settings. Both conditions must be met for the frame to render.

## Paying with a wallet

eSewa and Khalti authenticate inside their own app or website. That is what
keeps the customer's PIN away from your site and from ours, so the overlay
hands off rather than trying to contain it.

* **On a phone**, the wallet opens in place and returns to the checkout when it
  is done.
* **On a desktop**, the wallet may open in a separate window that closes itself
  once the payment lands. The overlay shows a waiting state until it does.
* **In an in-app browser** (a link opened inside Instagram, Facebook, or a
  similar app), the wallet always opens in place. Separate windows are
  unreliable there.

Fonepay is the exception: its QR is displayed and confirmed inside the overlay
with no hand-off at all.

While the customer is away, the overlay shows a waiting screen with a manual
status check. If a payment completes but the provider's confirmation never
reaches us, that check asks the provider directly rather than only re-reading
our own records.

## Closing and reopening is safe

If the customer closes the overlay and opens it again, they resume **the same
payment**, not a new one. Anything they had already typed is still there.

This matters for more than convenience: it means one order can never produce two
live payment sessions, so a customer cannot accidentally pay twice for the same
thing.

## PayBridgeNP ID inside the overlay

[PayBridgeNP ID](/guides/paybridgenp-id) works in the overlay, with one
difference worth planning around.

**What works.** A returning customer types their mobile number, we tell them we
have their details, they enter a one-time code, and their name, email and phone
fill in. Same as hosted checkout.

**What does not.** They are not recognised *before* they type. On hosted
checkout a returning customer is greeted by name on arrival; in the overlay they
always start by entering their number.

The reason is the browser, not a missing feature. Silent recognition depends on
a cookie on the PayBridgeNP domain, and browsers deliberately withhold that
cookie from a page running inside another site. The overlay is exactly that.

For the same reason, "remember me on this device" is offered only on hosted
checkout. The overlay does not show it, because the grant it creates could not
be delivered.

## What you still handle

The overlay is the payment step only. Your cart, your prices, your discounts,
and your order records stay yours. PayBridgeNP creates a session for an amount
you give it and tells you when that amount is paid.

Discount codes are a good example: apply them in your own cart and send us the
final amount. There is no promo-code field in the checkout.

## Verifying the payment

Do not treat the overlay closing as proof of payment. Confirm it the same way
you would for any other PayBridgeNP integration:

* Listen for the [`payment.succeeded` webhook](/guides/webhook-verification),
  which is signed and retried until you acknowledge it.
* Or read the session back through the API.

See [Confirming payments](/guides/confirming-payments) for the full contract.

## Limits

* Each button opts in separately. A button you have not ticked keeps
  redirecting.
* The overlay renders only on allowed origins registered for your project in the active mode.
* Wallet payments briefly leave the overlay, by design.
* Returning customers are not recognised until they enter their mobile number.
  Hosted Checkout greets them on arrival; the overlay cannot.
* The amount comes from the button, so the overlay suits a fixed price. A
  custom-amount button takes its amount from the page, which means the browser
  can change it. Never drive a cart total that way. Carts belong on Hosted
  Checkout, where your server states the amount.
* Platform plugins (WooCommerce, Shopify) use Hosted Checkout and cannot open
  the overlay.
