FloPay
Examples

Server-Side Session Creation

Create checkout sessions from your server using the billing API or the @flopay/js helper.

Before rendering a checkout form, you need a session UUID from the billing API. There are two approaches: a raw API route, or the createCheckoutSession helper from @flopay/js.

Next.js API Route

This is the recommended pattern for server-side session creation. It calls POST /v1/checkouts/sessions on the billing API and returns the session UUID.

app/api/create-session/route.ts
import { NextResponse } from 'next/server';
 
const billingApiUrl = process.env.BILLING_API_URL!;
const checkoutBaseUrl = process.env.NEXT_PUBLIC_CHECKOUT_BASE_URL!;
const clientId = process.env.FLOPAY_CLIENT_ID!;
 
export async function POST(request: Request) {
  try {
    const body = await request.json();
 
    const payload = {
      clientId,
      successUrl: `${checkoutBaseUrl}/success`,
      cancelUrl: `${checkoutBaseUrl}/cancel`,
      checkoutMode: 'full',
      items: (body.items ?? []).map((item: any) => ({
        providerItemId: item.providerItemId,
        providerItemName: item.name,
        quantity: item.quantity ?? 1,
        totalAmount: item.amount,
        overrideAmount: item.overrideAmount ?? null,
        currency: item.currency ?? 'USD',
      })),
      subscriptions: (body.subscriptions ?? []).map((sub: any) => ({
        providerPlanId: sub.providerPlanId,
        providerPlanName: sub.name,
        quantity: sub.quantity ?? 1,
        totalAmount: sub.amount,
        overrideAmount: sub.overrideAmount ?? null,
        currency: sub.currency ?? 'USD',
      })),
      accountData: {
        userId: body.account.userId,
        firstName: body.account.firstName ?? null,
        lastName: body.account.lastName ?? null,
        email: body.account.email,
        country: body.account.country ?? null,
        gender: null,
        city: null,
        state: null,
        zip: null,
      },
      couponCodes: [],
    };
 
    const response = await fetch(
      `${billingApiUrl.replace(/\/+$/, '')}/v1/checkouts/sessions`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      },
    );
 
    if (response.status === 201) {
      const data = await response.json();
      const uuid = data?.data?.uuid;
 
      return NextResponse.json({
        status: 201,
        sessionId: uuid,
        redirectUrl: `${checkoutBaseUrl}/checkout?id=${uuid}`,
      });
    }
 
    if (response.status === 204) {
      return NextResponse.json({
        status: 204,
        redirectUrl: `${checkoutBaseUrl}/success`,
      });
    }
 
    return NextResponse.json(
      { error: 'Billing API error', status: response.status },
      { status: 500 },
    );
  } catch (err) {
    return NextResponse.json(
      { error: err instanceof Error ? err.message : 'Unknown error' },
      { status: 500 },
    );
  }
}

Client-Side Alternative

The createCheckoutSession helper from @flopay/js handles the API call and browser redirect in one step. This is useful when you want to create sessions directly from the client.

create-session-client.ts
import { createCheckoutSession } from '@flopay/js';
 
await createCheckoutSession({
  billingApiUrl: 'https://billing.example.com',
  checkoutBaseUrl: 'https://checkout.example.com',
  clientId: 'client_123',
  items: [
    {
      providerItemId: 'prod_abc',
      providerItemName: 'Pro Plan',
      totalAmount: 49.99,
      overrideAmount: 24.99,
    },
  ],
  subscriptions: [
    {
      providerPlanId: 'plan_monthly',
      providerPlanName: 'Monthly Pro',
      totalAmount: 19.99,
    },
  ],
  account: {
    userId: 'user_1',
    email: 'user@example.com',
    firstName: 'Jane',
    lastName: 'Doe',
  },
  successUrl: '/success',
  cancelUrl: '/cancel',
  redirectParams: { email: 'user@example.com', mode: 'confirm' },
});

On a 201 response, createCheckoutSession automatically redirects the browser to the checkout page with the session UUID. On 204 (payment method already on file), it redirects to the successUrl.

For automatic retry on timeout errors, use createCheckoutSessionWithRetries:

import { createCheckoutSessionWithRetries } from '@flopay/js';
 
await createCheckoutSessionWithRetries({
  maxRetries: 3,
  // ...same options as createCheckoutSession
});

On this page