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

# In-page Checkout

> Create overlay and embedded checkout sessions that keep the buyer on your site.

In-page Checkout keeps the buyer on your site. Unlike [Redirect Checkout](/universal-payment-gateway/advanced-setup/redirect-checkout), its supported provider presentation is an overlay or an embedded provider checkout.

## In-page capability reference

The **Supported SDK mode** is the value supplied to `CreateOrderOptions`. The **Public checkout type** is returned in `PaymentSession::$checkout['type']`. It identifies the provider instruction returned by the prepared session; it is not a separate browser-selected setting.

| Gateway | Supported SDK mode | Public checkout type | SDK-only presentation |
| - | - | - | - |
| PayHere | `overlay` | `overlay` | Start PayHere’s official browser overlay with the returned signed fields |
| OnePay | `overlay` | `onepay_sdk_overlay` | Start the OnePay official SDK overlay with the returned direct gateway URL and transaction ID |
| DirectPay | `overlay` | `directpay_v3` | Start the DirectPay V3 official overlay with the returned signed payload |
| DirectPay | `embedded` | `directpay_v3` | Mount the DirectPay V3 official checkout in a container on your page |

The table describes platform capabilities. A gateway/mode pair is usable only when it is currently returned by your backend's `availability()` call for the configured domain and selected environment.

## 1. Prepare an overlay session

Choose a gateway/mode pair returned by `availability()` with `mode: overlay`. PayHere, OnePay, and DirectPay currently support Overlay checkout. Persist the returned `completionContext` with the pending merchant order before sending public checkout instructions to the browser.

<Tabs>
  <Tab title="PHP">
    ```php theme={null}
    use Avraapi\Apix\Payments\CheckoutMode;
    use Avraapi\Apix\Payments\CreateOrderOptions;
    use Avraapi\Apix\Payments\GatewayCode;

    $overlaySession = $apix->payment()->createOrder(new CreateOrderOptions(
        gateway: GatewayCode::from($selectedMethod['gateway']),
        mode: CheckoutMode::Overlay,
        orderId: $orderId,
        items: $items,
        amount: $amount,
        currency: $currency,
        customer: $customer,
        urls: $urls,
        merchantDomain: $merchantDomain, // Optional
        providerOptions: $providerOptions, // Optional
    ));

    // Persist server-only completion evidence with your pending order.
    $completionContext = $overlaySession->completionContext;
    ```
  </Tab>

  <Tab title="Laravel">
    ```php theme={null}
    use Avraapi\Laravel\Facades\AvraAPI;

    use Avraapi\Apix\Payments\CheckoutMode;
    use Avraapi\Apix\Payments\CreateOrderOptions;
    use Avraapi\Apix\Payments\GatewayCode;

    $overlaySession = AvraAPI::payment()->createOrder(new CreateOrderOptions(
        gateway: GatewayCode::from($selectedMethod['gateway']),
        mode: CheckoutMode::Overlay,
        orderId: $orderId,
        items: $items,
        amount: $amount,
        currency: $currency,
        customer: $customer,
        urls: $urls,
        merchantDomain: $merchantDomain, // Optional
        providerOptions: $providerOptions, // Optional
    ));

    // Persist server-only completion evidence with your pending order.
    $completionContext = $overlaySession->completionContext;
    ```
  </Tab>

  <Tab title="Node.js">
    ```ts theme={null}
    import { CheckoutMode, CreateOrderOptions, GatewayCode } from '@avraapi/node-sdk';

    const overlaySession = await client.payment().createOrder(new CreateOrderOptions({
      gateway: selectedMethod.gateway as GatewayCode,
      mode: CheckoutMode.Overlay,
      orderId, items, amount, currency, customer, urls,
      merchantDomain, providerOptions,
    }));
    await orders.savePending({ completionContext: overlaySession.completionContext });
    ```
  </Tab>
</Tabs>

<Note>
  The selected method must be an `overlay` method returned by your server-side `availability()` result. Do not accept a browser-provided gateway name or mode without that validation.
</Note>

## 2. Prepare an embedded session

**Embedded checkout currently supports DirectPay only.** Use `CheckoutMode::Embedded` only when DirectPay Embedded is returned by `availability()`. The same trusted order, customer, URL, and optional configuration values used above apply here.

