Skip to content

spavlovic77/v0-nop-web-test-client

Repository files navigation

NOP Web Test Client

Table of Contents

Overview

NOP Web Test Client is a Next.js-based Progressive Web App (PWA) that enables merchants to:

  • Generate QR payment codes compliant with Slovak Payment Link Standard v1.3
  • Receive real-time payment confirmations via MQTT
  • Track transaction history with comprehensive audit logging
  • Verify payment integrity using SHA-256 hashing
  • Operate in both TEST and PRODUCTION banking environments

The application uses mutual TLS (mTLS) authentication with client certificates to securely communicate with banking APIs, ensuring bank-grade security for all transactions.

Features

Core Functionality

  • Certificate Management: Upload and convert PKCS#12 certificates from XML format
  • QR Code Generation: Create payment QR codes following Slovak Payment Link Standard
  • Real-time Notifications: MQTT-based instant payment confirmations
  • Data Integrity: SHA-256 hash verification for payment authenticity
  • Transaction History: Complete audit trail with database persistence
  • Dual Environment: Seamless switching between TEST and PRODUCTION modes
  • PWA Support: Installable on mobile devices with offline capabilities

Security Features

  • Mutual TLS (mTLS) authentication
  • Client certificate-based API access
  • Input sanitization and XSS prevention
  • IBAN checksum validation (ISO 13616)
  • Temporary file management with automatic cleanup
  • Comprehensive audit logging
  • Data integrity verification

User Experience

  • Mobile-first responsive design
  • Real-time payment status updates
  • Automatic IBAN formatting
  • Currency input with Slovak formatting
  • Transaction summary and printing
  • Visual environment indicators (TEST/PRODUCTION)

Prerequisites

Required Software

  • Node.js 18.x or higher (Download)
  • npm 9.x or higher (included with Node.js)
  • Git (Download)

Required Services

  • Supabase Account - PostgreSQL database with real-time capabilities (Sign up)
  • Vercel Account - For deployment (optional) (Sign up)
  • Merchant Certificates - PKCS#12
  • CA Certificate Bundle - Root and intermediate certificates for API

Banking Requirements

  • Valid merchant account with Slovak bank supporting NOP
  • PKCS#12 certificate with VATSK (tax ID) and POKLADNICA (cash register ID)
  • Access to TEST environment for development
  • Production credentials for live transactions

Installation

1. Clone Repository

```bash git clone https://github.com/your-username/nop-web-test-client.git cd nop-web-test-client ```

2. Install Dependencies

```bash npm install ```

This installs all required packages including:

  • Next.js 16 with App Router
  • React 19.2
  • Supabase client libraries
  • MQTT.js for real-time messaging
  • node-forge for certificate handling
  • QRCode generation library
  • shadcn/ui components

3. Database Setup

Create Supabase Project

  1. Go to Supabase Dashboard
  2. Click "New Project"
  3. Enter project details:
    • Name: nop-client (or your preferred name)
    • Database Password: Strong password (save securely!)
    • Region: Europe West (recommended for Slovakia)
  4. Click "Create new project" and wait 2-3 minutes

Run Database Migrations

Execute SQL scripts in order using Supabase SQL Editor:

Step 1: Clean Database (Optional - only if starting fresh) ```bash

Open scripts/000_drop_all_tables.sql

Copy content to Supabase SQL Editor

Run to drop all existing tables

```

Step 2: Create transaction_generations Table ```bash

Open scripts/001_create_transaction_generations_table.sql

Copy content to Supabase SQL Editor

Run to create table with RLS policies

```

Step 3: Create mqtt_notifications Table ```bash

Open scripts/002_create_mqtt_notifications_table.sql

Copy content to Supabase SQL Editor

Run to create table with RLS policies

```

Step 4: Create mqtt_subscriptions Table ```bash

Open scripts/003_create_mqtt_subscriptions_table.sql

Copy content to Supabase SQL Editor

Run to create table with RLS policies

```

Verify Tables

In Supabase Dashboard → Table Editor, confirm these tables exist:

  • transaction_generations - Transaction generation audit log
  • mqtt_notifications - Payment notification storage
  • mqtt_subscriptions - MQTT subscription tracking

