How to: WhatsApp E-commerce Flow — Starter Kit

 How to: WhatsApp E-commerce Flow — Starter Kit

Full technical seriesiZND Technical Blog
Parts 1–6 — WhatsApp Webhooks ▸ Idempotency ▸ Orders ▸ Stripe ▸ Docker ▸ Netlify Serverless

This repository contains a production-ready WhatsApp E-commerce Backend designed to bridge the gap between the WhatsApp Business Cloud API and automated order fulfillment. It covers every layer — from webhook security to payment confirmation messages sent back to the customer.


🚀 Key Features

  • Robust Webhook Handling: Processes WhatsApp text messages and interactive messages (Product List Selection, Product detail clicks).
  • Security First: Cryptographix-hub-signature-256 verification on all WhatsApp and Stripe webhooks.
  • Idempotency: Redis-backed event deduplication prevents double-orders if WhatsApp retries a message delivery.
  • Zero-Oversell Inventory:
    • Atomic Reservations: Redis Lua script (scripts/reserve.lua) for concurrency-safe, TTL-controlled stock holds.
    • Reconciliation Cronscripts/cleanup-reservations.js scans expired reservations and marks pending orders as expired.
  • Payment Integration: Stripe Checkout session created per order; confirmation WhatsApp template sent automatically on checkout.session.completed.
  • Dual Netlify Modecreate-order-proxy supports BACKEND_MODE=proxy (forward to dedicated server) or BACKEND_MODE=inline (run DB logic directly in function).
  • Flexible Deployment: Docker, Netlify Functions, or cPanel/VPS — all covered.

📂 Repository Structure

/
├── netlify/
│   └── functions/
│       ├── webhook.js             # Serverless WhatsApp entry point (Part 5)
│       ├── payment-callback.js    # Stripe webhook handler (Part 5)
│       └── create-order-proxy.js  # Dual-mode order proxy (Part 6)
├── src/
│   └── index.js                  # Core Express app — full implementation (Part 4)
├── migrations/
│   └── migration.sql             # UUID & JSONB-optimised Postgres schema (Part 4)
├── scripts/
│   ├── cleanup-reservations.js   # Redis reconciliation & stock release cron (Part 5)
│   └── reserve.lua               # Atomic Redis Lua reservation script (Part 5)
├── templates/
│   └── whatsapp_templates.md     # Pre-formatted message templates
├── Dockerfile                    # Alpine-based production image (Part 5)
├── docker-compose.yml            # Full-stack local environment (Part 5)
├── postman_collection.json       # End-to-end test suite
├── .env.example                  # All required environment variables
└── README.md

🛠️ Quick Start

1. Local Development (Docker Compose)

git clone <repo-url>
cd "WhatsApp E-commerce Flow"

# Copy and fill environment variables
cp .env.example .env

# Build and launch all services (Express app + Postgres + Redis)
docker compose up --build

# Apply the database schema
docker compose exec db psql -U postgres -d wa -f /app/migrations/migration.sql

Server available at http://localhost:3000.

2. Run Cleanup Script (manual or cron)

node scripts/cleanup-reservations.js

Schedule this via system cron or Netlify Scheduled Functions to automatically release expired stock holds.

3. Test with Postman

  1. Import postman_collection.json into Postman.
  2. Set environment variables: ACCESS_TOKENPHONE_NUMBER_IDCATALOG_IDTO_WABASE_URLVERIFY_TOKEN.
  3. Run requests in order:
    1. WhatsApp — Send Product List → triggers the shopping flow.
    2. Backend — Webhook Verification (GET /webhook) → confirm token.
    3. Backend — Create Order (POST /create-order) → provisional order + Stripe session.
    4. Backend — Payment Callback (POST /payment-callback) → simulate Stripe success.
    5. Backend — Catalog Sync (POST /catalog-sync) → placeholder for future catalog push.

🔑 Environment Variables

Copy .env.example to .envNever commit secrets.

# Server
PORT=3000
BASE_URL=https://your-app-url.com

# Postgres
DATABASE_URL=postgres://user:pass@host:5432/db

# Redis
REDIS_URL=redis://redis:6379

# WhatsApp Cloud API
WHATSAPP_PHONE_NUMBER_ID=1234567890
WHATSAPP_ACCESS_TOKEN=EAA...
WHATSAPP_APP_SECRET=your_whatsapp_app_secret
VERIFY_TOKEN=your_webhook_verify_token

