RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /How-to
  5. /How to build a local AI product with Nigerian naira pricing
HOW-TO · SUP

How to build a local AI product with Nigerian naira pricing

intermediate·30 min·By Fredoline Eruo
Target environment
Ubuntu 24.04 · Ollama 0.4.x
PREREQUISITES

Local AI service deployed, Paystack integration, naira pricing strategy

What this does

Packaging a local AI service as a monetized product requires integrating Paystack for naira-denominated payments, defining subscription tiers, and handling payment webhooks. This guide covers currency display with the ₦ symbol, tier configuration, webhook verification, and subscription management for Nigerian customers.

Steps

1. Install Paystack SDK

pip install paystackpy python-dotenv

2. Define subscription tiers

TIERS = {
    "starter": {
        "name": "Starter",
        "price_ngn": 5_000,
        "display": "₦5,000/month",
        "requests_per_month": 1_000,
        "features": ["basic_ai_access", "email_support"],
    },
    "professional": {
        "name": "Professional",
        "price_ngn": 15_000,
        "display": "₦15,000/month",
        "requests_per_month": 10_000,
        "features": ["advanced_ai_access", "priority_support", "api_access"],
    },
    "enterprise": {
        "name": "Enterprise",
        "price_gn": 50_000,
        "display": "₦50,000/month",
        "requests_per_month": -1,  # unlimited
        "features": ["full_access", "dedicated_support", "sla"],
    },
}

3. Initialize Paystack and create a subscription

import paystackpy as paystack
from dotenv import load_dotenv

load_dotenv()
ps = paystack.Paystack(secret_key=os.getenv("PAYSTACK_SECRET_KEY"))

def create_subscription(email: str, tier: str) -> dict:
    plan_code = f"ai_{tier}_monthly"
    return ps.subscription.create(
        email=email,
        plan=plan_code,
    )

4. Build the webhook handler Verify Paystack webhook signatures to prevent spoofed payment notifications:

import hmac, hashlib
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.post("/webhook/paystack")
async def paystack_webhook(request: Request):
    payload = await request.body()
    signature = request.headers.get("x-paystack-signature")
    expected = hmac.new(
        os.getenv("PAYSTACK_WEBHOOK_SECRET").encode(),
        payload, hashlib.sha512
    ).hexdigest()
    if signature != expected:
        raise HTTPException(status_code=403, detail="Invalid signature")
    event = await request.json()
    if event["event"] == "charge.success":
        await activate_subscription(event["data"]["customer"]["email"])
    return {"status": "received"}

5. Display prices in naira throughout the UI Use the Intl.NumberFormat API for consistent formatting:

const formatter = new Intl.NumberFormat('en-NG', {
  style: 'currency',
  currency: 'NGN',
  minimumFractionDigits: 0,
});
// formatter.format(15000) → "₦15,000"
  • Record the local run evidence. Save the exact command, runtime or package version, model name if applicable, and observed output so the result can be reproduced later.

Verification

Test the subscription creation:

curl -X POST http://localhost:8000/subscription \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","tier":"professional"}'

Expected: {"status":"success","subscription_code":"SUB_xxx","amount_display":"₦15,000/month"}

Test the webhook locally:

curl -X POST http://localhost:8000/webhook/paystack \
  -H "Content-Type: application/json" \
  -H "x-paystack-signature: <valid_hmac_hex>" \
  -d '{"event":"charge.success","data":{"customer":{"email":"[email protected]"}}}'

Expected: {"status":"received"} with HTTP 200

Common failures

  • Currency display mismatch: Always store prices as integers in kobo (smallest unit) and convert to naira at display time to avoid floating-point rounding errors.
  • Webhook replay attacks: Validate the signature on every request and maintain a deduplication log using the payment reference to prevent processing the same event twice.
  • Failed webhook verification in test mode: Paystack test mode requires a valid test secret key. Never hardcode production keys in development.
  • Subscription renewal failures: Set up a daily reconciliation job that checks subscription expiry dates and sends renewal reminders 3 days before expiration.

Related guides

  • How to set up agent scheduling with cron and triggers — A nightly reconciliation agent syncs Paystack subscription status and deactivates expired accounts.
  • How to build an AI content generation pipeline — The content pipeline becomes the core product feature that subscribers pay for via these tiers.
← All how-to guidesCourses →