Skip to content

getblitz-io/getblitz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

32 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GetBlitz Payment Gateway

A self-hosted payment gateway for SEPA Instant Transfers with real-time WebSocket notifications. Built for businesses accepting online and offline EUR payments across Europe.

Features

  • 🏦 SEPA Payments - Accept SEPA Instant Transfers via bank integrations (Qonto, custom providers)
  • πŸ” Self-Hosted - Full data sovereignty with your own database and infrastructure
  • ⚑ Real-time - WebSocket notifications for instant payment confirmations
  • 🏒 Multi-tenant - Organization-based access with API key management
  • πŸ“± Embeddable SDK - Lightweight JavaScript widget for merchant integration
  • πŸ”’ Secure - HMAC webhook verification, rate limiting, and structured logging
  • πŸ§ͺ Test Mode - Built-in test bank simulator for development

Quick Start

Prerequisites

  • Node.js 22+
  • pnpm 10+
  • Docker & Docker Compose

1. Install Dependencies

pnpm install

2. Configure Environment

Create .env files for each app based on your configuration. Key variables include:

  • DATABASE_USER - PostgreSQL user
  • DATABASE_PASSWORD - PostgreSQL password
  • DATABASE_HOST - PostgreSQL host
  • DATABASE_PORT - PostgreSQL port
  • DATABASE_NAME - PostgreSQL database
  • REDIS_URL - Redis URL for pub/sub
  • AUTH_SECRET - Better Auth secret key
  • NEXT_PUBLIC_APP_URL - Public app URL

3. Start Infrastructure

# Start PostgreSQL and Redis
docker compose up -d

4. Setup Database

# Generate Prisma client
pnpm db:generate

# Push schema to database
pnpm db:push

5. Start Development Servers

# Start all services (Next.js + WSS + Demo + Test Bank)
pnpm dev

# Or start individually:
pnpm dev:next       # Next.js dashboard + API (port 3000)
pnpm dev:wss        # WebSocket server
pnpm dev:demo       # Demo merchant site (port 3002)
pnpm dev:test-bank  # Mock bank simulator (port 3003)

The dashboard will be available at http://localhost:3000

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Infrastructure                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ PostgreSQL  β”‚              Redis                       β”‚         β”‚
β”‚  (Database) β”‚           (Pub/Sub)                      β”‚         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                    β”‚                    β”‚
        β–Ό                    β–Ό                    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Next.js     β”‚    β”‚  WebSocket    β”‚    β”‚   Client      β”‚
β”‚  Dashboard    │◄───│   Server      │◄───│    SDK        β”‚
β”‚   + API       β”‚    β”‚   (Socket.io) β”‚    β”‚   (GetBlitz)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                    β–²                    β”‚
        β”‚                    β”‚                    β”‚
        β–Ό                    β”‚                    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Bank Providerβ”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚   Merchant    β”‚
β”‚   Webhook     β”‚                         β”‚   Website     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

getblitz/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ web/                 # Dashboard + API routes (Next.js 16)
β”‚   β”œβ”€β”€ wss/                 # WebSocket server (Socket.io)
β”‚   β”œβ”€β”€ demo/                # Demo merchant site
β”‚   └── test-bank/           # Mock bank simulator for development
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ api/                 # tRPC routers, services, repositories (DI pattern)
β”‚   β”œβ”€β”€ auth/                # Better Auth configuration
β”‚   β”œβ”€β”€ bank-providers/      # Bank provider integrations (Qonto, test-bank)
β”‚   β”œβ”€β”€ database/            # Prisma schema and client
β”‚   β”œβ”€β”€ redis/               # Redis client and pub/sub
β”‚   β”œβ”€β”€ shared-types/        # TypeScript interfaces
β”‚   β”œβ”€β”€ ui/                  # Shared UI components (shadcn/ui)
β”‚   β”œβ”€β”€ validators/          # Zod schemas
β”‚   β”œβ”€β”€ websocket/           # WebSocket utilities
β”‚   └── getblitz-client/     # Embeddable payment SDK
└── tooling/                 # ESLint, Prettier, TypeScript, Vitest configs

API Reference

Create Payment Challenge

POST /api/v1/challenge
Authorization: Bearer <API_KEY>
Content-Type: application/json

{
  "amount": 500,           # Amount in cents (€5.00)
  "currency": "EUR",       # EUR only
  "bankAccountId": "uuid"  # Optional: specific bank account
}

Response:

{
  "sessionId": "uuid",
  "referenceId": "GB-A9F3B2C1",
  "paymentUrl": "https://pay.example.com/pay/uuid",
  "expiresAt": "2024-01-01T12:15:00.000Z"
}

Webhook Events

The gateway sends webhooks to merchants for payment events:

