Developer Documentation

Drop-In Checkout

New

Accept payments with a single component — no custom form code required. Drop-In handles payment method selection, card rendering, 3DS, and confirmation.

PCI Compliant
3D Secure
Multi-Currency
Responsive
Customizable

Overview

Drop-In is ClapPay's pre-built payment UI. It embeds as a single iframe and manages the complete payment flow — from payment method selection through 3DS authentication and payment confirmation.

Fast Integration

Working checkout in under 30 minutes

Minimal Code

Create a session + mount the component

PCI Compliant

Card data never touches your servers

Installation

Install the ClapPay JavaScript SDK:

bash
npm install @clappay/js
# or
yarn add @clappay/js

Step 1 — Create a Drop-In Session (Server-Side)

Always create Drop-In sessions server-side using your secret key. Never expose your secret key in client-side code.

typescript
// app/api/checkout/session/route.ts (Next.js App Router)
import { NextResponse } from 'next/server';

export async function POST(req: Request) {
  const { amount, currency, returnUrl } = await req.json();

  const session = await fetch(
    `${process.env.CLAPPAY_API_URL}/api/v1/payment/v2/dropin-sessions/`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.CLAPPAY_SECRET_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ amount, currency, return_url: returnUrl }),
    }
  ).then(r => r.json());

  return NextResponse.json({
    sessionId: session.session.session_id,
    clientSecret: session.session.client_secret,
    publishableKey: process.env.NEXT_PUBLIC_CLAPPAY_PK,
  });
}

Step 2 — Mount the Component (React / Next.js)

tsx
'use client';
// app/checkout/page.tsx
import { useState, useEffect } from 'react';
import { ClapPayDropInComponent } from '@clappay/js/adapters/nextjs-dropin';
import { useRouter } from 'next/navigation';

export default function CheckoutPage() {
  const router = useRouter();
  const [session, setSession] = useState<{ sessionId: string; clientSecret: string; publishableKey: string } | null>(null);

  useEffect(() => {
    fetch('/api/checkout/session', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ amount: 4999, currency: 'USD', returnUrl: `${window.location.origin}/thanks` }),
    })
      .then(r => r.json())
      .then(setSession);
  }, []);

  if (!session) return <p>Loading checkout…</p>;

  return (
    <ClapPayDropInComponent
      publishableKey={session.publishableKey}
      sessionId={session.sessionId}
      clientSecret={session.clientSecret}
      amount={4999}
      currency="USD"
      returnUrl={`${window.location.origin}/thanks`}
      appearance={{ theme: 'auto', primaryColor: '#6366f1' }}
      onSuccess={({ paymentIntentId }) => router.push(`/order/${paymentIntentId}`)}
      onError={({ message }) => alert(message)}
      onReady={() => console.log('Drop-In ready')}
      className="max-w-md mx-auto"
    />
  );
}

Vanilla JavaScript Integration

javascript
import { loadClapPayDropIn } from '@clappay/js/dropin';

// 1. Create session (server-side call, here simplified)
const { sessionId, clientSecret, publishableKey } = await fetch('/api/checkout/session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ amount: 4999, currency: 'USD', returnUrl: 'https://example.com/thanks' }),
}).then(r => r.json());

// 2. Load and mount Drop-In
const dropin = await loadClapPayDropIn(publishableKey, {
  container: '#payment-form',    // CSS selector or HTMLElement
  sessionId,
  clientSecret,
  amount: 4999,
  currency: 'USD',
  returnUrl: 'https://example.com/thanks',
  locale: 'en',
  appearance: { theme: 'auto' },
});

// 3. Listen for events
dropin
  .on('ready',      ()       => console.log('Drop-In ready'))
  .on('success',    (data)   => window.location.href = `/order/${data.paymentIntentId}`)
  .on('error',      (err)    => console.error(err.message))
  .on('processing', ()       => showSpinner())
  .on('cancel',     ()       => closeModal());

// 4. Mount
dropin.mount();

Customization

Use the appearance prop to customize colors, fonts, and corner radius.

typescript
const appearance = {
  theme: 'light' | 'dark' | 'auto',   // follows system preference when 'auto'
  primaryColor: '#6366f1',             // button + focus ring color
  fontFamily: 'Inter, sans-serif',     // custom font
  borderRadius: '8px',                 // card/input corner radius
};

Events Reference

EventPayloadDescription
readyvoidDrop-In is mounted and ready for interaction
success{ paymentIntentId, status, amount, currency }Payment completed successfully
error{ message, code?, type? }Payment failed or validation error
processingvoidPayment is being processed (network call in progress)
cancelvoidCustomer cancelled the payment

Security

PCI DSS Compliant

Card data is captured inside a ClapPay-hosted iframe and never passes through your servers.

Session Expiry

Drop-In sessions expire after 2 hours. Create a new session for each checkout attempt.

Origin Validation

The Drop-In iframe validates the parent origin to prevent clickjacking attacks.

CSP Compatible

Add `frame-src 'self' https://api.clappay.com;` to your Content-Security-Policy.