Configuration

Environment Variables

Create .env.local file in project root:

```env

Supabase Configuration

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

CA Certificate Bundle - TEST Environment

NEXT_PUBLIC_EMBEDDED_CA_BUNDLE=-----BEGIN CERTIFICATE----- MIIFazCCBFOgAwIBAgIQBN... (Complete CA certificate chain for api-banka-i.kverkom.sk) ... -----END CERTIFICATE-----

CA Certificate Bundle - PRODUCTION Environment

NEXT_PUBLIC_EMBEDDED_CA_BUNDLE_PROD=-----BEGIN CERTIFICATE----- MIIFazCCBFOgAwIBAgIQBN... (Complete CA certificate chain for api-banka.kverkom.sk) ... -----END CERTIFICATE----- ```

Obtaining Supabase Credentials

  1. In Supabase Dashboard, go to SettingsAPI
  2. Copy these values:
    • Project URLNEXT_PUBLIC_SUPABASE_URL
    • anon public keyNEXT_PUBLIC_SUPABASE_ANON_KEY
    • service_role keySUPABASE_SERVICE_ROLE_KEY

Obtaining CA Certificates

CA certificates are required for TLS verification with banking APIs.

For TEST Environment (api-banka-i.kverkom.sk):

  1. Visit crt.sh
  2. Search for: api-banka-i.kverkom.sk
  3. Download certificate chain (intermediate + root CA)
  4. Convert to PEM format if needed
  5. Add to NEXT_PUBLIC_EMBEDDED_CA_BUNDLE

For PRODUCTION Environment (api-banka.kverkom.sk):

  1. Visit crt.sh
  2. Search for: api-banka.kverkom.sk
  3. Download certificate chain (intermediate + root CA)
  4. Convert to PEM format if needed
  5. Add to NEXT_PUBLIC_EMBEDDED_CA_BUNDLE_PROD

Important: CA bundle should contain ONLY intermediate and root CA certificates, NOT the server certificate.

Usage

Development Mode

```bash npm run dev ```

Application runs at http://localhost:3000

Production Build

```bash npm run build npm start ```

Using the Application

1. Upload Certificates

  1. XML Authentication Data: Upload your PKCS#12 certificate in XML format
  2. Certificate Password: Enter the password for your certificate
  3. CA Certificate: Upload the CA certificate bundle (if not using embedded)
  4. Click Save Configuration

The application will:

  • Extract VATSK (tax ID) and POKLADNICA (cash register ID)
  • Convert PKCS#12 to PEM format
  • Validate certificate structure
  • Store credentials securely in session

2. Enter Payment Details

  1. IBAN: Enter recipient's IBAN (auto-formatted with spaces)
  2. Amount: Enter payment amount in EUR (auto-formatted)
  3. Environment: Toggle between TEST and PRODUCTION

3. Generate QR Code

  1. Click Generate QR Code
  2. Application will:
    • Call banking API to generate transaction ID
    • Create payment link following Slovak Payment Link Standard
    • Generate QR code
    • Automatically subscribe to MQTT for payment confirmation

4. Payment Confirmation

  1. Customer scans QR code with banking app
  2. Customer authorizes payment
  3. Application receives MQTT notification
  4. Payment integrity verified using SHA-256 hash
  5. Confirmation modal displayed with payment details

5. View Transaction History

  1. Click Transaction List
  2. Select date range
  3. View all transactions with amounts and statuses
  4. Print summary or detailed report

Architecture

Technology Stack

Frontend:

  • Next.js 16 (App Router)
  • React 19.2 with Server Components
  • TypeScript 5.x
  • Tailwind CSS v4
  • shadcn/ui components

Backend:

  • Next.js API Routes
  • Node.js 18+
  • MQTT.js for real-time messaging
  • node-forge for certificate handling

Database:

  • Supabase (PostgreSQL 15)
  • Row Level Security (RLS)
  • Real-time subscriptions

Infrastructure:

  • Vercel (deployment)
  • Service Worker (PWA)
  • Edge Functions (API routes)

Application Flow

