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

# Integrating Monieswitch Checkout in Web Applications

> A simple guide to embedding Monieswitch Checkout for seamless Naira payments in your website.

### Who is this for?

<Info>
  Web developers who want to accept Naira payments using the Monieswitch
  Checkout widget in their websites or web applications.
</Info>

## Overview

This guide covers:

* Direct Checkout (simple, client-side)
* Continued Checkout (secure, server-initialized)
* Payment verification with webhooks
* Basic error handling

***

## Prerequisites

<Steps>
  <Step title="Monieswitch Account">
    **A Monieswitch account**. Register at [Monieswitch
    Dashboard](https://dashboard.monieswitch.com/register).
  </Step>

  <Step title="API Keys">
    **Your public and secret keys** from the Monieswitch dashboard.
  </Step>

  <Step title="Web Application">
    **A website or web application** where you want to accept payments.
  </Step>
</Steps>

***

## 1. Setup

### Add Monieswitch Library

Include this script in your HTML:

```html index.html theme={"system"}
<script
  defer
  src="https://monieswitch-staging-checkout-inline.pages.dev/inline.js"
></script>
```

***

## 2. Direct Checkout (Simple)

Best for quick implementations and testing.

```html index.html theme={"system"}
<script
  defer
  src="https://monieswitch-staging-checkout-inline.pages.dev/inline.js"
></script>

<div class="container">
  <div class="payment-section">
    <h2 class="section-title">Direct Checkout</h2>

    <form id="paymentForm">
      <div class="form-group">
        <label for="email-address">Email Address</label>
        <input
          type="email"
          id="email-address"
          placeholder="Enter your email"
          required
        />
      </div>

      <div class="form-group">
        <label for="amount">Amount (₦)</label>
        <input
          type="number"
          id="amount"
          placeholder="Enter amount"
          min="1"
          required
        />
      </div>

      <div class="form-group">
        <label for="bearer">Bearer Type</label>
        <select id="bearer" required>
          <option value="">Select bearer type</option>
          <option value="account">Account</option>
          <option value="subaccount">Subaccount</option>
          <option value="customer">Customer</option>
        </select>
      </div>

      <div class="form-group">
        <label for="subaccount">Subaccount ID (Optional)</label>
        <input type="text" id="subaccount" placeholder="Enter subaccount ID" />
      </div>

      <button type="submit" class="btn-primary">Pay with Monieswitch</button>
    </form>
  </div>
</div>

<script>
  const paymentForm = document.getElementById("paymentForm");

  paymentForm.addEventListener("submit", function (e) {
    e.preventDefault();

    PayWithMonieswitch.checkout({
      publicKey: "pk_test_fDWvDVIBEHoSLchxGx02JtxZYP4tC7qFeGhUtmkgdnML8ZRb",
      reference: Date.now(),
      amount: Number(document.getElementById("amount").value),
      email: document.getElementById("email-address").value,
      currency: "NGN",
      channels: ["BANK"],
      bearer: document.getElementById("bearer").value,
      subaccountId: document.getElementById("subaccount").value,
      redirectURL: "",
      onClose: function () {},
      onError: function (error) {
        console.log("Error: ", error);
      },
      onSuccess: function (reference) {
        console.log("Success: " + reference);
      },
    });
  });
</script>
```

***

## 3. Continued Checkout (Recommended)

More secure as payment details are initialized on your server.

### Backend Setup

```javascript backend/server.js theme={"system"}
require("dotenv").config();
const express = require("express");
const axios = require("axios");
const app = express();

app.use(express.json());

// Initialize checkout
app.post("/api/checkout/initialize", async (req, res) => {
  try {
    const { amount, email } = req.body;

    const response = await axios.post(
      "https://nini.monieswitch.com/checkout/initialize",
      {
        amount: parseFloat(amount),
        email: email,
        currency: "NGN",
      },
      {
        headers: {
          "x-access-token": process.env.MONIESWITCH_SECRET_KEY,
          "x-pub-key": process.env.MONIESWITCH_PUBLIC_KEY,
        },
      }
    );

    res.json(response.data);
  } catch (error) {
    res.status(500).json({ error: "Failed to initialize payment" });
  }
});

app.listen(3000);
```

### Frontend Implementation

```html index.html theme={"system"}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Monieswitch Continue Checkout</title>
    <script
      defer
      src="https://monieswitch-staging-checkout-inline.pages.dev/inline.js"
    ></script>
  </head>
  <body>
    <div class="container">
      <div class="payment-section">
        <h2 class="section-title">Continue Checkout</h2>

        <form id="continuePaymentForm">
          <div class="form-group">
            <label for="code">Checkout Code</label>
            <input
              type="text"
              id="code"
              placeholder="Enter checkout code"
              required
            />
          </div>

          <button type="submit" class="btn-primary">Continue Payment</button>
        </form>
      </div>
    </div>

    <script>
      document
        .getElementById("continuePaymentForm")
        .addEventListener("submit", function (e) {
          e.preventDefault();

          PayWithMonieswitch.continueCheckout({
            checkoutCode: document.getElementById("code").value,
            onClose: function () {},
            onError: function (error) {
              console.log("Error: ", error);
            },
            onSuccess: function (reference) {
              console.log("Success: " + reference);
            },
          });
        });
    </script>
  </body>
</html>
```

***

## 5. Payment Verification

### Backend Verification

```javascript backend/server.js theme={"system"}
// Verify payment status after success callback
app.get("/status", async (req, res) => {
  try {
    const { reference } = req.body;

    const response = await axios.get(
      `https://nini.monieswitch.com/checkout/status/${reference}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.MONIESWITCH_SECRET_KEY}`,
        },
      }
    );

    const payment = response.data;

    if (payment.hasPaid) {
      // Payment verified - update your database, send email, etc.
      console.log("Payment verified:", payment);
    }

    res.json(payment);
  } catch (error) {
    res.status(500).json({ error: "Verification failed" });
  }
});
```

### Webhook Handler (Recommended)

```javascript backend/server.js theme={"system"}
// Handle webhook notifications
app.post("/webhooks/monieswitch", (req, res) => {
  const event = req.body;

  if (event.event === "payment.successful") {
    const payment = event.data;
    console.log("Payment received:", payment.reference);

    // Update your database
    // Send confirmation email
    // Fulfill order
  }

  res.status(200).send("OK");
});
```

***

## 6. Environment Variables

Create a `.env` file for your backend:

```env theme={"system"}
MONIESWITCH_PUBLIC_KEY=your_public_key_here
MONIESWITCH_SECRET_KEY=your_secret_key_here
```

***

## Security Best Practices

<Warning title="Important Security Notes">
  * Never expose your **SECRET\_KEY** in frontend code - Always verify payments
    on your backend - Use webhooks for reliable payment notifications - Validate
    all payment amounts server-side
</Warning>

1. **Client-side**: Only use your public key
2. **Server-side**: Keep your secret key secure
3. **Verification**: Always verify payments on your backend
4. **Webhooks**: Use webhooks for real-time payment updates

***

## Common Payment Channels

The supported payment channels in Nigeria are:

* **BANK** - Bank transfer
* **CARD** - Debit/Credit cards
* **USSD** - USSD payments

```javascript theme={"system"}
channels: ["BANK", "CARD", "USSD"];
```

***

## Error Handling

```javascript theme={"system"}
onError: function(error) {
  // Handle different error types
  if (error.code === 'PAYMENT_CANCELLED') {
    console.log('User cancelled payment');
  } else if (error.code === 'INSUFFICIENT_FUNDS') {
    alert('Insufficient funds');
  } else {
    alert('Payment failed: ' + error.message);
  }
}
```

***

## Next Steps

* Set up [webhooks](/features/payments/webhook) for reliable payment notifications
* Add payment status tracking in your app
* Test with small amounts before going live
* Check the [API Reference](/api-reference/introduction) for more features
