DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Stripe Connect: Building a Marketplace With Split Payments

Stripe Connect: Building a Marketplace With Split Payments

Marketplaces need to split payments between the platform and sellers. Stripe Connect handles the complex parts: onboarding sellers, splitting funds, handling payouts, and staying compliant.

Connect Account Types

Express — Stripe-hosted onboarding, Stripe handles KYC. Best for most marketplaces.

Standard — Sellers have full Stripe accounts. Platform gets limited control.

Custom — Full control, full liability. Complex, only for large platforms.

Onboarding a Seller

// Create a Connect account
const account = await stripe.accounts.create({
  type: 'express',
  country: 'US',
  email: seller.email,
  capabilities: {
    card_payments: { requested: true },
    transfers: { requested: true },
  },
});

// Save account ID to your database
await db.seller.update({
  where: { id: seller.id },
  data: { stripeAccountId: account.id },
});

// Create onboarding link
const accountLink = await stripe.accountLinks.create({
  account: account.id,
  refresh_url: `${BASE_URL}/sellers/onboarding/refresh`,
  return_url: `${BASE_URL}/sellers/onboarding/complete`,
  type: 'account_onboarding',
});

// Redirect seller to accountLink.url
Enter fullscreen mode Exit fullscreen mode

Checking Onboarding Status

async function isSellerReady(stripeAccountId: string): Promise<boolean> {
  const account = await stripe.accounts.retrieve(stripeAccountId);
  return account.details_submitted && account.charges_enabled;
}
Enter fullscreen mode Exit fullscreen mode

Taking a Payment With Platform Fee

// Checkout Session with application fee
const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  payment_method_types: ['card'],
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: { name: product.name },
      unit_amount: product.priceInCents,
    },
    quantity: 1,
  }],
  payment_intent_data: {
    application_fee_amount: Math.floor(product.priceInCents * 0.10), // 10% fee
    transfer_data: {
      destination: seller.stripeAccountId, // Seller gets the rest
    },
  },
  success_url: `${BASE_URL}/success`,
  cancel_url: `${BASE_URL}/cancel`,
});
Enter fullscreen mode Exit fullscreen mode

Manual Transfers

// Transfer funds to seller after your own processing
const transfer = await stripe.transfers.create({
  amount: sellerAmountInCents,
  currency: 'usd',
  destination: seller.stripeAccountId,
  transfer_group: `ORDER_${orderId}`,
});
Enter fullscreen mode Exit fullscreen mode

Webhook Events to Handle

switch (event.type) {
  case 'account.updated':
    // Check if seller completed onboarding
    const account = event.data.object;
    if (account.charges_enabled) await markSellerActive(account.id);
    break;

  case 'payment_intent.succeeded':
    await fulfillOrder(event.data.object.metadata.orderId);
    break;

  case 'transfer.created':
    await logSellerPayout(event.data.object);
    break;
}
Enter fullscreen mode Exit fullscreen mode

Dashboard Link for Sellers

// Let sellers view their Stripe dashboard
const loginLink = await stripe.accounts.createLoginLink(seller.stripeAccountId);
// Redirect to loginLink.url — expires in a few minutes
Enter fullscreen mode Exit fullscreen mode

Building payment infrastructure? The AI SaaS Starter Kit includes full Stripe Connect integration with seller onboarding flow, split payment checkout, and payout tracking. $99 at whoffagents.com.

Top comments (0)