```

  1. User uploads certificates → Certificate conversion (P12 to PEM)
  2. User enters payment details → Input validation and sanitization
  3. User generates QR → API call to banking system (mTLS)
  4. Banking API returns transaction ID → QR code generation
  5. Automatic MQTT subscription → Listen for payment confirmation
  6. Customer pays → Bank sends MQTT notification
  7. Application receives notification → Integrity verification
  8. Display confirmation → Save to database ```

API Architecture

``` ┌─────────────────┐ │ Next.js App │ │ (Frontend) │ └────────┬────────┘ │ ├─────────────────────────────────────┐ │ │ ▼ ▼ ┌─────────────────────┐ ┌──────────────────────┐ │ API Routes │ │ Supabase Database │ │ (Backend) │ │ (PostgreSQL) │ ├─────────────────────┤ ├──────────────────────┤ │ /api/generate- │◄─────────►│ transaction_ │ │ transaction │ │ generations │ │ │ │ │ │ /api/mqtt- │◄─────────►│ mqtt_notifications │ │ subscribe │ │ │ │ │ │ mqtt_subscriptions │ │ /api/convert-p12- │ │ │ │ to-pem │ └──────────────────────┘ └──────────┬──────────┘ │ ├──────────────────┬────────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │ Banking API │ │ MQTT Broker │ │ Certificate │ │ (mTLS) │ │ (mqtts://) │ │ Authority │ └─────────────┘ └──────────────┘ └──────────────┘ ```

Security

Threat Model

The application handles sensitive financial data and must protect against:

  • Man-in-the-middle attacks
  • Certificate theft
  • Data tampering
  • Replay attacks
  • XSS and injection attacks
  • Unauthorized access
  • Information disclosure

Security Implementations

1. Mutual TLS (mTLS) Authentication

Implementation:

  • Client certificates required for all banking API calls
  • Server certificate validation against trusted CA bundle
  • TLS 1.2+ enforced for all encrypted communications

Security Level: ⭐⭐⭐⭐⭐ (Bank-grade)

Attack Probability: Very Low (0.1%)

  • Requires compromising both client certificate and private key
  • Banking APIs reject invalid or expired certificates
  • Certificate pinning prevents MITM attacks

2. Certificate Management

Implementation: ```typescript // Temporary file creation with unique session ID const sessionId = randomUUID() const certPath = join(tmpdir(), ${sessionId}-client.pem)

// Write with restricted permissions (0o600 = owner read/write only) await writeFile(certPath, certPem, { mode: 0o600 })

// Automatic cleanup after use await unlink(certPath) ```

Security Level: ⭐⭐⭐⭐⭐

Vulnerabilities:

  • Temporary File Exposure (Low Risk)

    • Files written to /tmp directory
    • Readable by root user on shared systems
    • Mitigation: Files exist for <1 second, unique session IDs prevent conflicts
    • Attack Probability: Low (5%) - Requires local system access and precise timing
  • No Persistent Storage - Certificates never saved to disk permanently

  • Memory Safety - Certificates cleared from memory after use

  • Session Isolation - UUID-based naming prevents cross-session contamination

3. Input Validation and Sanitization

Implementation: ```typescript const sanitizeInput = (input: string): string => { return input .replace(/<script\b[^<](?:(?!</script>)<[^<])</script>/gi, "") .replace(/javascript:/gi, "") .replace(/on\w+\s=/gi, "") }

const validateIbanSecure = (iban: string): boolean => { const sanitized = sanitizeInput(iban).replace(/\s/g, "").toUpperCase() // Mod-97 checksum validation per ISO 13616 const rearranged = sanitized.slice(4) + sanitized.slice(0, 4) const numericString = rearranged.replace(/[A-Z]/g, (char) => (char.charCodeAt(0) - 55).toString() ) let remainder = 0 for (let i = 0; i < numericString.length; i++) { remainder = (remainder * 10 + parseInt(numericString[i])) % 97 } return remainder === 1 } ```

Security Level: ⭐⭐⭐⭐