# Stripe
STRIPE_SECRET=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Netlify Function Mode
BACKEND_MODE=proxy            # 'proxy' or 'inline'
BACKEND_URL=https://your-main-backend.com  # only if BACKEND_MODE=proxy

# Optional
LOG_LEVEL=info

🔒 Security & Idempotency

MechanismImplementation
WhatsApp Signaturex-hub-signature-256 verified via crypto.timingSafeEqual on raw body.
Stripe Signaturestripe.webhooks.constructEvent with raw body required.
IdempotencyEvery wamid.* and Stripe event ID stored in Redis for 24 h to prevent re-processing.
Stock SafetyRedis Lua script atomically checks and decrements stock; TTL auto-expires stale holds.

📦 Deployment Options

Option A — Netlify (Serverless)

  1. Connect this repo to your Netlify site.

  2. Go to Site settings → Environment variables and set all keys from .env.example.

  3. Set BACKEND_MODE:

    • proxy — recommended for production; Netlify functions forward to a dedicated Express server.
    • inline — all logic runs inside the function; suitable for low traffic, accepts function time limits.
  4. Register your Stripe webhook endpoint:

    https://<site>.netlify.app/.netlify/functions/payment-callback
    
  5. For the reservation cleanup, use Netlify Scheduled Functions or an external cron to run cleanup-reservations.js periodically.

Option B — cPanel / VPS (Traditional)

  1. Upload files via SFTP or Git.

  2. Set environment variables in cPanel Node App Manager or via .env.

  3. Entry point: src/index.js.

  4. Use pm2 (if available) for process management:

    pm2 start src/index.js --name whatsapp-commerce
    
  5. Ensure your Postgres and Redis instances are reachable from the cPanel server.

Option C — Docker (Self-hosted / VPS)

docker compose up --build -d

All services (app, db, redis) are wired together via docker-compose.yml. Redis is configured with persistence (--save 60 1).


🗄️ Database Schema

The schema uses UUID primary keys and JSONB for flexible item and metadata storage:

TablePurpose
productsProduct catalogue with SKU, price, currency
variantsProduct variants (size, colour) with price delta
ordersAll orders with payment & fulfillment statuses
reservations(Optional) Long-term reservation tracking

Run migrations/migration.sql against your Postgres database to initialise.


🔄 Order Flow

Customer → WhatsApp message
    → Webhook verified (signature + idempotency)
    → Product selected (text intent or interactive reply)
    → Provisional order created in Postgres
    → Stock reserved in Redis (10-minute TTL)
    → Stripe Checkout session created
    → Customer receives payment link via WhatsApp
    → Customer completes payment
    → Stripe fires checkout.session.completed
    → Order marked 'paid'; stock hold released
    → Order confirmation template sent via WhatsApp

❓ FAQ

Why a proxy function?
Keeps heavy database queries off Netlify serverless functions to avoid the 10-second execution limit. Set BACKEND_MODE=proxy and point BACKEND_URL to your Express server.

How do you prevent overselling?
Redis reservations with a short TTL (10 min) act as a hold. The atomireserve.lua Lua script checks and decrements stock in a single Redis transaction — no race conditions.

How do I submit WhatsApp message templates?
Pre-submit order_confirmation and shipping_update templates in the Meta Business Suite under WhatsApp → Message Templates. Allow 24–48 h for approval before going live.

How do I clean up expired orders?
Run scripts/cleanup-reservations.js on a schedule. It scans reservations_by_sku:* sets in Redis, finds expired keys, removes them from the index, and marks the corresponding pending orders as expired in Postgres.


📋 Checklist Before Go-Live

  • [ ] WhatsApp App Secret set in WHATSAPP_APP_SECRET
  • [ ] Stripe webhook registered with raw-body endpoint
  • [ ] order_confirmation template approved by Meta
  • [ ] Redis and Postgres reachable from your deploy target
  • [ ] Cleanup cron configured (system cron, Netlify Scheduled Function, or external)
  • [ ] BACKEND_MODE set correctly for your deployment model
  • [ ] .env not committed to version control

📜 License

MIT — fork freely for client projects. Open a PR or issue for contributions.


Technical documentation based on the iZND WhatsApp E-commerce series (Parts 1–6).