Designing a Production-Ready Stripe Connect Payment Flow for Marketplaces

Designing a Production-Ready Stripe Connect Payment Flow for Marketplaces

Written by
Written by

Santu R.

Post Date
Post Date

Jan 21, 2026

shares

Marketplaces don’t behave like normal e-commerce.

In a typical checkout, a customer pays, the seller ships, and the transaction is done. Simple, predictable, and easy to model.

Marketplaces are different. Vendors can accept or reject items. Orders may be partially fulfilled. Commissions depend on what actually ships, not what was originally ordered.

Yet many platforms still treat marketplace payments like standard checkouts.

That mistake usually shows up later as refunds, accounting drift, and operational headaches.

In this post, we’ll walk through a production-tested Stripe Connect payment architecture that aligns money movement with real business decisions — using authorization-based payments, delayed capture, and deterministic fee calculation.

The Marketplace Payment Reality

At a high level, our marketplace flow looked straightforward:

On paper, this is a textbook use case for Connect.

The complexity isn’t what happens — it’s when money should actually move.

In marketplaces, business decisions happen after checkout. Payments shouldn’t get ahead of those decisions.

The First Mistake: Capturing Too Early

Our initial implementation followed Stripe’s most common example:

PaymentIntent::create([ 'amount' => $amount, 'currency' => 'usd', 'confirm' => true, ]);

This pattern is well documented, quick to implement, and works perfectly for single-seller stores.

In a marketplace, it fails fast.

Why Immediate Capture Breaks Marketplaces

Capturing funds immediately created a cascade of problems:

None of this was a Stripe issue.

It was an architectural one.

Payment finality was happening before business logic was complete.

The Shift That Fixed Everything: Authorization First

The fix wasn’t complex — but it required changing how we thought about checkout.

Instead of capturing money immediately, we separated authorization from capture.

The PaymentIntent was created with manual capture enabled:

PaymentIntent::create([ 'amount' => $totalAmount * 100, 'currency' => 'usd', 'customer' => $user->stripe_customer_id, 'capture_method' => 'manual', 'transfer_data' => [ 'destination' => $connectedAccountId, ], 'automatic_payment_methods' => ['enabled' => true], ]);

From Stripe’s perspective, this means:

This single change unlocked the rest of the system.

Aligning Payment State with Business State

After checkout:

Principle: Payment state should never advance faster than business state.

What Happens When Vendors Decide

Item Acceptance

When a vendor accepts an item:

If other items are still pending, the system simply waits.

No partial captures. No recalculations. No side effects.

Item Rejection

When an item is rejected:

Accepted or rejected, the rule never changes:

Stripe is called exactly once, with final numbers.

Finalization: One Clean Payment Decision

Once all items reach a terminal state, the platform finalizes the payment.

Case 1: All Items Rejected

If nothing is accepted:

$paymentIntent->cancel();

Case 2: One or More Items Accepted

If some items are accepted:

$paymentIntent->capture([ 'amount_to_capture' => $acceptedAmount * 100, 'application_fee_amount' => $platformFeeInCents, ]);

This results in one clean, auditable Stripe transaction.

In production, this step also handles authorization expiry and retry logic — but the core model stays the same.

Why Platform Fees Must Be Applied at Capture Time

We learned quickly that fee timing matters.

Applying platform fees earlier caused:

Fees are a consequence of fulfillment, not intent.

By applying them at capture time:

Stripe handles the rest — transferring net funds to vendors and retaining the platform’s commission automatically.

No internal wallets. No manual transfers. No reconciliation surprises.

Why This Architecture Holds Up in Production

This model gives you:

Most importantly, customers are charged only for what vendors actually accept.

Closing Thoughts

Stripe Connect is powerful, but marketplace payments demand deliberate design.

Treating them like standard e-commerce leads to refunds, accounting drift, and operational risk. For platforms with vendor approvals, partial fulfillment, or commissions, authorization-first payments with delayed capture should be the default.

Align payment state with business reality — and everything downstream becomes simpler, safer, and easier to operate.