Implementation of Digital Goods Marketplace on Website
A digital goods marketplace is a platform where independent authors sell their products: templates, plugins, fonts, photos, videos, courses. The platform takes a commission, provides payment infrastructure and delivery.
Key System Participants
- Authors — upload products, set prices, receive payouts
- Buyers — pay, download, leave reviews
- Administration — moderates products, manages payouts
Content Moderation
class ProductModerationService
{
public function submit(Product $product): void
{
$product->update(['status' => 'under_review']);
// Automatic checks
$checks = [
'images_quality' => $this->checkImagesQuality($product),
'description_len' => strlen($product->description) >= 200,
'preview_exists' => $product->preview_files->isNotEmpty(),
'files_scan' => $this->scanFilesForMalware($product),
];
$autoApprove = !in_array(false, $checks);
if ($autoApprove) {
$product->update(['status' => 'active']);
} else {
// Manual review needed
ModerationTask::create([
'product_id' => $product->id,
'checks' => $checks,
'priority' => $this->calculatePriority($product),
]);
}
}
}
Author Payout Mechanism
class AuthorPayoutService
{
public function processPayout(int $authorId): PayoutResult
{
$author = User::findOrFail($authorId);
$balance = $author->payout_balance;
if ($balance < config('marketplace.min_payout')) {
return PayoutResult::belowMinimum($balance);
}
// Payout via Stripe Connect or bank transfer
if ($author->stripe_connect_id) {
$transfer = $this->stripe->transfers->create([
'amount' => (int)($balance * 100), // in cents
'currency' => 'rub',
'destination' => $author->stripe_connect_id,
'metadata' => ['author_id' => $authorId],
]);
$author->decrement('payout_balance', $balance);
Payout::create([
'author_id' => $authorId,
'amount' => $balance,
'stripe_id' => $transfer->id,
'status' => 'completed',
]);
return PayoutResult::success($balance);
}
return PayoutResult::noPaymentMethod();
}
}
Author Analytics
Route::get('/api/author/stats', function (Request $request) {
$author = auth()->user();
return response()->json([
'total_revenue' => Sale::where('author_id', $author->id)->sum('author_payout'),
'total_sales' => Sale::where('author_id', $author->id)->count(),
'this_month' => Sale::where('author_id', $author->id)
->whereMonth('created_at', now()->month)
->sum('author_payout'),
'top_products' => Sale::where('author_id', $author->id)
->groupBy('product_id')
->orderByRaw('COUNT(*) DESC')
->limit(5)
->with('product:id,name,thumbnail')
->selectRaw('product_id, COUNT(*) as sales_count, SUM(author_payout) as revenue')
->get(),
'pending_payout' => $author->payout_balance,
]);
})->middleware('auth');
Search and Filtering
// Elasticsearch or PostgreSQL full-text search
public function search(string $query, array $filters): LengthAwarePaginator
{
return Product::where('status', 'active')
->when($query, fn($q) => $q->whereFullText(['name', 'description'], $query))
->when($filters['category'] ?? null, fn($q, $cat) => $q->where('category_id', $cat))
->when($filters['price_max'] ?? null, fn($q, $max) => $q->where('price', '<=', $max))
->when($filters['sort'] ?? 'popular', function ($q, $sort) {
match($sort) {
'newest' => $q->latest(),
'popular' => $q->orderByDesc('sales_count'),
'rating' => $q->orderByDesc('rating_avg'),
'price_asc' => $q->orderBy('price'),
default => $q->latest(),
};
})
->paginate(24);
}
Timeline
Digital goods marketplace with moderation, payouts, and analytics: 25–35 business days.







