- Overview
- Features
- Prerequisites
- Installation
- Configuration
- Usage
- Architecture
- Security
- API Documentation
- Database Schema
- Deployment
- Troubleshooting
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.
- 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
- 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
- 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)
- 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
- 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
```bash git clone https://github.com/your-username/nop-web-test-client.git cd nop-web-test-client ```
```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
- Go to Supabase Dashboard
- Click "New Project"
- Enter project details:
- Name: nop-client (or your preferred name)
- Database Password: Strong password (save securely!)
- Region: Europe West (recommended for Slovakia)
- Click "Create new project" and wait 2-3 minutes
Execute SQL scripts in order using Supabase SQL Editor:
Step 1: Clean Database (Optional - only if starting fresh) ```bash
```
Step 2: Create transaction_generations Table ```bash
```
Step 3: Create mqtt_notifications Table ```bash
```
Step 4: Create mqtt_subscriptions Table ```bash
```
In Supabase Dashboard → Table Editor, confirm these tables exist:
transaction_generations- Transaction generation audit logmqtt_notifications- Payment notification storagemqtt_subscriptions- MQTT subscription tracking
Create .env.local file in project root:
```env
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
NEXT_PUBLIC_EMBEDDED_CA_BUNDLE=-----BEGIN CERTIFICATE----- MIIFazCCBFOgAwIBAgIQBN... (Complete CA certificate chain for api-banka-i.kverkom.sk) ... -----END CERTIFICATE-----
NEXT_PUBLIC_EMBEDDED_CA_BUNDLE_PROD=-----BEGIN CERTIFICATE----- MIIFazCCBFOgAwIBAgIQBN... (Complete CA certificate chain for api-banka.kverkom.sk) ... -----END CERTIFICATE----- ```
- In Supabase Dashboard, go to Settings → API
- Copy these values:
- Project URL →
NEXT_PUBLIC_SUPABASE_URL - anon public key →
NEXT_PUBLIC_SUPABASE_ANON_KEY - service_role key →
SUPABASE_SERVICE_ROLE_KEY
- Project URL →
CA certificates are required for TLS verification with banking APIs.
For TEST Environment (api-banka-i.kverkom.sk):
- Visit crt.sh
- Search for:
api-banka-i.kverkom.sk - Download certificate chain (intermediate + root CA)
- Convert to PEM format if needed
- Add to
NEXT_PUBLIC_EMBEDDED_CA_BUNDLE
For PRODUCTION Environment (api-banka.kverkom.sk):
- Visit crt.sh
- Search for:
api-banka.kverkom.sk - Download certificate chain (intermediate + root CA)
- Convert to PEM format if needed
- Add to
NEXT_PUBLIC_EMBEDDED_CA_BUNDLE_PROD
Important: CA bundle should contain ONLY intermediate and root CA certificates, NOT the server certificate.
```bash npm run dev ```
Application runs at http://localhost:3000
```bash npm run build npm start ```
- XML Authentication Data: Upload your PKCS#12 certificate in XML format
- Certificate Password: Enter the password for your certificate
- CA Certificate: Upload the CA certificate bundle (if not using embedded)
- 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
- IBAN: Enter recipient's IBAN (auto-formatted with spaces)
- Amount: Enter payment amount in EUR (auto-formatted)
- Environment: Toggle between TEST and PRODUCTION
- Click Generate QR Code
- 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
- Customer scans QR code with banking app
- Customer authorizes payment
- Application receives MQTT notification
- Payment integrity verified using SHA-256 hash
- Confirmation modal displayed with payment details
- Click Transaction List
- Select date range
- View all transactions with amounts and statuses
- Print summary or detailed report
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)
```
- User uploads certificates → Certificate conversion (P12 to PEM)
- User enters payment details → Input validation and sanitization
- User generates QR → API call to banking system (mTLS)
- Banking API returns transaction ID → QR code generation
- Automatic MQTT subscription → Listen for payment confirmation
- Customer pays → Bank sends MQTT notification
- Application receives notification → Integrity verification
- Display confirmation → Save to database ```
``` ┌─────────────────┐ │ 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 │ └─────────────┘ └──────────────┘ └──────────────┘ ```
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
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
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
/tmpdirectory - 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
- Files written to
-
✅ 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
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) ```
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) ```
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
- Topic format:
-
❌ 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:
-
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") } ```
-
Implement nonce tracking: ```typescript const processedNonces = new Set() if (processedNonces.has(payload.nonce)) { throw new Error("Duplicate message detected") } processedNonces.add(payload.nonce) ```
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:
- 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); ```
- Rotate service role key regularly
- Use Vercel's encrypted environment variables
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:
- 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 ```
-
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 }) } ```
-
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 }) ```
| 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
| 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 |
P0 - Immediate (Before Production):
- Implement rate limiting on all API routes
- Add API key authentication for public endpoints
- 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.)
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
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
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
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); ```
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); ```
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); ```
-
Connect Repository ```bash
git add . git commit -m "Initial commit" git push origin main ```
-
Import to Vercel
- Go to Vercel Dashboard
- Click "Add New..." → "Project"
- Import your GitHub repository
- Vercel auto-detects Next.js configuration
-
Configure Environment Variables
- In Vercel project settings → Environment Variables
- Add all variables from
.env.local:NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEYNEXT_PUBLIC_EMBEDDED_CA_BUNDLENEXT_PUBLIC_EMBEDDED_CA_BUNDLE_PROD
-
Deploy
- Click "Deploy"
- Wait 2-3 minutes for build
- Application available at
https://your-project.vercel.app
- In Vercel project → Settings → Domains
- Add your custom domain
- Configure DNS records as instructed
- SSL certificate automatically provisioned
```bash
vercel --prod
vercel
vercel dev ```
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
Problem: "Forbidden" response from banking API
- Cause: Invalid CA certificate bundle or wrong environment
- Solution:
- Verify CA bundle contains only intermediate + root CA (not server cert)
- Ensure using correct environment (TEST vs PRODUCTION)
- Check certificate expiration date
Problem: "Connection timeout"
- Cause: Network issues or incorrect API endpoint
- Solution:
- Verify internet connection
- Check firewall settings
- Confirm API endpoint URL
Problem: "MQTT connection failed"
- Cause: Invalid certificates or broker unreachable
- Solution:
- Verify certificates are valid
- Check MQTT broker hostname (mqtt-i.kverkom.sk for TEST)
- Ensure port 8883 is not blocked
Problem: "No messages received"
- Cause: Payment not completed or wrong topic
- Solution:
- Verify payment was authorized in banking app
- Check VATSK and POKLADNICA are correct
- Wait full 120-second timeout period
Problem: "Missing Supabase configuration"
- Cause: Environment variables not set
- Solution: Verify
.env.localcontains all Supabase credentials
Problem: "Database insert failed"
- Cause: RLS policies or schema mismatch
- Solution:
- Verify RLS policies are created
- Check table schema matches migrations
- Confirm service role key is correct
Problem: "Module not found" errors
- Cause: Missing dependencies
- Solution:
npm installornpm ci
Problem: "Type errors" during build
- Cause: TypeScript configuration or missing types
- Solution:
npm run type-checkto identify issues
- Documentation: functional-documentation.md
- Issues: GitHub Issues
- Banking API: Contact your bank's technical support
- Supabase: Supabase Documentation
This project is licensed under the MIT License - see LICENSE file for details.
- 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