Build a farmers market platform by creating a Paystack Subaccount per farmer, using Paystack Multi-Split to route each order line item's revenue to the correct farmer's subaccount at checkout, and then coordinating pickup or delivery separately. For complex carts with multiple farmers, collect the full cart payment first and use Transfers to pay each farmer their portion after the webhook confirms.
Tables: farmers (name, phone, bank_code, account_number, paystack_subaccount_code), products (farmer_id, name, unit, price_per_unit, stock_qty), orders (customer_id, status, total, paystack_ref), order_items (order_id, product_id, farmer_id, qty, unit_price, subtotal).
async function checkout(customerEmail, customerId, cartItems) {
var total = cartItems.reduce(function(sum, item) { return sum + (item.qty * item.unit_price); }, 0);
var reference = 'FARM-' + Date.now();
// Group items by farmer for split calculation
var farmerTotals = {};
for (var item of cartItems) {
if (!farmerTotals[item.farmer_id]) farmerTotals[item.farmer_id] = 0;
farmerTotals[item.farmer_id] += item.qty * item.unit_price;
}
var order = await db.orders.create({
customer_id: customerId, status: 'pending', total, paystack_ref: reference,
});
for (var item of cartItems) {
await db.orderItems.create({ ...item, order_id: order.id });
}
var res = await fetch('https://api.paystack.co/transaction/initialize', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
email: customerEmail,
amount: total,
currency: 'NGN',
reference,
metadata: { order_id: order.id, customer_id: customerId, farmer_totals: farmerTotals },
}),
});
return (await res.json()).data.authorization_url;
}
// Webhook: confirm order and pay each farmer
if (event.event === 'charge.success') {
var meta = event.data.metadata;
if (!meta.order_id) return res.sendStatus(200);
await db.orders.update(meta.order_id, { status: 'confirmed' });
// Pay each farmer their share via Transfers
var farmerTotals = meta.farmer_totals;
for (var farmerId of Object.keys(farmerTotals)) {
var farmer = await db.farmers.findById(farmerId);
var platformFee = Math.floor(farmerTotals[farmerId] * 0.10); // 10% platform fee
var payout = farmerTotals[farmerId] - platformFee;
await fetch('https://api.paystack.co/transfer', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
source: 'balance', amount: payout,
recipient: farmer.paystack_recipient_code,
reason: 'Order #' + meta.order_id + ' payout',
}),
});
// Notify farmer of new order
await sendOrderNotification(farmer.phone, meta.order_id, farmerTotals[farmerId] / 100);
}
}
// Reduce stock on order confirmation
async function reduceStock(orderId) {
var items = await db.orderItems.findByOrder(orderId);
for (var item of items) {
var product = await db.products.findById(item.product_id);
if (product.stock_qty < item.qty) {
// Out of stock after payment — refund this item and notify
await refundOrderItem(item);
continue;
}
await db.products.update(item.product_id, { stock_qty: product.stock_qty - item.qty });
}
}
// Delivery: aggregate order by delivery zone
async function assignDeliveryDriver(orderId) {
var order = await db.orders.findById(orderId);
var customer = await db.customers.findById(order.customer_id);
var driver = await db.drivers.findAvailableInZone(customer.delivery_zone);
await db.orders.update(orderId, { driver_id: driver.id, status: 'out_for_delivery' });
await sendSMS(driver.phone, 'New order ' + orderId + ' for delivery to ' + customer.address);
await sendSMS(customer.phone, 'Your order is on its way! Driver: ' + driver.name + ' — ' + driver.phone);
}
// Cron: weekly farmer reconciliation report
async function sendFarmerWeeklyReport(farmerId) {
var weekStart = new Date();
weekStart.setDate(weekStart.getDate() - 7);
var items = await db.orderItems.findByFarmerAndPeriod(farmerId, weekStart, new Date());
var totalEarned = items.reduce(function(sum, i) { return sum + i.subtotal; }, 0);
var farmer = await db.farmers.findById(farmerId);
await sendFarmerReport(farmer.phone, totalEarned / 100, items.length);
}
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
See build a grocery delivery app with rider payouts for a related model focused on rider-based delivery and per-delivery payouts.
KES 2,999
The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.
Start Paystack Course