Vulnerabilities:

  • Regex-based Sanitization (Medium Risk)

    • Regex patterns can be bypassed with sophisticated payloads
    • Attack Probability: Medium (15%) - Requires advanced XSS knowledge
    • Mitigation: Use DOMPurify library for production
    • Impact: Limited - React escapes output by default
  • IBAN Checksum Validation - Prevents invalid IBANs

  • Type Safety - TypeScript prevents type confusion attacks

  • Amount Validation - Digit-only input with reasonable limits

Recommendation: Replace regex sanitization with DOMPurify: ```typescript import DOMPurify from 'isomorphic-dompurify' const sanitizeInput = (input: string): string => DOMPurify.sanitize(input) ```

4. Data Integrity Verification

Implementation: ```typescript const generateDataIntegrityHash = async ( iban: string, amount: string, currency: string, endToEndId: string ): Promise => { const inputString = ${iban}|${amount}|${currency}|${endToEndId} const encoder = new TextEncoder() const data = encoder.encode(inputString) const hashBuffer = await crypto.subtle.digest("SHA-256", data) const hashArray = Array.from(new Uint8Array(hashBuffer)) return hashArray.map(b => b.toString(16).padStart(2, "0")).join("") } ```

Security Level: ⭐⭐⭐⭐⭐

Vulnerabilities:

  • Hash Collision (Theoretical Risk)

    • SHA-256 collision probability: 2^-256
    • Attack Probability: Negligible (<0.0001%)
    • Mitigation: Use HMAC-SHA256 with secret key for production
  • Cryptographically Secure - SHA-256 is industry standard

  • Tamper Detection - Any modification changes hash

  • Replay Protection - Transaction ID provides uniqueness

Recommendation: Upgrade to HMAC-SHA256 for production: ```typescript const secret = process.env.INTEGRITY_SECRET_KEY const key = await crypto.subtle.importKey( "raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"] ) const signature = await crypto.subtle.sign("HMAC", key, data) ```

5. MQTT Security

Implementation: ```typescript const client = mqtt.connect(mqtts://${broker}:8883, { cert: clientCertBuffer, key: clientKeyBuffer, ca: caCertBuffer, rejectUnauthorized: true, protocol: "mqtts", keepalive: 60, connectTimeout: 30000, reconnectPeriod: 0 }) ```

Security Level: ⭐⭐⭐⭐

Vulnerabilities:

  • Topic Enumeration (Low Risk)

    • Topic format: VATSK-{vatsk}/POKLADNICA-{pokladnica}/{transactionId}
    • Predictable structure allows topic guessing
    • Attack Probability: Low (10%) - Requires valid certificates
    • Mitigation: MQTT broker enforces ACLs based on certificate CN
  • Message Replay (Medium Risk)

    • No timestamp validation on received messages
    • Attack Probability: Medium (20%) - Requires MQTT access
    • Mitigation: Add timestamp validation and nonce checking
    • Impact: Duplicate payment confirmations (non-financial)
  • TLS Encryption - All MQTT traffic encrypted

  • Certificate Authentication - Only authorized clients can connect

  • QoS 1 - At-least-once delivery guarantees message receipt

Recommendations:

  1. Add timestamp validation: ```typescript const messageAge = Date.now() - new Date(payload.receivedAt).getTime() if (messageAge > 300000) { // 5 minutes throw new Error("Message too old, possible replay attack") } ```

  2. Implement nonce tracking: ```typescript const processedNonces = new Set() if (processedNonces.has(payload.nonce)) { throw new Error("Duplicate message detected") } processedNonces.add(payload.nonce) ```

6. Database Security

Implementation:

  • Row Level Security (RLS) policies on all tables
  • Service role key for server-side operations
  • Anon key for client-side read operations
  • Parameterized queries prevent SQL injection

Security Level: ⭐⭐⭐⭐⭐

Vulnerabilities:

  • Service Role Key Exposure (Critical Risk)

    • Service role key in environment variables
    • If leaked, grants full database access
    • Attack Probability: Low (5%) - Requires server compromise
    • Mitigation: Use Vercel environment variables, never commit to Git
    • Impact: Complete database compromise
  • Anonymous Read Access (Low Risk)

    • RLS policies allow anonymous users to read all records
    • Attack Probability: High (80%) - Public API endpoint
    • Mitigation: Implement user authentication and row-level filtering
    • Impact: Transaction history visible to anyone
  • SQL Injection Prevention - Supabase client uses parameterized queries

  • Connection Encryption - All database connections use TLS

  • Audit Logging - All operations logged with timestamps

