Learn how to onboard sellers to your platform using Stripe Connect Express with this step-by-step tutorial covering setup, onboarding, payments, and compliance.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
How to Onboard Sellers with Stripe Connect: A Comprehensive Tutorial
Introduction
Stripe Connect is a powerful platform that allows you to build a marketplace, SaaS platform, or crowdfunding site where you can facilitate payments between customers and service providers or sellers. This tutorial will guide you through the process of onboarding sellers to your platform using Stripe Connect.
Step 1: Set Up Your Stripe Account
Before you can onboard sellers, you need to have a Stripe account set up as a platform.
Step 2: Choose the Right Connect Account Type
Stripe Connect offers three types of accounts:
For this tutorial, we'll focus on Express accounts as they offer a good balance between simplicity and customization.
Step 3: Install the Stripe Library
You'll need to install the Stripe library in your application. Here's how to do it in different environments:
For Node.js:
npm install stripe
For PHP:
composer require stripe/stripe-php
For Python:
pip install stripe
For Ruby:
gem install stripe
Step 4: Initialize the Stripe Client
In your application code, initialize the Stripe client with your secret key:
Node.js:
const stripe = require('stripe')('sk_test_YOUR_SECRET_KEY');
PHP:
\Stripe\Stripe::setApiKey('sk_test_YOUR_SECRET_KEY');
Python:
import stripe
stripe.api_key = 'sk_test_YOUR_SECRET\_KEY'
Ruby:
require 'stripe'
Stripe.api_key = 'sk_test_YOUR_SECRET\_KEY'
Step 5: Create an Express Account Link
To start the onboarding process, you first need to create a Connect account for your seller, then generate an account link that directs them to the Stripe-hosted onboarding flow:
Node.js:
async function createSellerAccount(sellerId) {
// First, create a Connect Express account
const account = await stripe.accounts.create({
type: 'express',
metadata: {
seller\_id: sellerId
}
});
// Store the account ID in your database
// saveAccountIdToDatabase(sellerId, account.id);
// Then, create an account link for onboarding
const accountLink = await stripe.accountLinks.create({
account: account.id,
refresh\_url: 'https://yourdomain.com/onboarding/refresh',
return\_url: 'https://yourdomain.com/onboarding/complete',
type: 'account\_onboarding'
});
// Return the URL to redirect your seller to
return accountLink.url;
}
PHP:
function createSellerAccount($sellerId) {
// First, create a Connect Express account
$account = \Stripe\Account::create([
'type' => 'express',
'metadata' => [
'seller\_id' => $sellerId
]
]);
// Store the account ID in your database
// saveAccountIdToDatabase($sellerId, $account->id);
// Then, create an account link for onboarding
$accountLink = \Stripe\AccountLink::create([
'account' => $account->id,
'refresh\_url' => 'https://yourdomain.com/onboarding/refresh',
'return\_url' => 'https://yourdomain.com/onboarding/complete',
'type' => 'account\_onboarding'
]);
// Return the URL to redirect your seller to
return $accountLink->url;
}
Step 6: Redirect the Seller to the Onboarding URL
Now that you have generated the account link URL, redirect the seller to this URL to complete the Stripe onboarding process. Here's how you might do this in a web application:
Node.js (Express.js):
app.get('/onboard-seller/:id', async (req, res) => {
const sellerId = req.params.id;
try {
const onboardingUrl = await createSellerAccount(sellerId);
res.redirect(onboardingUrl);
} catch (error) {
console.error('Error creating onboarding link:', error);
res.status(500).send('Unable to create onboarding link');
}
});
PHP:
// Assuming you have a route that handles /onboard-seller/{id}
$sellerId = $\_GET['id'];
try {
$onboardingUrl = createSellerAccount($sellerId);
header("Location: $onboardingUrl");
exit();
} catch (Exception $e) {
echo 'Error creating onboarding link: ' . $e->getMessage();
}
Step 7: Handle the Return from Stripe
After the seller completes (or abandons) the Stripe onboarding process, they'll be redirected to your return_url
or refresh_url
. Set up handlers for these routes:
Node.js (Express.js):
// Handle successful completion of onboarding
app.get('/onboarding/complete', async (req, res) => {
const sellerId = req.query.seller\_id;
// Retrieve the account ID from your database based on seller\_id
// const accountId = getAccountIdFromDatabase(sellerId);
// Check if the account is fully onboarded
try {
const account = await stripe.accounts.retrieve(accountId);
if (account.details\_submitted) {
// Seller has completed onboarding
// Update your database to mark the seller as active
res.send('Congratulations! Your account has been set up successfully.');
} else {
// Seller didn't complete all steps
res.send('Your account setup is not complete. Please finish all steps.');
}
} catch (error) {
console.error('Error checking account status:', error);
res.status(500).send('Error checking account status');
}
});
// Handle the need to refresh the onboarding link
app.get('/onboarding/refresh', async (req, res) => {
const sellerId = req.query.seller\_id;
// Retrieve the account ID from your database
// const accountId = getAccountIdFromDatabase(sellerId);
try {
// Create a new account link for the same account
const accountLink = await stripe.accountLinks.create({
account: accountId,
refresh\_url: 'https://yourdomain.com/onboarding/refresh',
return\_url: 'https://yourdomain.com/onboarding/complete',
type: 'account\_onboarding'
});
// Redirect to the new link
res.redirect(accountLink.url);
} catch (error) {
console.error('Error refreshing onboarding link:', error);
res.status(500).send('Error refreshing onboarding link');
}
});
Step 8: Set Up Webhook Events
Stripe sends webhook events for important account updates. Set up a webhook endpoint to listen for these events:
// Node.js (Express.js) example
const bodyParser = require('body-parser');
app.post('/webhook', bodyParser.raw({type: 'application/json'}), async (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
sig,
'whsec_your_webhook\_secret'
);
} catch (err) {
console.error(`Webhook Error: ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle specific events
switch (event.type) {
case 'account.updated':
const account = event.data.object;
console.log(`Account ${account.id} was updated`);
// If the account is now fully onboarded, update your database
if (account.details_submitted && account.charges_enabled) {
// updateSellerStatus(account.id, 'active');
console.log(`Seller with account ${account.id} is now active`);
}
break;
case 'account.application.deauthorized':
// The seller has disconnected their account
const accountId = event.data.object.id;
// updateSellerStatus(accountId, 'disconnected');
console.log(`Seller with account ${accountId} has disconnected`);
break;
}
res.json({received: true});
});
Step 9: Create a Dashboard Link for Sellers
After a seller has been onboarded, they may need to access their Stripe Express dashboard to view payouts, update information, etc. Generate a dashboard link:
async function createDashboardLink(accountId) {
const loginLink = await stripe.accounts.createLoginLink(accountId);
return loginLink.url;
}
Implement this in an endpoint:
app.get('/seller/dashboard/:id', async (req, res) => {
// Get the seller's account ID from your database
// const accountId = getAccountIdFromDatabase(req.params.id);
try {
const dashboardUrl = await createDashboardLink(accountId);
res.redirect(dashboardUrl);
} catch (error) {
console.error('Error creating dashboard link:', error);
res.status(500).send('Unable to access dashboard');
}
});
Step 10: Process Payments and Handle Transfers
Once sellers are onboarded, you can process payments on their behalf and automatically transfer funds. Here's a basic example:
async function createPaymentWithTransfer(amount, currency, customerId, sellerAccountId, applicationFeeAmount) {
try {
const paymentIntent = await stripe.paymentIntents.create({
amount: amount,
currency: currency,
customer: customerId,
payment_method_types: ['card'],
application_fee_amount: applicationFeeAmount,
transfer\_data: {
destination: sellerAccountId,
},
});
return paymentIntent;
} catch (error) {
console.error('Error creating payment with transfer:', error);
throw error;
}
}
This function:
Step 11: Monitor Account Status and Compliance
It's important to regularly check the status of your connected accounts to ensure they remain in good standing:
async function checkAccountStatus(accountId) {
try {
const account = await stripe.accounts.retrieve(accountId);
// Check if the account is fully onboarded and can process payments
const isActive = account.details_submitted && account.charges_enabled;
// Check if there are any requirements that need attention
const requiresAttention = account.requirements.currently\_due.length > 0;
return {
isActive,
requiresAttention,
requirements: account.requirements
};
} catch (error) {
console.error(`Error checking account ${accountId} status:`, error);
throw error;
}
}
You can schedule this to run periodically or in response to webhook events.
Step 12: Implement Account Updates
Sometimes sellers need to update their information. You can create a new account link specifically for updates:
async function createAccountUpdateLink(accountId) {
const accountLink = await stripe.accountLinks.create({
account: accountId,
refresh\_url: 'https://yourdomain.com/account/refresh',
return\_url: 'https://yourdomain.com/account/updated',
type: 'account\_update'
});
return accountLink.url;
}
Conclusion
You've now set up a complete flow for onboarding sellers with Stripe Connect Express accounts. This implementation provides:
Remember that this tutorial covers the Express account type, which is ideal for most marketplaces. If you need more control over the user experience, you might consider Custom accounts, though they require more development and compliance work.
For production use, make sure to implement proper error handling, data validation, and security measures throughout your application.
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.