# Embedded iframe

> Load the Ozow payment page inside a container on your own checkout with the Ozow SDK, so your customer never leaves your site.

Source: https://hub.ozow.com/integration-methods/apis/payin/embedded-iframe/

The embedded iframe embeds the Ozow payment page directly inside a container on your own page. Your
customer never leaves your site, the full payment experience loads inside an iframe within your
checkout flow.

**This guide is a Payments API integration.** You create the payment request with
[`POST /postpaymentrequest`](https://hub.ozow.com/api-reference/payments-api/post-post-payment-request.md), authenticate with
your API key, and sign the hash with your private key: the One API Client ID and Client Secret
are not used here. [Prerequisites and
onboarding](https://hub.ozow.com/getting-started/prerequisites-and-onboarding.md) says which credential
belongs to which API.

> ⚠️ **Important**: You must use the Ozow SDK to implement the iframe checkout. Do not attempt to
> build your own iframe implementation or embed the Ozow payment page directly without the SDK. Only
> SDK-based implementations are supported and guaranteed to function correctly.

Not sure which embedded option is right for you? See [Choose your integration](https://hub.ozow.com/integration-methods.md).

## Before you start

- You have completed [Prerequisites and onboarding](https://hub.ozow.com/getting-started/prerequisites-and-onboarding.md)
- You have your API key, private key, and site code from your [Ozow Dashboard](https://dash.ozow.com)
- **jQuery 1.12.x or higher is required**: the Ozow SDK depends on jQuery. Make sure it is loaded on
  your page before the Ozow SDK script.
- Your notification URL, success URL, cancel URL, and error URL are set up and publicly accessible
  via HTTPS

## How iframe checkout works

```mermaid
sequenceDiagram
    participant C as Customer
    participant M as Your page
    participant S as Ozow SDK
    participant O as Payments API
    participant P as Ozow iframe

    C->>M: Reaches checkout
    M->>O: POST /postpaymentrequest
    O-->>M: Returns payment URL
    M->>S: createPaymentFrame(container, paymentUrl, postData)
    S->>P: Loads Ozow payment page in iframe
    C->>P: Completes payment inside iframe
    O-->>M: Sends notification to NotifyUrl
    M->>M: Verifies notification hash
    S->>M: Redirects parent page after completion
```

## Environments

| Environment | Payment request endpoint | SDK payment URL | Dashboard |
|---|---|---|---|
| Production | `https://api.ozow.com/postpaymentrequest` | `https://pay.ozow.com/` | [dash.ozow.com](https://dash.ozow.com) |
| Staging | `https://stagingapi.ozow.com/postpaymentrequest` | `https://stagingpay.ozow.com/` | [stagingdash.ozow.com](https://stagingdash.ozow.com) |

> ℹ️ **Note**: The SDK payment URL (`pay.ozow.com`) is different from the API endpoint
> (`api.ozow.com`). Make sure you use the correct URL for each purpose.

---

## Core integration

### Step 1: Create a payment request

Create a payment request server-side using the Payments API. This is identical to the redirect
integration, follow [Steps 1 and 2 in the Redirect: Payments API
guide](https://hub.ozow.com/integration-methods/apis/deprecated-integrations/redirect-to-ozow.md) to generate the hash check and post the payment
request.

The response returns a `url`, this is your `paymentUrl` for the SDK in Step 4.

> ⚠️ **Important**: Never generate the hash or expose your private key in browser code. The payment
> request must be created server-side.

---

### Step 2: Install the SDK

Add jQuery and the Ozow SDK script to your page. jQuery must be loaded before the Ozow SDK.

```html
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://static-content.ozow.com/scripts/js/v2/ozow-integration-2.0.min.js"></script>
```

---

### Step 3: Add the page markup

Add a container div where the iframe will be rendered, a trigger element to launch the payment, and
a cancel button:

```html
<!-- Container where the iframe will be rendered -->
<div id="paymentContainer"></div>

<!-- Trigger element - customer clicks this to start payment -->
<input type="radio" id="payUsingOzow" value="Ozow" /> Pay with Ozow

<!-- Cancel button -->
<button id="cancelOzowPayment">Cancel Payment</button>
```

---

### Step 4: Initialise the SDK and launch the iframe

Instantiate the SDK and wire up your trigger element to launch the iframe when the customer selects
Ozow as their payment method.

```javascript
const ozow = new Ozow();

const paymentUrl = "https://pay.ozow.com/"; // Use https://stagingpay.ozow.com/ for staging
const postData = {
  SiteCode: "YOUR_SITE_CODE",
  CountryCode: "ZA",
  CurrencyCode: "ZAR",
  Amount: "100.00",
  TransactionReference: "ORDER-001",
  BankReference: "ABC123",
  CancelUrl: "https://yourstore.com/cancel",
  ErrorUrl: "https://yourstore.com/error",
  SuccessUrl: "https://yourstore.com/success",
  NotifyUrl: "https://yourstore.com/notify",
  IsTest: "false",
  HashCheck: "YOUR_GENERATED_HASH",
};

document.getElementById("payUsingOzow").onclick = () => {
  ozow.createPaymentFrame("paymentContainer", paymentUrl, postData);
};
```

The SDK automatically appends `?viewName=JsInjection` to the payment URL. Your success, cancel, and
error URLs are automatically rewritten to `/payment/iframeredirect?redirecturl=<ENCODED_URL>`; no
extra work required on your side.

---

### Step 5: Handle cancellation

Wire up the cancel button to dismiss the iframe:

```javascript
document.getElementById("cancelOzowPayment").onclick = () => {
  ozow.cancelFramePayment();
};
```

---

### Step 6: Handle the payment outcome

Ozow sends a notification to your `NotifyUrl` when the transaction completes. Handle this exactly as
described in [Step 4: Handle the notification
response](https://hub.ozow.com/integration-methods/apis/deprecated-integrations/redirect-to-ozow.md#step-4-handle-the-notification-response) in
the Redirect, Payments API guide, same format, same hash verification process.

After the payment is complete, the SDK automatically redirects the parent page to your `SuccessUrl`,
`CancelUrl`, or `ErrorUrl` depending on the outcome.

> ℹ️ **Note**: The SDK handles the following postMessage events internally. You only need to add a
> custom listener if you require additional behaviour beyond the defaults.

| Event | SDK behaviour |
|---|---|
| `ozowResize` | Resizes the iframe height automatically |
| `ipayMessage` | Redirects the parent page after payment completion |

**Optional custom event listener**

```javascript
window.addEventListener("message", (e) => {
  if (e.data?.event === "ozowResize") {
    // Optional custom handling
  }
});
```

---

## Error handling

If the container ID, payment URL, or post data are invalid, the SDK will:

1. Log a descriptive error message to the browser console
2. Display an alert to the customer: **"Payment could not be completed, please contact the site administrator."**

Check the browser console for detailed error information during development.

---

## Complete example

```html
<div id="paymentContainer"></div>
<input type="radio" id="payUsingOzow" value="Ozow" /> Pay with Ozow
<button id="cancelOzowPayment">Cancel</button>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://static-content.ozow.com/scripts/js/v2/ozow-integration-2.0.min.js"></script>
<script>
  const ozow = new Ozow();
  const paymentUrl = "https://pay.ozow.com/";
  const postData = {
    SiteCode: "YOUR_SITE_CODE",
    CountryCode: "ZA",
    CurrencyCode: "ZAR",
    Amount: "100.00",
    TransactionReference: "ORDER-001",
    BankReference: "ABC123",
    CancelUrl: "https://yourstore.com/cancel",
    ErrorUrl: "https://yourstore.com/error",
    SuccessUrl: "https://yourstore.com/success",
    NotifyUrl: "https://yourstore.com/notify",
    IsTest: "false",
    HashCheck: "YOUR_GENERATED_HASH",
  };

  document.getElementById("payUsingOzow").onclick = () =>
    ozow.createPaymentFrame("paymentContainer", paymentUrl, postData);

  document.getElementById("cancelOzowPayment").onclick = () =>
    ozow.cancelFramePayment();
</script>
```