Recommendations:

  1. Implement authentication: ```typescript // Add Supabase Auth const { data: { user } } = await supabase.auth.getUser() if (!user) throw new Error("Unauthorized")

// Update RLS policies CREATE POLICY "Users can only see their own transactions" ON transaction_generations FOR SELECT USING (auth.uid() = user_id); ```

  1. Rotate service role key regularly
  2. Use Vercel's encrypted environment variables

7. API Security

Implementation:

  • HTTPS enforced for all API calls
  • Client IP logging for audit trail
  • Retry logic with exponential backoff
  • Timeout protection (30 seconds)
  • Error handling without information disclosure

Security Level: ⭐⭐⭐⭐

Vulnerabilities:

  • No Rate Limiting (High Risk)

    • API endpoints have no request throttling
    • Attack Probability: High (70%) - Easy to exploit
    • Mitigation: Implement rate limiting middleware
    • Impact: DoS attacks, resource exhaustion
  • No API Authentication (Medium Risk)

    • API routes accessible without authentication
    • Attack Probability: High (80%) - Public endpoints
    • Mitigation: Add API key or JWT authentication
    • Impact: Unauthorized transaction generation
  • Verbose Error Messages (Low Risk)

    • Some error messages expose internal details
    • Attack Probability: Medium (30%) - Requires triggering errors
    • Mitigation: Generic error messages for production
    • Impact: Information disclosure aids attackers
  • HTTPS Encryption - All API traffic encrypted

  • Input Validation - All inputs validated before processing

  • Audit Logging - All API calls logged with IP and timestamp

Recommendations:

  1. Add rate limiting: ```typescript import rateLimit from 'express-rate-limit'

const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // limit each IP to 100 requests per windowMs message: "Too many requests, please try again later" })

export default limiter ```

  1. Add API authentication: ```typescript const apiKey = request.headers.get("x-api-key") if (apiKey !== process.env.API_SECRET_KEY) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } ```

  2. Generic error messages: ```typescript // Development if (process.env.NODE_ENV === "development") { return NextResponse.json({ error: error.message, stack: error.stack }) } // Production return NextResponse.json({ error: "An error occurred" }, { status: 500 }) ```

Security Scorecard

Category Score Status
Authentication ⭐⭐⭐⭐⭐ Excellent (mTLS)
Authorization ⭐⭐⭐ Needs Improvement (No user auth)
Data Encryption ⭐⭐⭐⭐⭐ Excellent (TLS everywhere)
Input Validation ⭐⭐⭐⭐ Good (Needs DOMPurify)
Data Integrity ⭐⭐⭐⭐⭐ Excellent (SHA-256 hashing)
Certificate Management ⭐⭐⭐⭐⭐ Excellent (Temporary files)
API Security ⭐⭐⭐ Needs Improvement (No rate limiting)
Database Security ⭐⭐⭐⭐ Good (Needs user auth)
Error Handling ⭐⭐⭐⭐ Good (Some verbose errors)
Audit Logging ⭐⭐⭐⭐⭐ Excellent (Comprehensive)

Overall Security Rating: ⭐⭐⭐⭐ (4/5) - Production Ready with Recommendations

Critical Vulnerabilities Summary

Vulnerability Severity Probability Impact Priority
No Rate Limiting High 70% DoS P0
No API Authentication High 80% Unauthorized Access P0
Anonymous Database Access Medium 80% Data Exposure P1
Service Role Key Exposure Critical 5% Full Compromise P1
Regex-based Sanitization Medium 15% XSS P2
MQTT Message Replay Medium 20% Duplicate Confirmations P2
Temporary File Exposure Low 5% Certificate Theft P3
Verbose Error Messages Low 30% Information Disclosure P3

Security Recommendations Priority

P0 - Immediate (Before Production):

  1. Implement rate limiting on all API routes
  2. Add API key authentication for public endpoints
  3. Implement user authentication with Supabase Auth

