How to Build a Custom Vendor Marketplace Module in Magento 2

Understanding Vendor Marketplaces in Magento 2
Building a custom vendor marketplace in Magento 2 allows multiple sellers to list and sell products through your store. Think of it like an eCommerce version of Amazon or Etsy, where you act as the platform owner while vendors handle their own inventory, pricing, and orders.
While there are pre-built extensions available (including some great ones on magefine.com), sometimes you need a custom solution tailored to your specific business requirements. Let's walk through how to build one from scratch.
Core Components of a Vendor Marketplace
Before diving into code, let's outline the key components we'll need to build:
- Vendor Management: Registration, profiles, and approval system
- Product Management: Allow vendors to add/edit their products
- Order Management: Split orders by vendor and handle commissions
- Payment System: Handle payouts to vendors
- Admin Controls: Oversight and moderation tools
Setting Up the Module Structure
First, create the basic module structure in your Magento 2 installation:
app/code/Magefine/VendorMarketplace/
├── etc/
│ ├── module.xml
│ ├── db_schema.xml
│ └── adminhtml/
│ └── system.xml
├── registration.php
└── Setup/
└── InstallSchema.php
Let's start with the registration.php
file:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Magefine_VendorMarketplace',
__DIR__
);
Creating the Vendor Entity
We need a database table to store vendor information. Here's how to set it up in db_schema.xml
:
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="magefine_vendor_marketplace" resource="default" engine="innodb" comment="Vendor Marketplace Table">
<column xsi:type="int" name="vendor_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Vendor ID"/>
<column xsi:type="varchar" name="name" nullable="false" length="255" comment="Vendor Name"/>
<column xsi:type="varchar" name="email" nullable="false" length="255" comment="Vendor Email"/>
<column xsi:type="varchar" name="status" nullable="false" length="20" comment="Vendor Status"/>
<column xsi:type="datetime" name="created_at" nullable="false" comment="Creation Time"/>
<column xsi:type="datetime" name="updated_at" nullable="false" comment="Update Time"/>
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="vendor_id"/>
</constraint>
</table>
</schema>
Building the Vendor Registration Form
Create a registration form that potential vendors can use to apply. Here's a basic layout XML example:
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">magefine_vendor_marketplace_form.magefine_vendor_marketplace_form_data_source</item>
</item>
<item name="label" xsi:type="string" translate="true">Vendor Application</item>
<item name="template" xsi:type="string">templates/form/collapsible</item>
</argument>
<fieldset name="vendor_information">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Vendor Information</item>
</item>
</argument>
<field name="name">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">Business Name</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
</argument>
</field>
<!-- Additional fields would go here -->
</fieldset>
</form>
Implementing Vendor Product Management
Vendors need to be able to manage their products. We'll extend the Magento product grid to include vendor filtering:
<?php
namespace Magefine\VendorMarketplace\Ui\DataProvider\Product;
use Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider as MagentoProductDataProvider;
class ProductDataProvider extends MagentoProductDataProvider
{
public function getData()
{
$data = parent::getData();
// Filter products by current vendor
if ($this->isVendorLoggedIn()) {
$vendorId = $this->getCurrentVendorId();
foreach ($data['items'] as $key => $item) {
if ($item['vendor_id'] != $vendorId) {
unset($data['items'][$key]);
}
}
$data['totalRecords'] = count($data['items']);
}
return $data;
}
}
Handling Orders and Commissions
When an order contains products from multiple vendors, we need to split it and calculate commissions. Here's a basic observer for order placement:
<?php
namespace Magefine\VendorMarketplace\Observer;
use Magento\Framework\Event\ObserverInterface;
class ProcessOrder implements ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer)
{
$order = $observer->getEvent()->getOrder();
$items = $order->getAllItems();
$vendorOrders = [];
// Group items by vendor
foreach ($items as $item) {
$product = $item->getProduct();
$vendorId = $product->getVendorId();
if (!isset($vendorOrders[$vendorId])) {
$vendorOrders[$vendorId] = [
'items' => [],
'total' => 0
];
}
$vendorOrders[$vendorId]['items'][] = $item;
$vendorOrders[$vendorId]['total'] += $item->getRowTotal();
}
// Process each vendor's portion
foreach ($vendorOrders as $vendorId => $vendorOrder) {
$this->createVendorOrder($order, $vendorId, $vendorOrder);
}
}
protected function createVendorOrder($mainOrder, $vendorId, $vendorOrder)
{
// Calculate commission (example: 10%)
$commission = $vendorOrder['total'] * 0.10;
$payout = $vendorOrder['total'] - $commission;
// Save vendor order record
// This would typically go to a separate vendor_orders table
}
}
Creating the Vendor Dashboard
Vendors need a dashboard to manage their store. Here's how to set up a basic controller:
<?php
namespace Magefine\VendorMarketplace\Controller\Dashboard;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
class Index extends Action
{
protected $resultPageFactory;
public function __construct(
Context $context,
PageFactory $resultPageFactory
) {
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
public function execute()
{
// Check if vendor is logged in
if (!$this->isVendorLoggedIn()) {
return $this->_redirect('vendor/account/login');
}
$resultPage = $this->resultPageFactory->create();
$resultPage->getConfig()->getTitle()->set(__('Vendor Dashboard'));
return $resultPage;
}
}
Payment Processing for Vendors
Implementing a payout system is crucial. Here's a simplified version of how to handle payouts:
<?php
namespace Magefine\VendorMarketplace\Model;
class Payout
{
public function processPayouts()
{
// Get all vendors with pending balances
$vendors = $this->getVendorsWithPendingPayouts();
foreach ($vendors as $vendor) {
try {
// Process payment via PayPal, Stripe, etc.
$this->processPayment(
$vendor->getPayoutEmail(),
$vendor->getPendingBalance(),
$vendor->getCurrency()
);
// Update vendor balance
$this->updateVendorBalance($vendor->getId(), 0);
// Record transaction
$this->recordTransaction(
$vendor->getId(),
$vendor->getPendingBalance(),
'completed'
);
} catch (\Exception $e) {
$this->recordTransaction(
$vendor->getId(),
$vendor->getPendingBalance(),
'failed',
$e->getMessage()
);
}
}
}
}
Admin Interface for Marketplace Management
As the marketplace owner, you'll need an admin interface to manage vendors. Here's a basic grid component:
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">magefine_vendor_marketplace_listing.magefine_vendor_marketplace_listing_data_source</item>
</item>
</argument>
<columns name="vendor_columns">
<column name="vendor_id">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">ID</item>
</item>
</argument>
</column>
<column name="name">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">Name</item>
</item>
</argument>
</column>
<!-- Additional columns would go here -->
</columns>
</listing>
Testing and Deployment
Before deploying your custom marketplace module:
- Test all vendor flows (registration, product management, order viewing)
- Verify commission calculations with different product types
- Test the admin interface for vendor management
- Ensure payment processing works correctly
- Check performance with multiple vendors and products
Once testing is complete, you can deploy your module to production. Remember to:
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush
Final Thoughts
Building a custom vendor marketplace in Magento 2 requires careful planning and implementation. While this guide covers the basics, a production-ready marketplace would need additional features like:
- Advanced vendor verification
- Shipping management per vendor
- Vendor rating system
- More sophisticated commission structures
- Detailed reporting for vendors
If you're looking for a ready-made solution, check out the marketplace extensions available on magefine.com that can save you development time while providing robust functionality.
Remember that maintaining a multi-vendor marketplace requires ongoing technical support, so consider our Magento hosting solutions that are optimized for marketplace performance.