In the UPI payments ecosystem, transactions are commonly initiated via UPI Collect or UPI Intent. Understanding the architectural differences between these mechanisms is essential for building reliable payment workflows.
UPI Collect vs UPI Intent
- UPI Collect: Dispatches a payment request notification to the customer's VPA. The user must switch apps, find the notification, and authorize the request before it expires.
- UPI Intent: Employs standard mobile deep links (upi://pay?...) that automatically launch installed UPI apps with the payee address and transaction amount pre-populated. This eliminates manual VPA entry and improves conversion rates.
The Merchant Tokens Database Structure
UPIGateway.dev stores merchant configuration records in the merchant_tokens table inside Supabase. This structure isolates credentials per merchant account with Row Level Security (RLS) enforcement:
-- Merchant Gateway Credentials Schema (Supabase)
CREATE TABLE public.merchant_tokens (
id SERIAL PRIMARY KEY,
user_token VARCHAR(255) NOT NULL,
gateway VARCHAR(50) NOT NULL, -- 'paytm', 'phonepe', 'bharatpe', 'googlepay'
number VARCHAR(50), -- Registered merchant mobile
mid VARCHAR(100), -- Merchant identifier
upi_id VARCHAR(100) NOT NULL, -- Bank-linked UPI VPA for funds routing
is_active BOOLEAN DEFAULT TRUE,
credentials JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW()
);
Automated Status Verification and IMAP Poller
To confirm payment without requiring custom SDK installations on customer devices, UPIGateway.dev utilizes dual verification channels: direct status API polling against supported gateway endpoints, complemented by an SSL IMAP listener (Port 993) that parses official transaction credit notifications in real-time.
Anti-Replay and UTR Integrity Guards
To protect merchants against fraud, the verification pipeline enforces strict anti-replay validation. Every confirmed 12-digit UTR is checked against existing completed orders in the database. If a customer or script attempts to resubmit a previously utilized UTR, the request is flagged and blocked.