P1 - High Priority (Within 1 week): 4. Update RLS policies for user-specific data access 5. Rotate and secure service role key in Vercel 6. Add timestamp validation for MQTT messages

P2 - Medium Priority (Within 1 month): 7. Replace regex sanitization with DOMPurify 8. Implement nonce tracking for replay protection 9. Upgrade to HMAC-SHA256 for integrity verification

P3 - Low Priority (Within 3 months): 10. Add monitoring for temporary file access 11. Implement generic error messages for production 12. Add security headers (CSP, HSTS, etc.)

API Documentation

POST /api/generate-transaction

Generates new transaction ID from banking API using mTLS authentication.

Request: ```typescript FormData { clientCert: File | string // PEM client certificate clientKey: File | string // PEM private key caCert: File | string // CA certificate bundle iban: string // Recipient IBAN amount: string // Payment amount isProductionMode: boolean // Environment flag } ```

Response: ```json { "success": true, "data": { "transaction_id": "QR-abc123...", "created_at": "2024-01-01T12:00:00Z" }, "clientIP": "192.168.1.1", "timestamp": "2024-01-01T12:00:00Z" } ```

Security:

  • mTLS authentication required
  • Temporary certificate files (auto-cleanup)
  • Audit logging to database
  • 30-second timeout protection

POST /api/mqtt-subscribe

Subscribes to MQTT broker for real-time payment notifications.

Request: ```typescript FormData { clientCert: File | string // PEM client certificate clientKey: File | string // PEM private key caCert: File | string // CA certificate bundle transactionId: string // Transaction to monitor vatsk: string // Tax ID pokladnica: string // Cash register ID isProductionMode: boolean // Environment flag } ```

Response: ```json { "success": true, "hasMessages": true, "messages": ["payment notification JSON"], "messageCount": 1, "communicationLog": ["timestamped log entries"], "clientIP": "192.168.1.1", "listeningDuration": "5 seconds" } ```

Security:

  • MQTTS (MQTT over TLS) with client certificates
  • QoS 1 (at-least-once delivery)
  • 120-second timeout
  • Automatic database persistence

POST /api/convert-p12-to-pem

Converts PKCS#12 certificate to PEM format.

Request: ```typescript FormData { p12File: File // PKCS#12 certificate password: string // Certificate password } ```

Response: ```json { "certificate": "-----BEGIN CERTIFICATE-----...", "privateKey": "-----BEGIN PRIVATE KEY-----...", "vatsk": "1234567890" } ```

Security:

  • Password-protected certificate parsing
  • VATSK extraction from certificate subject
  • No persistent storage
  • Memory-safe certificate handling

Database Schema

transaction_generations

Audit log for all transaction generation requests.

```sql CREATE TABLE transaction_generations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), transaction_id TEXT, vatsk TEXT, pokladnica TEXT, iban TEXT, amount NUMERIC(10,2), status_code INTEGER NOT NULL, duration_ms INTEGER NOT NULL, client_ip TEXT NOT NULL, response_timestamp TIMESTAMPTZ, dispute BOOLEAN DEFAULT false, created_at TIMESTAMPTZ DEFAULT NOW() );

-- Indexes for performance CREATE INDEX idx_transaction_id ON transaction_generations(transaction_id); CREATE INDEX idx_created_at ON transaction_generations(created_at); CREATE INDEX idx_vatsk ON transaction_generations(vatsk); ```

mqtt_notifications

Storage for received payment notifications.

```sql CREATE TABLE mqtt_notifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), topic TEXT NOT NULL, raw_payload TEXT NOT NULL, vatsk TEXT, pokladnica TEXT, transaction_id TEXT, transaction_status TEXT, amount NUMERIC(10,2), currency TEXT, integrity_hash TEXT, end_to_end_id TEXT, payload_received_at TIMESTAMPTZ, integrity_validation BOOLEAN, created_at TIMESTAMPTZ DEFAULT NOW() );

-- Indexes for performance CREATE INDEX idx_transaction_id_notif ON mqtt_notifications(transaction_id); CREATE INDEX idx_created_at_notif ON mqtt_notifications(created_at); CREATE INDEX idx_vatsk_notif ON mqtt_notifications(vatsk); ```