<Tabs>
  <Tab title="PHP">
    ```php theme={null}
    use Avraapi\Apix\Payments\CheckoutMode;
    use Avraapi\Apix\Payments\CreateOrderOptions;
    use Avraapi\Apix\Payments\GatewayCode;

    $embeddedSession = $apix->payment()->createOrder(new CreateOrderOptions(
        gateway: GatewayCode::DirectPay,
        mode: CheckoutMode::Embedded,
        orderId: $orderId,
        items: $items,
        amount: $amount,
        currency: $currency,
        customer: $customer,
        urls: $urls,
        merchantDomain: $merchantDomain, // Optional
        providerOptions: $providerOptions, // Optional
    ));

    // Persist server-only completion evidence with your pending order.
    $completionContext = $embeddedSession->completionContext;
    ```
  </Tab>

  <Tab title="Laravel">
    ```php theme={null}
    use Avraapi\Laravel\Facades\AvraAPI;

    use Avraapi\Apix\Payments\CheckoutMode;
    use Avraapi\Apix\Payments\CreateOrderOptions;
    use Avraapi\Apix\Payments\GatewayCode;

    $embeddedSession = AvraAPI::payment()->createOrder(new CreateOrderOptions(
        gateway: GatewayCode::DirectPay,
        mode: CheckoutMode::Embedded,
        orderId: $orderId,
        items: $items,
        amount: $amount,
        currency: $currency,
        customer: $customer,
        urls: $urls,
        merchantDomain: $merchantDomain, // Optional
        providerOptions: $providerOptions, // Optional
    ));

    // Persist server-only completion evidence with your pending order.
    $completionContext = $embeddedSession->completionContext;
    ```
  </Tab>

  <Tab title="Node.js">
    ```ts theme={null}
    import { CheckoutMode, CreateOrderOptions, GatewayCode } from '@avraapi/node-sdk';

    const embeddedSession = await client.payment().createOrder(new CreateOrderOptions({
      gateway: GatewayCode.DirectPay,
      mode: CheckoutMode.Embedded,
      orderId, items, amount, currency, customer, urls,
      merchantDomain, providerOptions,
    }));
    await orders.savePending({ completionContext: embeddedSession.completionContext });
    ```
  </Tab>
</Tabs>

## 3. Return only public checkout instructions

The exact `checkout` object is provider-specific. Return its public fields unchanged to the browser. Set `$checkoutSession` to the Overlay or Embedded session you just created. Never include `completionContext`, Vault credentials, project credentials, or internal order data.

<Tabs>
  <Tab title="PHP">
    ```php theme={null}
    $checkoutSession = $overlaySession;
    // For DirectPay Embedded instead: $checkoutSession = $embeddedSession;

    http_response_code(200);
    header('Content-Type: application/json; charset=UTF-8');

    echo json_encode([
        'gateway' => $checkoutSession->gateway->value,
        'mode' => $checkoutSession->mode->value,
        'status' => $checkoutSession->status,
        'expires_at' => $checkoutSession->expiresAt,
        'checkout' => $checkoutSession->checkout,
        'request_id' => $checkoutSession->requestId,
    ], JSON_THROW_ON_ERROR);
    ```
  </Tab>

  <Tab title="Laravel">
    ```php theme={null}
    $checkoutSession = $overlaySession;
    // For DirectPay Embedded instead: $checkoutSession = $embeddedSession;

    http_response_code(200);
    header('Content-Type: application/json; charset=UTF-8');

    echo json_encode([
        'gateway' => $checkoutSession->gateway->value,
        'mode' => $checkoutSession->mode->value,
        'status' => $checkoutSession->status,
        'expires_at' => $checkoutSession->expiresAt,
        'checkout' => $checkoutSession->checkout,
        'request_id' => $checkoutSession->requestId,
    ], JSON_THROW_ON_ERROR);
    ```
  </Tab>

  <Tab title="Node.js">
    ```ts theme={null}
    const checkoutSession = overlaySession; // Or embeddedSession for DirectPay Embedded.

    return response.json({
      gateway: checkoutSession.gateway,
      mode: checkoutSession.mode,
      status: checkoutSession.status,
      expires_at: checkoutSession.expiresAt,
      checkout: checkoutSession.checkout,
      request_id: checkoutSession.requestId,
    }); // Never include completionContext.
    ```
  </Tab>
</Tabs>

## 4. Launch the provider presentation

<Tip>
  **Payment Elements is highly recommended for Overlay and Embedded checkout.** It handles method rendering and the provider presentation using the public session returned by your backend. It remains optional: the SDK-only integration below is fully supported when you need to integrate each provider's official browser SDK yourself.
</Tip>

For an SDK-only integration, load and use the selected provider's official browser SDK according to its documentation, passing only the public fields returned in `checkout`. Do not create or alter the signed checkout data yourself.