Event Description
payment.success Payment completed (full amount received)
payment.partial Partial payment received (for split payments)
payment.failed Payment failed
payment.expired Payment session expired

All webhooks include amountPaidCents showing current progress toward the total amountCents.

πŸ“š See docs/webhooks.md for payload schema and signature verification.

SDK Integration

<script src="https://cdn.yourdomain.com/getblitz.js"></script>
<script>
  const payment = new GetBlitz({
    sessionId: "sess_123",
    apiUrl: "https://pay.yourdomain.com",
    wssUrl: "wss://wss.yourdomain.com",
  });

  payment.mount("#payment-container");

  payment
    .on("onSuccess", (token) => {
      console.log("Payment successful:", token);
    })
    .on("onError", (error) => {
      console.error("Payment failed:", error);
    })
    .on("onExpired", () => {
      console.log("Payment session expired");
    });
</script>

Bank Provider Integration

GetBlitz supports multiple bank providers through a pluggable adapter system.

πŸ“š See docs/banks/ for detailed setup guides.

Supported Providers

Provider Auth Type Description Setup Guide
Qonto OAuth2 Business banking for SMEs View
Revolut Certificate Business banking for SMEs View
Test Bank None Mock provider for development View

Note: Test Bank is automatically hidden in production environments.

Adding a Custom Provider

Bank providers implement a standard interface in packages/bank-providers:

interface BankProvider {
  id: string;
  displayName: string;
  authType: "oauth2" | "api_key" | "certificate" | "none";
  isTestProvider: boolean;

  getSetupGuide(): string | null;
  getAuthUrl(params: AuthParams): string;
  exchangeCode(params: CodeParams): Promise<BankCredentials>;
  listAccounts(params: AccountParams): Promise<Account[]>;
  verifyAndParseWebhook(params: WebhookParams): Promise<WebhookResult>;
  createWebhook(params: WebhookCreateParams): Promise<WebhookConfig>;
}

Configuration

Environment Variables

Variable Description Required
DATABASE_USER PostgreSQL user βœ…
DATABASE_PASSWORD PostgreSQL password βœ…
DATABASE_HOST PostgreSQL host βœ…
DATABASE_PORT PostgreSQL port βœ…
DATABASE_NAME PostgreSQL database βœ…
REDIS_URL Redis URL for pub/sub βœ…
AUTH_SECRET Better Auth secret key βœ…
NEXT_PUBLIC_APP_URL Public app URL βœ…
WSS_URL WebSocket server URL βœ…
CRON_SECRET Cron job auth secret ⚠️ Production

Provider-specific variables (e.g., Qonto OAuth credentials) should be configured per your bank integration.

Development

Running Tests

# Run all tests
pnpm test

# Run tests for a specific package
pnpm -F @getblitz/api test

Database Commands

pnpm db:push      # Push schema to database
pnpm db:migrate   # Run migrations
pnpm db:studio    # Open Prisma Studio
pnpm db:generate  # Generate Prisma client

Linting & Formatting

pnpm lint         # Run ESLint
pnpm lint:fix     # Fix lint issues
pnpm format       # Check formatting
pnpm format:fix   # Fix formatting
pnpm typecheck    # Run TypeScript checks

Deployment

One-Click Deploy

Deploy to DigitalOcean

Deploy to Render

See DEPLOYMENT.md for detailed instructions and environment configuration.

Docker (Manual)

# Build and run with Docker Compose
docker compose -f compose.yml up -d

Vercel (Next.js)

  1. Connect your repository to Vercel
  2. Set the root directory to apps/web
  3. Add environment variables
  4. Deploy

Session Expiration Cron

Set up a cron job to expire pending sessions:

# Every minute
* * * * * curl -H "Authorization: Bearer $CRON_SECRET" https://pay.yourdomain.com/api/cron/expire-sessions

Or use Vercel Cron by adding to apps/web/vercel.json:

{
  "crons": [
    {
      "path": "/api/cron/expire-sessions",
      "schedule": "* * * * *"
    }
  ]
}

Payment Flow

  1. Merchant creates a payment challenge via API
  2. Customer is redirected to payment page
  3. Customer scans EPC-QR code with their bank app
  4. Customer completes SEPA Instant Transfer
  5. Bank Webhook sends payment confirmation
  6. API matches payment by reference ID
  7. API updates payment status to PAID
  8. Redis publishes event for real-time notification
  9. WSS forwards event to connected clients
  10. SDK triggers onSuccess callback

Security

  • API Keys: Secure, rotatable keys per organization
  • Webhook Verification: HMAC-SHA256 signature validation
  • Rate Limiting: Configurable limits via Redis
  • CORS: Strict origin validation on WebSocket connections
  • Database: ACID transactions for payment state updates

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published

Contributors 3

  •  
  •  
  •