McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Build a Farmers Market Ordering Platform
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Build a Farmers Market Ordering Platform

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.

In this article

  1. 1. Multi-Farmer Cart and Payment
  2. 2. Inventory Management and Delivery Coordination
  3. 3. Learn More

Multi-Farmer Cart and Payment

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);
  }
}

Inventory Management and Delivery Coordination

// 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.

Learn More

See build a grocery delivery app with rider payouts for a related model focused on rider-based delivery and per-delivery payouts.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓Create one Paystack Subaccount per farmer — revenue splits happen automatically at checkout.
  • ✓For mixed-farmer carts, collect full payment then use Paystack Transfers to pay each farmer.
  • ✓Track inventory per farmer so customers see real-time stock levels before ordering.
  • ✓Route orders to each farmer via SMS or WhatsApp after the webhook confirms payment.
  • ✓Aggregate weekly payouts for farmers who prefer bank transfer over instant subaccount settlement.

Frequently Asked Questions

What happens if a farmer runs out of stock after an order is paid?
Check stock availability at checkout (before payment) and reserve the quantity for the pending order. When the webhook confirms, finalize the stock deduction. If a race condition results in a paid item going out of stock anyway, refund just that line item via the Paystack Refund API with a partial amount and notify the customer. Partial refunds work by specifying the amount parameter in the refund request.
How do I handle minimum order quantities or box subscriptions?
Add a minimum_order_qty field to the products table and validate at cart checkout. For box subscriptions (weekly vegetable box), use Paystack Plans for recurring billing — the same Plan-based subscription model as a subscription box business. Each week's delivery is triggered when the invoice.create webhook fires with a success status.
How do I onboard farmers who do not have smartphones or bank accounts?
Register farmers using mobile agent-assisted onboarding (a field agent visits the farm). For unbanked farmers, set up M-Pesa as the payout method (Paystack supports M-Pesa payouts in Kenya). For feature phones, send order notifications via SMS instead of app push. Farmers can check their earnings by texting a short code or having a family member access the farmer portal.

Learn Paystack Integration

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

Not ready? Create Free Account

Keep reading

Things You Can Build with Paystack: Project Guides

A complete map of real-world projects you can build using the Paystack API. From online store checkouts and subscription platforms to savings apps and solar pay-as-you-go systems, each category links to step-by-step build guides with working code.

Read more

Build a Parking Payment App

A build guide for a parking payment app where drivers scan a QR code on entry, pay for their session via Paystack (card or M-Pesa), and the system validates payment before the barrier lifts for exit. Covers time-based pricing, session management, and overstay handling.

Read more

Build a Referral Payout System

A build guide for a referral payout system where users share referral links, earn commissions when referrals convert, and withdraw their balance via Paystack Transfers to their bank account or M-Pesa wallet.

Read more

Build a Veterinary Clinic Booking and Payment System

A build guide for a veterinary clinic booking and payment system where pet owners book appointments online, pay a deposit via Paystack to confirm the slot, and pay the balance at the clinic after the consultation. Includes pet health records, vaccination schedules, and automated reminders.

Read more

Paystack in Kenya: M-Pesa, Pesalink and the Daraja Question

The complete guide to using Paystack in Kenya. Covers every supported payment method, the Daraja question, M-Pesa charge code, transfers to mobile wallets and paybills, Pesalink, settlement, and Kenya-specific regulatory considerations.

Read more

Building a Freelance Marketplace on Paystack

A freelance marketplace holds client funds until the work is approved, then releases to the freelancer. This guide covers implementing that hold-and-release pattern using Paystack delayed settlement, collecting platform commission via splits, and handling disputes and refunds.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.