FloPayFloPay
Getting started

Node.js Quick Start

Add the optional Node backend pieces for an embedded FloPayCheckout integration.

Node.js Quick Start

For the recommended embedded flow, the browser creates the checkout session inline through FloPayCheckout createSession. You do not need a Node endpoint just to create a session ahead of time.

Use @flopay/node when you need server-side responsibilities such as:

  • Verifying Flo webhook deliveries
  • Fulfilling orders or activating subscriptions after payment
  • Managing customers
  • Supporting an older hosted/session-ID-based flow

If you're following the React Quick Start, webhook verification is usually the first backend step to add. Session creation can stay on the client.

1. Configure Secrets

.env
STRIPE_SECRET_KEY=sk_test_...
FLO_WEBHOOK_SECRET=flo_whsec_...

2. Initialize the SDK

import { FloPay } from '@flopay/node';
 
export const flopay = new FloPay(process.env.STRIPE_SECRET_KEY!);

3. Verify Webhooks

// app/api/webhooks/route.ts
import { FloPay } from '@flopay/node';
import { NextResponse } from 'next/server';
 
const flopay = new FloPay(process.env.STRIPE_SECRET_KEY!);
const webhookSecret = process.env.FLO_WEBHOOK_SECRET!;
 
export async function POST(request: Request) {
  const body = await request.text();
  const signature = request.headers.get('flo-signature');
 
  if (!signature) {
    return NextResponse.json({ error: 'Missing Flo signature' }, { status: 400 });
  }
 
  let event;
  try {
    event = flopay.webhooks.constructEvent(body, signature, webhookSecret);
  } catch (error) {
    console.error('Invalid webhook signature', error);
    return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });
  }
 
  switch (event.type) {
    case 'checkout.session.completed':
      // Mark the order as paid / grant access
      break;
    case 'payment_intent.payment_failed':
      // Log or notify
      break;
    default:
      console.log('Unhandled event type:', event.type);
  }
 
  return NextResponse.json({ received: true });
}

Read the webhook request body as raw text (request.text()), not parsed JSON. Signature verification requires the original bytes.

4. How It Fits the Embedded Flow

  1. Your React app renders FloPayCheckout with createSession
  2. The component creates the billing session directly and renders the embedded payment form
  3. The customer completes payment on the page
  4. Flo sends a webhook to your Node endpoint
  5. Your server fulfills the order and records the final payment state

5. Need Server-Created Sessions?

If you still want a pre-created session or hosted redirect flow, @flopay/node still supports it:

const result = await flopay.checkout.sessions.create({
  billingApiUrl: 'https://api.stage.flopay.com',
  checkoutBaseUrl: 'https://checkout.example.com',
  clientId: 'client_123',
  items: [
    {
      providerItemId: 'prod_abc',
      providerItemName: 'Pro Plan',
      totalAmount: 49.99,
      currency: 'USD',
    },
  ],
  account: {
    userId: 'user_1',
    email: 'user@example.com',
  },
  successUrl: 'https://example.com/success',
  cancelUrl: 'https://example.com/cancel',
});

That flow still works, but it is no longer the main quick-start path for embedded checkout.

Next Steps

On this page