بنقرة واحدة
marketplace-building
// Launch a multi-vendor marketplace with seller onboarding, commission rules, automated payouts via Stripe Connect, and vendor dashboards
// Launch a multi-vendor marketplace with seller onboarding, commission rules, automated payouts via Stripe Connect, and vendor dashboards
Manage supplier invoices and vendor payments with automated receipt matching, payment scheduling, early discount optimization, and reconciliation workflows
Enable wholesale and B2B sales with company accounts, custom catalogs, quote workflows, purchase orders, and net payment terms
Predict future inventory needs using historical sales data, seasonal trends, and reorder points to prevent stockouts and overstock
Control which products appear first in collections using automated ranking rules, manual overrides, and performance-based sorting algorithms
Sync your catalog and inventory across your own site, Amazon, eBay, and wholesale channels to sell everywhere from one system
Design an order management system that routes orders to the right warehouse, handles split shipments, and manages backorders gracefully
| name | marketplace-building |
| description | Launch a multi-vendor marketplace with seller onboarding, commission rules, automated payouts via Stripe Connect, and vendor dashboards |
| category | business-operations |
| risk | critical |
| source | curated |
| date_added | 2026-03-12 |
| tags | ["marketplace","multi-vendor","seller-onboarding","commissions","payouts","Stripe-Connect","platform"] |
| triggers | ["marketplace","multi-vendor marketplace","seller onboarding","marketplace commissions","seller payouts","platform marketplace"] |
| tools | ["claude-code","cursor","gemini-cli","copilot","codex-cli","kiro","opencode"] |
| platforms | ["shopify","woocommerce","bigcommerce","custom"] |
| difficulty | advanced |
A multi-vendor marketplace lets independent sellers list products on your platform, collects payment from buyers, deducts your commission, and pays out the remainder to sellers. The key components are: seller onboarding with KYC verification, product listing management per seller, commission calculation, and automated payouts. For Shopify and WooCommerce merchants, purpose-built marketplace apps handle most of this — custom development is needed primarily for highly specific commission structures or white-label marketplace platforms.
| Platform | Recommended Tool | Why |
|---|---|---|
| Shopify | Multi Vendor Marketplace by Webkul or BOLD Multi-Vendor | Webkul's app adds seller accounts, product management, commission rules, and a seller dashboard to Shopify without replacing the storefront |
| WooCommerce | Dokan Multi-Vendor (most popular, 60K+ installs) or WC Vendors | Dokan is purpose-built for WooCommerce marketplaces with seller onboarding, commission management, payout requests, and a seller dashboard |
| BigCommerce | Multi Vendor Marketplace by Webkul (BigCommerce version) | Webkul has a BigCommerce version of their marketplace app |
| Custom / Headless | Build seller accounts + Stripe Connect for KYC and payouts | Stripe Connect handles KYC, bank account collection, and 1099-K tax forms — use it for any custom marketplace |
KYC (Know Your Customer) is required to verify seller identity before you can legally send them payments. Using Stripe Connect for this is strongly recommended — building it yourself is expensive and legally complex.
yourstore.com/seller/register)import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
// Create a Stripe Express account for a new seller and return the onboarding URL
async function onboardSeller(sellerId: string, sellerEmail: string): Promise<string> {
// Create the Stripe Express account
const account = await stripe.accounts.create({
type: 'express',
email: sellerEmail,
capabilities: {
transfers: { requested: true },
},
});
// Store the Stripe account ID on the seller record
await db.sellers.update(sellerId, { stripe_account_id: account.id });
// Generate the onboarding link (valid for 24 hours)
const accountLink = await stripe.accountLinks.create({
account: account.id,
refresh_url: `${process.env.APP_URL}/seller/onboarding/refresh`,
return_url: `${process.env.APP_URL}/seller/onboarding/complete`,
type: 'account_onboarding',
});
return accountLink.url; // send this URL to the seller
}
// Webhook handler: activate seller when Stripe confirms KYC is complete
async function handleStripeAccountUpdated(account: Stripe.Account): Promise<void> {
const seller = await db.sellers.findByStripeAccountId(account.id);
if (!seller) return;
if (account.charges_enabled && account.payouts_enabled && seller.status !== 'active') {
await db.sellers.update(seller.id, { status: 'active' });
// Send welcome email to seller
}
}
yourstore.com/seller/dashboardyourstore.com/dashboard// Calculate commission and record seller earnings when an order is paid
async function recordSellerEarning(params: {
orderId: string;
sellerId: string;
grossAmountCents: number; // what buyer paid for this seller's items
commissionRate: number; // e.g., 0.15 for 15%
}): Promise<void> {
const commissionCents = Math.round(params.grossAmountCents * params.commissionRate);
const netAmountCents = params.grossAmountCents - commissionCents;
// Funds held until return window closes (e.g., 30 days)
const availableAt = new Date();
availableAt.setDate(availableAt.getDate() + 30);
await db.sellerEarnings.insert({
seller_id: params.sellerId,
order_id: params.orderId,
gross_amount_cents: params.grossAmountCents,
commission_cents: commissionCents,
net_amount_cents: netAmountCents,
status: 'held', // becomes 'available' after return window
available_at: availableAt,
});
}
// Transfer available earnings to seller's Stripe account
async function payoutSeller(sellerId: string): Promise<void> {
const seller = await db.sellers.findById(sellerId);
const availableEarnings = await db.sellerEarnings.findAll({
seller_id: sellerId,
status: 'available',
available_at: { lte: new Date() },
});
const totalCents = availableEarnings.reduce((s, e) => s + e.net_amount_cents, 0);
if (totalCents < 100) return; // minimum payout $1.00
// Transfer from your Stripe balance to seller's connected account
const transfer = await stripe.transfers.create({
amount: totalCents,
currency: 'usd',
destination: seller.stripe_account_id,
metadata: { seller_id: sellerId },
});
// Mark earnings as paid out
await db.sellerEarnings.updateMany(
availableEarnings.map(e => e.id),
{ status: 'paid_out' }
);
}
yourstore.com/seller/dashboard showing: orders, products, earnings summary, and payout historyyourstore.com/dashboard with: sales analytics, product management, withdrawal requests, and order managementcharges_enabled && payouts_enabled on the Stripe account before allowing a seller to publish listings| Problem | Solution |
|---|---|
| Payout fails but earnings marked as paid | In Stripe Connect, use the transfer.created webhook to confirm success before marking earnings as paid_out; never mark paid-out in the same call that initiates the transfer |
| Platform pays out before buyer payment clears | Only trigger payout eligibility from the payment_intent.succeeded webhook, not from checkout session creation |
| Seller lists products before KYC is verified | Check Stripe account status (charges_enabled && payouts_enabled) before allowing product publication; Webkul and Dokan do this automatically |
| Seller disputes commission deduction | Store the commission rate and gross amount on every seller_earning record; show sellers their commission calculation history in the seller dashboard |