Implementing Dropshipping on a Website
From a technical perspective, dropshipping is an abstraction layer between buyer and supplier. The store holds only product data and orders, with no physical inventory. Implementation requires three interconnected subsystems: catalog import and synchronization, order transmission to the supplier, and shipment tracking. None of them can be deferred — without stock synchronization, the store accepts orders for products the supplier doesn't have.
System Architecture
┌─────────────────────────────────────────────────────────┐
│ E-Commerce Store │
│ │
│ Product Catalog Cart/Checkout User Account │
│ │ │ │ │
│ └──────────────────┼───────────────────┘ │
│ │ │
│ ┌────────────▼─────────────┐ │
│ │ Dropshipping Kernel │ │
│ │ - Supplier Router │ │
│ │ - Stock Aggregator │ │
│ │ - Price Calculator │ │
│ │ - Order Dispatcher │ │
│ └────────────┬─────────────┘ │
└───────────────────────────┼─────────────────────────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Supplier 1 │ │ Supplier 2 │ │ Supplier N │
│ REST API │ │ FTP + CSV │ │ SOAP/XML │
└─────────────┘ └─────────────┘ └─────────────┘
Data Models
// Supplier
Schema::create('dropship_suppliers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->enum('integration_type', ['api', 'csv', 'xml', 'soap']);
$table->jsonb('credentials')->nullable(); // encrypted via $casts + Crypt
$table->string('api_endpoint')->nullable();
$table->integer('processing_days')->default(1); // order assembly time
$table->decimal('default_margin', 5, 2)->default(30.00); // % margin
$table->boolean('is_active')->default(true);
$table->timestamps();
});
// Supplier Product (source data)
Schema::create('dropship_products', function (Blueprint $table) {
$table->id();
$table->foreignId('supplier_id')->constrained('dropship_suppliers');
$table->string('supplier_sku'); // supplier's SKU
$table->string('name');
$table->text('description')->nullable();
$table->decimal('supplier_price', 10, 2);
$table->integer('supplier_stock')->default(0);
$table->jsonb('attributes')->nullable();
$table->string('image_url')->nullable();
$table->foreignId('product_id')->nullable()->constrained('products'); // link to store product
$table->timestamp('synced_at')->nullable();
$table->timestamps();
$table->unique(['supplier_id', 'supplier_sku']);
});
Dropshipping Kernel
class DropshippingKernel
{
public function __construct(
private SupplierRepositoryInterface $suppliers,
private PriceCalculator $priceCalculator,
private OrderDispatcher $orderDispatcher,
) {}
/**
* Get final product price including supplier margin
*/
public function calculateRetailPrice(DropshipProduct $dp): float
{
$supplier = $dp->supplier;
$margin = $dp->margin_override ?? $supplier->default_margin;
return $this->priceCalculator->calculate(
supplierPrice: $dp->supplier_price,
marginPercent: $margin,
);
}
/**
* Check product availability with supplier in real-time
*/
public function checkAvailability(DropshipProduct $dp): StockResult
{
$connector = SupplierConnectorFactory::make($dp->supplier);
return $connector->checkStock($dp->supplier_sku);
}
/**
* Send order to supplier after payment confirmation
*/
public function dispatchOrder(Order $order): void
{
// Group items by supplier
$bySupplier = $order->items->groupBy(
fn($item) => $item->product->dropshipProduct?->supplier_id
);
foreach ($bySupplier as $supplierId => $items) {
if (!$supplierId) continue; // own products — skip
$this->orderDispatcher->dispatch(
supplier: Supplier::find($supplierId),
order: $order,
items: $items,
);
}
}
}
Supplier Connectors
Each supplier requires its own connector. Basic interface:
interface SupplierConnectorInterface
{
public function getProducts(int $page = 1, int $perPage = 100): array;
public function checkStock(string $sku): StockResult;
public function placeOrder(SupplierOrderDTO $dto): SupplierOrderResult;
public function getOrderStatus(string $supplierOrderId): OrderStatusResult;
}
Implementation for supplier with REST API:
class RestApiSupplierConnector implements SupplierConnectorInterface
{
public function __construct(
private readonly Supplier $supplier,
private readonly \GuzzleHttp\Client $http,
) {}
public function placeOrder(SupplierOrderDTO $dto): SupplierOrderResult
{
// REST API implementation
}
}
Implementation Timeline
- Data models + dropshipping kernel basics: 2–3 days
- One supplier connector (REST API): 1–2 days
- Catalog sync + real-time stock: 1–2 days
- Order dispatch system + supplier notifications: 2–3 days
- Shipment tracking + customer notifications: 1 day
- Admin interface for margin management: 1 day
Total: 8–12 working days for full dropshipping system.







