Custom SaaS Billing | Implementing Complex Payment Logic with Stripe

Custom SaaS billing integration involves connecting a payment gateway like Stripe, Paddle, or Braintree to an application's core logic to handle complex revenue models. Unlike standard e-commerce, B2B SaaS requires handling seat-based pricing, usage metering, and multi-year contract ramps. A robust integration ensures data consistency between the billing provider and the internal database.
Why Is Custom SaaS Billing Integration Necessary for B2B?
Standard checkout pages work for simple monthly subscriptions, but B2B SaaS often demands more flexibility. Enterprise clients frequently request custom contracts that include multi-year ramps, tiered discounts, and specific billing cycles that do not fit into a "one size fits all" template. Modern billing platforms are now expected to handle quote-to-cash workflows, including custom contracts and Docusign integrations.
When a startup moves beyond the initial MVP development phase, the billing logic often becomes the most complex part of the codebase. You are no longer just charging a credit card; you are managing state. If a user adds five seats mid-month, the system must calculate the prorated amount, update the subscription in the gateway, and reflect those changes in the application UI immediately. This level of synchronization requires a custom integration rather than a third-party plugin.
How Do You Architect a Scalable Billing System?
The most common mistake in SaaS development is treating the payment gateway as the "source of truth" for user permissions. If the gateway's API goes down or a webhook is delayed, your users might lose access to their accounts.
A production-ready architecture uses a dual-sync pattern:
- Internal Database: Stores the entitlement state (e.g.,
plan_type,seats_allowed,status). - Billing Gateway: Stores the financial state (e.g.,
stripe_customer_id,subscription_id,payment_method).
By keeping these separate, your application remains functional even if the billing provider experiences latency. You should use a robust database like PostgreSQL to manage these relationships, ensuring that every billing event is logged and traceable.
Should You Use Stripe, Paddle, or Braintree?
Choosing a provider depends on your operational capacity and geographic target.
Stripe: The Developer's Choice
Stripe is the industry standard for API development due to its extensive documentation and granular control. It allows for complex usage-based billing models where you report metered usage in real-time. However, you are responsible for sales tax compliance unless you use Stripe Tax, and even then, you remain the Merchant of Record.
Paddle: The Merchant of Record
Paddle acts as the Merchant of Record, meaning they handle global sales tax, localized payment methods, and compliance on your behalf. This is highly beneficial for small teams who do not want to deal with the administrative overhead of international tax filings.
Braintree: The Enterprise Alternative
Braintree, owned by PayPal, is often preferred by larger enterprises that need deep integration with PayPal's ecosystem or specific merchant account requirements. It offers competitive pricing for high-volume businesses but generally requires more manual configuration than Stripe.
How Do You Handle Metered and Usage-Based Billing?
Usage-based billing is becoming the default for infrastructure and AI-driven tools. Instead of a flat fee, you charge based on units consumed, such as API calls or gigabytes of storage. Implementing this requires high-fidelity metering to prevent revenue leakage.
To implement this in Stripe, you create a Metered price. Your application must then send usage records to Stripe periodically:
// Example: Reporting usage to Stripe in Node.js
const stripe = require('stripe')('sk_test_...');
await stripe.subscriptionItems.createUsageRecord(
'si_12345',
{
quantity: 500,
timestamp: Math.floor(Date.now() / 1000),
action: 'set',
}
);
This pattern requires a reliable background worker. If your application fails to report usage, you lose money. This is why cloud architecture is critical; you need a queue system (like RabbitMQ or AWS SQS) to ensure that every usage event is eventually recorded in the billing system.
What Are the Best Practices for Webhook Security?
Webhooks are the primary way billing gateways communicate with your app (e.g., payment succeeded, subscription canceled). Because these endpoints are public, they are targets for attacks.
- Signature Verification: Always verify the webhook signature using your provider's SDK. This ensures the request actually came from Stripe or Paddle.
- Idempotency: Ensure your webhook handler is idempotent. Billing providers may send the same event twice. Your code should check if the
event_idhas already been processed before updating the database. - Event Sourcing: Store the raw JSON of every webhook received. If a bug occurs, you can replay the events to restore your database to the correct state.
For companies focusing on security and compliance, these steps are non-negotiable. A single missed subscription deleted event could result in a user receiving services for free indefinitely.
How Do You Manage Subscription Transitions and Proration?
B2B users rarely stay on the same plan forever. They upgrade, downgrade, or add seats. Handling these transitions manually is a recipe for errors.
When a user changes their plan, you must decide how to handle the remaining balance of the current cycle. Stripe handles proration automatically by default, but you must reflect this in your UI so the user isn't surprised by a proration credit or an immediate charge.
// Previewing a proration before applying it
const invoice = await stripe.invoices.retrieveUpcoming({
customer: 'cus_123',
subscription: 'sub_456',
subscription_items: [{
id: 'si_789',
price: 'price_new_plan',
}],
});
Showing the invoice.amount_due to the user before they click Confirm Upgrade reduces support tickets and improves the user experience.
Why Is Revenue Recognition a Technical Challenge?
As a SaaS scales, the finance team will require Revenue Recognition reports. If a customer pays for an annual plan upfront, the accounting team must recognize that revenue incrementally over the service period rather than all at once.
While platforms like Stripe provide revenue recognition tools, the data is only as good as the integration. If your custom software doesn't correctly pass metadata (like service start and end dates), the financial reports will be inaccurate. This is why we emphasize database design patterns that track the lifecycle of a contract, not just the current status.
How Does Kraftwire Software Handle Billing Integrations?
At Kraftwire Software, we treat billing as a core architectural pillar rather than an afterthought. Whether we are building a six-week MVP or a complex enterprise platform, we implement a robust sync layer between your application and the payment gateway.
Our approach focuses on: · Reliability: Using queue-based webhook processing to ensure no payment event is missed. · Flexibility: Designing schemas that support seat-based, tiered, and metered billing from day one. · Security: Implementing strict signature verification and row-level security to protect financial data.
We help startups across the UK, USA, and Europe move from simple payment buttons to sophisticated, automated billing engines that scale with their growth.
FAQ
What is the difference between a payment gateway and a merchant of record? A payment gateway like Stripe processes transactions but leaves the burden of sales tax compliance and local regulations to you. A Merchant of Record (MoR) like Paddle takes legal responsibility for the sale, handling global taxes and compliance on your behalf, which simplifies international scaling for smaller SaaS teams.
How do I handle failed payments in a custom SaaS integration? You should implement a dunning process. When a payment failed webhook is received, your system should mark the internal subscription status as past_due and trigger an automated email sequence. If payment isn't received after a set period, the system should automatically revoke access to the application features.
Can I switch from Stripe to Paddle later? Switching billing providers is a significant undertaking known as a billing migration. It requires migrating customer credit card data via secure vault-to-vault transfer and re-mapping all subscription logic. It is generally better to choose the provider that fits your long-term tax and operational strategy during the initial build.
How do I implement seat-based pricing? In seat-based pricing, you sync the number of active users in your database with the quantity field of the subscription item in your billing gateway. Every time a user is added or removed, an API call updates the quantity, and the gateway handles the proration for the remainder of the billing cycle.
Is it better to build a custom billing UI or use a hosted portal? Stripe and other providers offer Customer Portals that handle card updates and plan changes. For an MVP, using a hosted portal saves weeks of development. However, for a seamless brand experience or complex B2B workflows, building a custom UI allows for better control over the user journey and upsell opportunities.
How do I test billing integrations without spending real money? All major providers offer a Sandbox or Test Mode. You use test API keys and special test card numbers to simulate successful payments, declines, and 3D Secure authentication. You can also use tools like Stripe CLI to trigger mock webhooks and test how your application responds to various events.
FAQ
What is the difference between a payment gateway and a merchant of record?
A payment gateway like Stripe processes transactions but leaves the burden of sales tax compliance and local regulations to you. A Merchant of Record (MoR) like Paddle takes legal responsibility for the sale, handling global taxes and compliance on your behalf, which simplifies international scaling for smaller SaaS teams.
How do I handle failed payments in a custom SaaS integration?
You should implement a "dunning" process. When a payment failed webhook is received, your system should mark the internal subscription status as past_due and trigger an automated email sequence. If payment isn't received after a set period, the system should automatically revoke access to the application features.
Can I switch from Stripe to Paddle later?
Switching billing providers is a significant undertaking known as a billing migration. It requires migrating customer credit card data and re-mapping all subscription logic. It is generally better to choose the provider that fits your long-term tax and operational strategy during the initial build.
How do I implement seat-based pricing?
In seat-based pricing, you sync the number of active users in your database with the quantity field of the subscription item in your billing gateway. Every time a user is added or removed, an API call updates the quantity, and the gateway handles the proration for the remainder of the billing cycle.
Is it better to build a custom billing UI or use a hosted portal?
Stripe and other providers offer Customer Portals that handle card updates and plan changes. For an MVP, using a hosted portal saves weeks of development. However, for a seamless brand experience or complex B2B workflows, building a custom UI allows for better control over the user journey.
How do I test billing integrations without spending real money?
All major providers offer a Sandbox or Test Mode. You use test API keys and special test card numbers to simulate successful payments, declines, and 3D Secure authentication. You can also use tools like Stripe CLI to trigger mock webhooks and test how your application responds to various events.