Skip to main content
This guide covers the complete integration: backend session creation, frontend redirect, webhook handling, and going live. By the end, customers will be able to select a plan, pay, and get an active subscription without any manual step on your side.

Prerequisites

  • Payment provider connected to Flexprice: see Razorpay Setup
  • Required webhook events enabled on your provider dashboard
  • Flexprice webhook endpoint registered to receive checkout.session.* events
  • Customer record exists in Flexprice before the checkout starts
  • Plan has at least one non-zero charge

Architecture

Step 1: Create a customer

A customer must exist in Flexprice before a session can be created. Create one at sign-up:
Use the external_id as your reference in subsequent calls.

Step 2: Create a Checkout Session

Call this from your backend only: never expose your API key to the frontend.
Two things worth noting here:
  • {CHECKOUT_SESSION_ID} in success_url is a placeholder that Razorpay replaces on redirect. Use it to identify which session the customer just completed.
  • idempotency_key tied to your internal order ID means a retry on timeout gives you back the same session, not a duplicate.
Store the returned id (chk_...) in your database alongside the order.

Step 3: Redirect the customer

Return the payment_action.url from your backend to your frontend and redirect immediately:
Do a full-page redirect, not an iframe. The payment link expires after 15 minutes, so don’t add unnecessary steps before the redirect.

Step 4: Handle the webhook

Do not rely on the redirect URL to confirm payment: it can be bypassed. The checkout.session.completed webhook is the authoritative signal. Register your endpoint in Settings → Webhooks, then handle the events:
Make this handler idempotent: Flexprice delivers events at least once. Check whether you’ve already fulfilled the order before acting.

Step 5: Handle success and failure pages

Use the redirect URLs for UX only, not for fulfillment logic. Success page: poll the session to confirm before showing a result:
If checkout_status is completed, show the success state. If it’s still pending, the webhook hasn’t arrived yet: show a “processing” state and poll again in a few seconds. Failure or cancel page: The customer can start over. Create a new session. The previous session and everything it created are cleaned up automatically.

Step 6: Test the integration

Use your provider’s test credentials before switching to live keys. For Razorpay test cards and UPI IDs, see Razorpay Checkout Setup. After a test payment, verify:
  • Session checkout_status is completed
  • Subscription is active
  • Invoice is finalized
  • Your backend received checkout.session.completed
  • Fulfillment ran (access granted, emails sent, DB updated)

Error reference

Recurring payments

This guide uses the default one-time payment link: each invoice generates its own link. To charge future invoices automatically, collect a mandate at checkout instead. The customer authorizes once, and renewals — plus one-off and wallet top-up invoices — auto-charge with no further action. See Autopay & Mandates.

Go-live checklist

  • Switch provider connection from test keys to live keys
  • Confirm all required webhook events are enabled on the production URL (not test)
  • success_url, failure_url, cancel_url point to production domains
  • Webhook endpoint responds within 5 seconds and uses HTTPS
  • Fulfillment handler is idempotent

Razorpay Setup

Test credentials and webhook event configuration.

Checkout Sessions API

Full field reference for the create session call.