mqtt_subscriptions

Tracking for MQTT subscription attempts.

```sql CREATE TABLE mqtt_subscriptions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), topic TEXT NOT NULL, vatsk TEXT, pokladnica TEXT, end_to_end_id TEXT, qos INTEGER NOT NULL, timestamp TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW() );

-- Indexes for performance CREATE INDEX idx_topic ON mqtt_subscriptions(topic); CREATE INDEX idx_created_at_sub ON mqtt_subscriptions(created_at); ```

Deployment

Vercel Deployment

  1. Connect Repository ```bash

    Push code to GitHub

    git add . git commit -m "Initial commit" git push origin main ```

  2. Import to Vercel

    • Go to Vercel Dashboard
    • Click "Add New..." → "Project"
    • Import your GitHub repository
    • Vercel auto-detects Next.js configuration
  3. Configure Environment Variables

    • In Vercel project settings → Environment Variables
    • Add all variables from .env.local:
      • NEXT_PUBLIC_SUPABASE_URL
      • NEXT_PUBLIC_SUPABASE_ANON_KEY
      • SUPABASE_SERVICE_ROLE_KEY
      • NEXT_PUBLIC_EMBEDDED_CA_BUNDLE
      • NEXT_PUBLIC_EMBEDDED_CA_BUNDLE_PROD
  4. Deploy

    • Click "Deploy"
    • Wait 2-3 minutes for build
    • Application available at https://your-project.vercel.app

Custom Domain

  1. In Vercel project → Settings → Domains
  2. Add your custom domain
  3. Configure DNS records as instructed
  4. SSL certificate automatically provisioned

Environment-Specific Deployments

```bash

Production

vercel --prod

Preview (staging)

vercel

Development

vercel dev ```

Troubleshooting

Certificate Issues

Problem: "Failed to convert P12 to PEM"

  • Cause: Incorrect password or corrupted certificate
  • Solution: Verify password, re-export certificate from bank

Problem: "No certificate found in P12 file"

  • Cause: Invalid P12 format or missing certificate
  • Solution: Ensure P12 contains both certificate and private key

API Connection Issues

Problem: "Forbidden" response from banking API

  • Cause: Invalid CA certificate bundle or wrong environment
  • Solution:
    1. Verify CA bundle contains only intermediate + root CA (not server cert)
    2. Ensure using correct environment (TEST vs PRODUCTION)
    3. Check certificate expiration date

Problem: "Connection timeout"

  • Cause: Network issues or incorrect API endpoint
  • Solution:
    1. Verify internet connection
    2. Check firewall settings
    3. Confirm API endpoint URL

MQTT Issues

Problem: "MQTT connection failed"

  • Cause: Invalid certificates or broker unreachable
  • Solution:
    1. Verify certificates are valid
    2. Check MQTT broker hostname (mqtt-i.kverkom.sk for TEST)
    3. Ensure port 8883 is not blocked

Problem: "No messages received"

  • Cause: Payment not completed or wrong topic
  • Solution:
    1. Verify payment was authorized in banking app
    2. Check VATSK and POKLADNICA are correct
    3. Wait full 120-second timeout period

Database Issues

Problem: "Missing Supabase configuration"

  • Cause: Environment variables not set
  • Solution: Verify .env.local contains all Supabase credentials

Problem: "Database insert failed"

  • Cause: RLS policies or schema mismatch
  • Solution:
    1. Verify RLS policies are created
    2. Check table schema matches migrations
    3. Confirm service role key is correct

Build Issues

Problem: "Module not found" errors

  • Cause: Missing dependencies
  • Solution: npm install or npm ci

Problem: "Type errors" during build

  • Cause: TypeScript configuration or missing types
  • Solution: npm run type-check to identify issues

Support

License

This project is licensed under the MIT License - see LICENSE file for details.

Acknowledgments

  • Slovak Banking Association for Payment Link Standard v1.3
  • Vercel for Next.js framework and hosting
  • Supabase for database infrastructure
  • shadcn/ui for component library

Built with ❤️ using Vercel v0 | GitHub

About

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •