Skip to main content

Payment Capabilities

Recurso integrates with payment gateways to handle:
  • Subscription payments
  • One-time charges
  • Payment retries (dunning)
  • Refunds

Supported Gateways

Payment Flow

Recurso generates the invoice; the customer pays it on Recurso’s hosted checkout page at {your-recurso-origin}/checkout/{invoice_id}. The checkout initiates a gateway order, drives the right client flow (Stripe Payment Element or Razorpay Checkout.js), and settlement is always verified server-side — the checkout confirms the payment with the gateway and binds it to the invoice before anything is marked paid. Gateway webhooks remain the authoritative backstop.

Configuration

Configure gateways in your environment:
.env
STRIPE_PUBLISHABLE_KEY (and RAZORPAY_KEY_ID for INR) are handed to the buyer’s browser by the hosted checkout. If the browser-side key is missing, checkout initiation fails loudly with a 503 instead of dead-ending the buyer.
See the Payment Gateways guide for detailed setup instructions.

Collect Payment

For Subscriptions

Creating a subscription generates its first invoice. Send the customer to the hosted checkout for that invoice — the gateway is chosen automatically by currency (INR → Razorpay, others → Stripe):
The checkout page handles everything from there: card + local methods via the Stripe Payment Element (with real failure states — a declined payment shows “Payment not completed” with retry, never a false success), or the Razorpay modal for INR (UPI, cards, netbanking).

One-Time Charges

There’s no standalone invoice-create API — one-off charges attach to a subscription and bill on its next invoice, or land immediately via an advance invoice:
See Advanced Billing for details.

Create Payment Order

The hosted checkout calls this for you; if you build a custom payment UI, create the gateway order directly. It is a public, rate-limited endpoint (no API key — it powers buyer-facing pages) that takes only the invoice id and picks the gateway by the invoice’s currency:
For most integrations use the checkout wrapper instead — POST /checkout/{id}/pay returns everything the browser flow needs (gateway, Stripe client_secret + publishable_key, or razorpay_key_id). Settle only via the verify endpoints (success / razorpay/verify); never mark invoices paid from the client.

Payment Methods

The payment instrument lives at the gateway, attached during checkout (Stripe SetupIntent / Razorpay token or UPI mandate) or through the customer portal. Renewals then charge it automatically. On the Recurso side you can update the card-on-file display metadata shown in the dashboard and dunning emails:
When a card expires, send the customer a magic link — the portal walks them through a fresh SetupIntent or mandate.

Record Offline Payment

Record payments received outside of Recurso — bank transfers, cash, cheques — optionally against an invoice, with TDS handled first-class:
string
required
bank_transfer, cash, or cheque.
integer
required
Cash actually received, in minor units.
integer
Tax deducted at source by the customer (Indian B2B). Posts to the TDS Receivable account — amount + tds_amount settles the invoice.
string
Bank/UTR/cheque reference for reconciliation.

List Offline Payments

Retrieve all offline payments recorded for an invoice or customer:

Virtual Accounts for Bank Transfers

For customers who prefer to pay via bank transfer, create a virtual account that auto-reconciles incoming payments:
When the customer transfers to this account, Recurso automatically matches the payment to the correct invoice. See the Virtual Accounts guide for setup.

Retrying Failed Payments

When payments fail, Recurso automatically:
  1. Sends payment failure notification
  2. Schedules retry based on dunning config
  3. Escalates with reminder emails
  4. Suspends subscription after max retries
For intelligent retry timing based on payment success patterns, see the Smart Retry guide. For configuring email sequences during payment recovery, see the Dunning Campaigns guide.

Refunds

Refunds are issued as credit notes of type refund — this calls the real Stripe/Razorpay refund API and posts a Refunds-vs-Cash ledger reversal:
The gateway refund settles asynchronously; the credit note tracks its refund_status (pendingprocessed, or failed / manual_required).

Webhooks

Next steps

Dunning & recovery

When a payment fails

The Ledger

Where every payment posts