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 Gift Card System on Paystack
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Build a Gift Card System on Paystack

Build a gift card system by: 1) letting customers purchase gift cards via Paystack (any amount), 2) generating a unique redemption code after payment webhook fires, 3) emailing the code to the recipient, 4) allowing code redemption at checkout as a partial or full payment discount, and 5) tracking remaining balance per code.

In this article

  1. 1. Gift Card Purchase and Code Generation
  2. 2. Redemption at Checkout
  3. 3. Learn More

Gift Card Purchase and Code Generation

Tables: gift_cards (code, initial_amount, remaining_balance, purchased_by, recipient_email, purchased_at, expires_at, status), gift_card_redemptions (gift_card_id, order_id, amount_used, redeemed_at).

var crypto = require('crypto');

function generateGiftCardCode() {
  // Format: XXXX-XXXX-XXXX-XXXX (16 uppercase letters/numbers)
  var bytes = crypto.randomBytes(8);
  var hex = bytes.toString('hex').toUpperCase();
  return hex.slice(0, 4) + '-' + hex.slice(4, 8) + '-' + hex.slice(8, 12) + '-' + hex.slice(12, 16);
}

async function purchaseGiftCard(buyerEmail, recipientEmail, amountInKobo) {
  var reference = 'GIFT-' + Date.now();
  var tempCode = generateGiftCardCode(); // hold before payment confirms

  // Initialize Paystack transaction
  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: buyerEmail, amount: amountInKobo, currency: 'NGN', reference,
      metadata: { purpose: 'gift_card', recipient_email: recipientEmail, temp_code: tempCode },
    }),
  });
  return (await res.json()).data.authorization_url;
}

// Webhook: create gift card after payment
if (event.event === 'charge.success' && event.data.metadata.purpose === 'gift_card') {
  var meta = event.data.metadata;
  var expires = new Date();
  expires.setFullYear(expires.getFullYear() + 1); // 1-year expiry

  await db.giftCards.create({
    code: meta.temp_code,
    initial_amount: event.data.amount,
    remaining_balance: event.data.amount,
    purchased_by: event.data.customer.email,
    recipient_email: meta.recipient_email,
    expires_at: expires,
    status: 'active',
  });

  await sendGiftCardEmail(meta.recipient_email, meta.temp_code, event.data.amount);
}

Redemption at Checkout

async function applyGiftCard(cartTotal, giftCardCode) {
  var giftCard = await db.giftCards.findByCode(giftCardCode);

  if (!giftCard) throw new Error('Invalid gift card code');
  if (giftCard.status !== 'active') throw new Error('Gift card is not active');
  if (new Date() > giftCard.expires_at) throw new Error('Gift card has expired');
  if (giftCard.remaining_balance <= 0) throw new Error('Gift card has no remaining balance');

  var discount = Math.min(giftCard.remaining_balance, cartTotal);
  var remainingToPay = cartTotal - discount;

  return { discount, remainingToPay, giftCardBalance: giftCard.remaining_balance };
}

async function checkoutWithGiftCard(customerEmail, cartTotal, giftCardCode, orderId) {
  var { discount, remainingToPay } = await applyGiftCard(cartTotal, giftCardCode);

  // Record the redemption
  await db.giftCardRedemptions.create({ gift_card_code: giftCardCode, order_id: orderId, amount_used: discount });
  await db.giftCards.decrement(giftCardCode, 'remaining_balance', discount);
  if ((await db.giftCards.findByCode(giftCardCode)).remaining_balance === 0) {
    await db.giftCards.update(giftCardCode, { status: 'exhausted' });
  }

  if (remainingToPay <= 0) {
    // Fully covered by gift card — complete order without Paystack transaction
    await db.orders.update(orderId, { status: 'paid', payment_method: 'gift_card' });
    return { fullyPaid: true };
  }

  // Charge the remaining amount via Paystack
  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: remainingToPay, metadata: { order_id: orderId } }),
  });
  return { fullyPaid: false, authorizationUrl: (await res.json()).data.authorization_url };
}

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 loyalty and points system tied to payments for a similar value-credit system with a different accumulation model.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓Gift card codes should be randomly generated and cryptographically unpredictable — not sequential numbers.
  • ✓Track balances per code, not per user — gift cards can be transferred or gifted to anyone.
  • ✓Support partial redemption: a NGN 10,000 gift card can be used across multiple orders.
  • ✓At checkout, apply the gift card discount server-side before initializing the Paystack transaction.
  • ✓Gift cards are a liability until redeemed — account for them in your financial reconciliation.

Frequently Asked Questions

How do I handle gift cards in financial reconciliation?
Gift card purchases are a liability, not revenue — you have received money but not yet delivered value. When the gift card is redeemed, you convert the liability to revenue. Maintain a gift_card_liability ledger: credit on purchase, debit on redemption. Report unredeemed gift card balances as liabilities on your balance sheet.
Can I make gift cards available in different denominations?
Yes. Either let customers choose a preset amount (NGN 5,000, 10,000, 20,000) or enter a custom amount within a range you define (minimum NGN 1,000, maximum NGN 100,000). Custom amounts make gift cards more flexible; preset amounts simplify your product catalog.
What if someone enters a wrong gift card code at checkout?
Return a clear error: "Invalid gift card code. Please check the code and try again." After 3 failed attempts with different codes from the same IP or session, add a brief delay or CAPTCHA to prevent brute-force guessing. Log failed attempts for security monitoring.

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 an Affiliate Commission Engine

A build guide for an affiliate commission engine where affiliates share tracking links, earn commissions when their referrals convert (pay via Paystack), and withdraw their balance via bank transfer. Covers click tracking, last-click attribution, commission ledger, and Paystack Transfers payout.

Read more

Build a Farmers Market Ordering Platform

A build guide for a farmers market ordering platform where customers order fresh produce from multiple farmers in one cart, the platform collects the combined payment via Paystack, and each farmer receives their share via Paystack Split Payments or Transfers. Covers inventory management, order routing to individual farmers, and delivery coordination.

Read more

Building a Kenyan Utility Bill Payment Integration

A developer guide to building a utility bill payment platform for Kenya using Paystack. Covers bill lookup by account number, payment collection via M-Pesa and cards, forwarding payments to utility paybills via Transfers, receipt generation, recurring utility payments, multi-utility platform design, and when direct M-Pesa paybill is the better option.

Read more

Split Payment Reconciliation and Subaccount Reporting

Split payment reconciliation means verifying that every vendor received the right amount from every transaction. This guide covers querying Paystack transaction and settlement data, building per-vendor earnings reports from your database, and finding discrepancies between expected and actual settlement.

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.