# BeezifiPay

Production-ready payer-centric payment platform implementing the concepts of **US8073771B2** ("Method and system for payer-centric payment using mobile terminal").

Built with Node.js, Express, EJS, and MariaDB. No TypeScript, no frontend framework — server-rendered HTML with a clean, accessible UI.

---

## Architecture

```
┌─────────────────┐     checkout request      ┌──────────────────┐
│  Merchant Portal│ ─────────────────────────► │   Payer Portal   │
│  /merchant/*    │                            │   /payer/*       │
└─────────────────┘ ◄───────────────────────── └──────────────────┘
        │               approve / decline               │
        │                                               │
        ▼                                               ▼
┌───────────────────────────────────────────────────────────────────┐
│                     Express + MariaDB                             │
│  Routes → Services → Repositories → DB                           │
│  Stripe PaymentIntents (payer card never seen by merchant)        │
└───────────────────────────────────────────────────────────────────┘
        │
        ├── /admin/*          read-only platform dashboard
        ├── /webhooks/stripe  Stripe event receiver
        └── /health           load balancer probe
```

The platform enforces the payer-centric model: **the merchant never sees raw card data**. Stripe.js tokenizes the card client-side; BeezifiPay stores only the `pm_xxx` PaymentMethod ID.

---

## Stack

| Layer | Technology |
|---|---|
| Runtime | Node.js 20+ |
| Framework | Express 4 |
| Templates | EJS 5 |
| Database | MariaDB 10.6+ / MySQL 8+ |
| Payments | Stripe (PaymentIntents + Elements) |
| Email | Nodemailer (SMTP or dev-console fallback) |
| SMS | Twilio (optional — phone verification) |
| Logging | Pino + pino-http |
| Security | Helmet, CSRF tokens, bcrypt, express-rate-limit |

---

## Setup

### 1. Install dependencies

```bash
npm install
```

### 2. Configure environment

```bash
cp .env.example .env
```

Edit `.env` and fill in the required values:

| Variable | Required | Description |
|---|---|---|
| `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_NAME` | Yes | MariaDB connection |
| `SESSION_SECRET` | Yes | Min 48 chars, cryptographically random |
| `STRIPE_PUBLISHABLE_KEY` | Yes (payments) | `pk_test_…` from Stripe dashboard |
| `STRIPE_SECRET_KEY` | Yes (payments) | `sk_test_…` from Stripe dashboard |
| `STRIPE_WEBHOOK_SECRET` | Yes (webhooks) | `whsec_…` from `stripe listen` |
| `SMTP_HOST` | No | Leave blank to log emails to console in dev |
| `ADMIN_PASSWORD` | No | Leave blank to disable admin portal |
| `TWILIO_ACCOUNT_SID` / `TWILIO_AUTH_TOKEN` / `TWILIO_FROM_NUMBER` | No | Leave blank to disable phone verification |

Generate a session secret:

```bash
node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"
```

### 3. Create the database

```sql
CREATE DATABASE BeezifiPay CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'BeezifiPay'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON BeezifiPay.* TO 'BeezifiPay'@'localhost';
FLUSH PRIVILEGES;
```

### 4. Run migrations

```bash
npm run migrate
```

Migrations also run automatically on every server start. Safe to run multiple times.

### 5. Start the server

```bash
# Development (auto-restarts on file changes)
npm run dev

# Production
npm start
```

---

## Stripe setup

For development, use [Stripe test mode](https://dashboard.stripe.com/test/apikeys).

To receive webhooks locally:

```bash
stripe listen --forward-to localhost:3000/webhooks/stripe
```

Copy the `whsec_…` secret it prints into `.env` as `STRIPE_WEBHOOK_SECRET`.

For production, create a webhook endpoint in the Stripe dashboard pointing to `https://yourdomain.com/webhooks/stripe` with these events:
- `payment_intent.succeeded`
- `payment_intent.payment_failed`

---

## Portal URLs

| Portal | URL |
|---|---|
| Landing page | `/` |
| Merchant login | `/merchant/login` |
| Merchant registration | `/merchant/register` |
| Payer login | `/payer/login` |
| Payer registration | `/payer/register` |
| Admin portal | `/admin` |
| Health check | `/health` |
| Patent demo | `/demo` |

---

## Features

### Phase 1 — Foundation
- Merchant and payer account registration with email verification
- Secure login with bcrypt, account lockout (5 attempts → 15-minute lockout)
- Token-based password reset (2-hour expiry)
- CSRF protection on all state-mutating requests
- MariaDB session store
- Pino structured logging with sensitive field redaction
- SQL migration system with per-file tracking

### Phase 2 — Organizations & payment vault
- Merchant organization creation and management
- Store locations (add, activate/deactivate)
- Staff invitations with role-based access: `owner` / `admin` / `staff`
- Payer payment method vault via Stripe Elements (PCI-compliant — raw card never reaches BeezifiPay)
- Optional phone number verification via Twilio OTP

### Phase 3 — Checkout lifecycle
- Checkout request creation with line items (subtotal, tax, live total preview)
- Email delivery to payer with 24-hour expiry
- Payer approve / decline
- Stripe PaymentIntents for real payment processing
- Manual processor stub for development without Stripe keys
- 12-state lifecycle: `draft → delivered → approved → processing → settled/failed/refunded/expired/canceled`
- Comprehensive audit log on every state transition

### Phase 4 — Operations
- **Refunds**: full and partial refunds via Stripe; merchant refund form on settled checkouts
- **Outbound webhooks**: merchants register HTTP endpoints; events `checkout.settled`, `checkout.declined`, `checkout.payment_failed`, `checkout.refunded`; deliveries signed with `HMAC-SHA256`
- **Notification queue**: checkout-request emails written to DB first, then sent; exponential-backoff retry for failures; 60-second in-process queue processor
- **Stripe webhooks**: inbound `payment_intent.succeeded` and `payment_intent.payment_failed` with signature verification
- **Admin portal**: platform statistics, merchant user management (deactivate/reactivate), payer account management, checkout list, paginated audit log
- **Health check**: `GET /health` for load balancer probes

---

## Project structure

```
server.js               # Entry point — migrations, Express app, queue processor
src/
  app.js                # Express app factory — middleware stack, CSP, session
  config/index.js       # Typed config built from environment variables
  db/
    index.js            # mysql2 pool, query/queryOne/withTransaction helpers
    migrate.js          # SQL migration runner
    sessionStore.js     # MariaDB-backed express-session store
  lib/
    email.js            # Nodemailer with dev console fallback
    logger.js           # Pino structured logger with field redaction
    password.js         # bcrypt hash/verify helpers
    sms.js              # Twilio client with graceful no-op when unconfigured
    stripe.js           # Lazy Stripe singleton (null when no key configured)
    tokens.js           # Crypto random token generation and hashing
  middleware/
    authenticate.js     # requireMerchantAuth / requirePayerAuth / requireMerchantAuthWithOrg
    csrf.js             # Synchronizer token pattern
    errorHandler.js     # 404 + global error handler
    flash.js            # Session flash messages
    rateLimiter.js      # authLimiter (15 req/15 min) + generalLimiter (500 req/15 min)
    validate.js         # Joi error formatter
  repositories/         # Thin DB wrappers — no business logic
    auditLogRepo.js
    checkoutRepo.js
    emailVerificationRepo.js
    merchantUserRepo.js
    notificationRepo.js
    organizationRepo.js
    passwordResetRepo.js
    payerAccountRepo.js
    paymentMethodRepo.js
    phoneVerificationRepo.js
    refundRepo.js
    webhookRepo.js
  routes/
    index.js            # Root router — mounts all sub-routers
    merchant/           # auth, dashboard, organization (+ webhooks), checkout
    payer/              # auth, dashboard, methods, requests, phone verification
    admin/              # login/logout, dashboard, merchants, payers, checkouts, audit
    webhooks.js         # Stripe inbound webhook handler
  services/             # Business logic — orchestrates repos, email, SMS, webhooks
    checkoutService.js
    merchantAuthService.js
    notificationService.js
    organizationService.js
    payerAuthService.js
    paymentMethodService.js
    paymentService.js
    phoneVerificationService.js
    refundService.js
    webhookDispatcherService.js
  views/
    shared/             # _head.ejs, _foot.ejs, _flash.ejs, _errors.ejs
    merchant/
    payer/
    admin/
sql/
  migrations/           # 0001…000N numbered SQL files applied in sequence
public/
  platform/             # Static CSS and JS per portal
```

---

## Security

- **PCI scope reduction**: Stripe.js runs in an iframe from `js.stripe.com`. Card data goes browser → Stripe. BeezifiPay never receives or stores raw card numbers.
- **CSRF**: Every POST form includes a `_csrf` token validated against the session.
- **Rate limiting**: Auth endpoints limited to 15 requests per 15 minutes per IP. General limit: 500 requests per 15 minutes.
- **Session**: `httpOnly`, `sameSite: lax`, `secure: true` in production. Sessions stored in MariaDB.
- **Helmet**: Sets `Content-Security-Policy`, `X-Frame-Options`, `Strict-Transport-Security`, and more.
- **Webhook signatures**: Outbound webhooks signed with `HMAC-SHA256(secret, body)` in the `X-BeezifiPay-Signature` header. Inbound Stripe webhooks verified with `stripe.webhooks.constructEvent()` using the raw request body.
- **Audit log**: Append-only `audit_logs` table records every significant action with actor, target, IP, and user-agent.

---

## Running tests

```bash
npm test
```

Tests live in `tests/` and use Node's built-in test runner (`node --test`).

---

## License

UNLICENSED — proprietary, F9 Networks.