| Public checkout type | Required public fields | Browser responsibility |
| - | - | - |
| `overlay` | `script_url`, `fields` | Load the returned PayHere script and start its payment overlay with `fields` |
| `onepay_sdk_overlay` | `direct_gateway_url`, `direct_transaction_id` | Pass both values to the official OnePay browser SDK overlay |
| `directpay_v3` | `script_url`, `data_string`, `signature`, `stage` | Load the returned DirectPay V3 script and start overlay or container checkout according to session `mode` |

In the examples below, `publicSession` is the exact **public** session object returned by your backend in the previous step. It must not contain `completionContext`.

### PayHere Overlay — SDK-only

Load PayHere’s official browser script, assign UI-only callbacks, then pass the returned signed fields directly to `startPayment()`.

```html theme={null}
<script src="https://www.payhere.lk/lib/payhere-2.0.js"></script>
<script>
  const checkout = publicSession.checkout;

  if (publicSession.mode !== 'overlay' || checkout.type !== 'overlay') {
    throw new Error('Expected a PayHere Overlay payment session.');
  }

  payhere.onCompleted = (orderId) => {
    // Update browser UI only. notify_url completion remains authoritative.
    console.info('PayHere browser flow completed for order:', orderId);
  };

  payhere.onDismissed = () => console.info('PayHere checkout was dismissed.');
  payhere.onError = (error) => console.error('PayHere checkout error:', error);

  payhere.startPayment(checkout.fields);
</script>
```

### OnePay Overlay — SDK-only

Install OnePay’s official browser SDK in your frontend build, then initialize it once and pass only the returned OnePay public fields. The SDK event is a UI signal; your server still completes the payment through `completePayment()`.

```js theme={null}
import { OnePaySDK } from '@onepaynpm/onepay-sdk';

const checkout = publicSession.checkout;

if (publicSession.mode !== 'overlay' || checkout.type !== 'onepay_sdk_overlay') {
  throw new Error('Expected a OnePay Overlay payment session.');
}

const onePay = new OnePaySDK({ debug: false });
await onePay.initialize();

onePay.addEventListener({
  onSuccess: (result) => console.info('OnePay browser flow completed:', result),
  onFail: (result) => console.error('OnePay checkout failed:', result),
  onClose: () => console.info('OnePay checkout was closed.'),
});

await onePay.processDirectPayment({
  directGatewayURL: checkout.direct_gateway_url,
  directTransactionId: checkout.direct_transaction_id,
});
```

### DirectPay Overlay and Embedded — SDK-only

Load DirectPay’s official V3 script. Use `doInAppCheckout()` for an Overlay session. Use `doInContainerCheckout()` for an Embedded session and give DirectPay a dedicated container ID. The signed fields returned by AvraAPI must remain unchanged.

```html theme={null}
<script src="https://cdn.directpay.lk/v3/directpayipg.min.js"></script>

<div id="directpay-checkout"></div>

<script>
  const checkout = publicSession.checkout;

  if (!['overlay', 'embedded'].includes(publicSession.mode)
      || checkout.type !== 'directpay_v3') {
    throw new Error('Expected a DirectPay Overlay or Embedded payment session.');
  }

  const payment = new DirectPayIpg.Init({
    signature: checkout.signature,
    dataString: checkout.data_string,
    stage: checkout.stage,
    ...(publicSession.mode === 'embedded'
      ? { container: 'directpay-checkout' }
      : {}),
  });

  const browserResult = publicSession.mode === 'overlay'
    ? await payment.doInAppCheckout()
    : await payment.doInContainerCheckout();

  // This is UI feedback only. Do not mark the order paid here.
  console.info('DirectPay browser result:', browserResult);
</script>
```

Browser completion events are display signals only. They can show progress, cancellation, or an error, but cannot mark an order paid.

## 5. Verify server-side completion

Receive the provider callback or return on your backend, load the stored `completionContext`, and call `completePayment()` with the gateway-required evidence. DirectPay requires its signed callback body and authorization header; OnePay always verifies its upstream provider status before a payment can succeed. Follow [Payment Response & Completion](/universal-payment-gateway/advanced-setup/webhooks-and-completion) before fulfilment.

## Optional: Payment Elements

[Payment Elements](/universal-payment-gateway/payment-elements/overview) is optional. It can launch the same returned PayHere, OnePay, and DirectPay public checkout instructions for you. It does not replace the server-side SDK preparation or completion steps on this page.

For setup options, safe availability rendering, and browser events, see [Payment Elements](/universal-payment-gateway/payment-elements/overview).


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