UPI Payments

Process UPI (Unified Payments Interface) payments through the Host-to-Host API for instant, real-time transactions in the Indian market with 24/7 availability.

Overview

UPI payment processing provides:
  • Instant Transfers: Real-time payment processing
  • 24/7 Availability: Round-the-clock payment processing
  • Mobile Optimized: Designed for mobile-first experience
  • UPI ID Validation: Automatic UPI ID format validation
  • Low Fees: Cost-effective payment processing
  • Bank Integration: Direct integration with Indian banks

Required Parameters

UPI-Specific Fields

ParameterDescriptionRequiredExample
upiIdUPI identifierYES”user@paytm”
nameCustomer full nameYES”Rajesh Kumar”

Customer Information

ParameterDescriptionRequiredExample
emailCustomer email addressYESrajesh@example.com
phoneNumberCustomer phone numberYES”+919876543210”
addressCustomer addressYES”123 MG Road”
cityCustomer cityYES”Mumbai”
stateState or provinceYES”Maharashtra”
postalCodePIN codeYES”400001”
countryCountry code (IN for India)YES”IN”

Transaction Details

ParameterDescriptionRequiredExample
amountPayment amountYES1500.00
unitCurrency code (INR)YES”INR”
originDomainMerchant domainYES”shop.example.com”
referenceIdMerchant referenceNO”UPI-12345”

Complete Request Example

{
  "name": "Rajesh Kumar",
  "upiId": "rajesh@paytm",
  "email": "rajesh@example.com",
  "phoneNumber": "+919876543210",
  "address": "123 MG Road",
  "city": "Mumbai",
  "state": "Maharashtra",
  "postalCode": "400001",
  "country": "IN",
  "amount": 1500.00,
  "unit": "INR",
  "originDomain": "shop.example.com",
  "referenceId": "UPI-12345",
  "notifyUrl": "https://api.example.com/webhook",
  "successUrl": "https://shop.example.com/success",
  "failureUrl": "https://shop.example.com/failure",
  "browserInfo": {
    "browserAcceptHeader": "application/json, text/plain, */*",
    "browserColorDepth": "24",
    "browserIP": "103.21.58.66",
    "browserJavaEnabled": false,
    "browserJavascriptEnabled": true,
    "browserLanguage": "en-IN",
    "browserScreenHeight": "1080",
    "browserScreenWidth": "1920",
    "browserTZ": "330",
    "browserUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
  }
}

Implementation Example

JavaScript/Node.js

async function processUPIPayment(paymentData) {
  const apiEndpoint = process.env.YONOBI_H2H_ENDPOINT;
  const apiKey = process.env.YONOBI_API_KEY;
  
  try {
    const response = await fetch(apiEndpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': apiKey
      },
      body: JSON.stringify({
        // UPI specific
        name: paymentData.customerName,
        upiId: paymentData.upiId,
        
        // Customer info
        email: paymentData.customerEmail,
        phoneNumber: paymentData.customerPhone,
        address: paymentData.customerAddress.street,
        city: paymentData.customerAddress.city,
        state: paymentData.customerAddress.state,
        postalCode: paymentData.customerAddress.postalCode,
        country: paymentData.customerAddress.country,
        
        // Transaction
        amount: paymentData.amount,
        unit: paymentData.currency,
        originDomain: paymentData.merchantDomain,
        referenceId: paymentData.orderId,
        
        // URLs
        notifyUrl: paymentData.webhookUrl,
        successUrl: paymentData.successUrl,
        failureUrl: paymentData.failureUrl,
        
        // Browser info for enhanced security
        browserInfo: paymentData.browserInfo
      })
    });
    
    const result = await response.json();
    
    if (response.ok) {
      return {
        success: true,
        paymentRequestId: result.paymentRequestId,
        redirectUrl: result.redirectUrl,
        status: result.status
      };
    } else {
      return {
        success: false,
        error: result.error,
        message: result.message
      };
    }
  } catch (error) {
    return {
      success: false,
      error: 'NETWORK_ERROR',
      message: error.message
    };
  }
}

Python

import requests
import json
import os

def process_upi_payment(payment_data):
    api_endpoint = os.getenv('YONOBI_H2H_ENDPOINT')
    api_key = os.getenv('YONOBI_API_KEY')
    
    headers = {
        'Content-Type': 'application/json',
        'X-API-Key': api_key
    }
    
    request_data = {
        # UPI specific
        'name': payment_data['customer_name'],
        'upiId': payment_data['upi_id'],
        
        # Customer info
        'email': payment_data['customer_email'],
        'phoneNumber': payment_data['customer_phone'],
        'address': payment_data['customer_address']['street'],
        'city': payment_data['customer_address']['city'],
        'state': payment_data['customer_address']['state'],
        'postalCode': payment_data['customer_address']['postal_code'],
        'country': payment_data['customer_address']['country'],
        
        # Transaction
        'amount': payment_data['amount'],
        'unit': payment_data['currency'],
        'originDomain': payment_data['merchant_domain'],
        'referenceId': payment_data['order_id'],
        
        # URLs
        'notifyUrl': payment_data['webhook_url'],
        'successUrl': payment_data['success_url'],
        'failureUrl': payment_data['failure_url'],
        
        # Browser info
        'browserInfo': payment_data['browser_info']
    }
    
    try:
        response = requests.post(api_endpoint, headers=headers, json=request_data)
        result = response.json()
        
        if response.status_code == 200:
            return {
                'success': True,
                'payment_request_id': result['paymentRequestId'],
                'redirect_url': result.get('redirectUrl'),
                'status': result['status']
            }
        else:
            return {
                'success': False,
                'error': result.get('error', 'UNKNOWN_ERROR'),
                'message': result.get('message', 'UPI payment processing failed')
            }
    except requests.RequestException as e:
        return {
            'success': False,
            'error': 'NETWORK_ERROR',
            'message': str(e)
        }

UPI ID Validation

Valid UPI ID Formats

  • Format: username@bankcode
  • Examples:
    • user@paytm
    • 9876543210@ybl
    • john.doe@oksbi
    • mobile@paytm

UPI ID Validation Function

function validateUPIId(upiId) {
  // UPI ID format: username@bankcode
  const upiRegex = /^[a-zA-Z0-9.\-_]{2,256}@[a-zA-Z][a-zA-Z0-9.\-_]{2,64}$/;
  
  if (!upiRegex.test(upiId)) {
    return {
      valid: false,
      error: 'Invalid UPI ID format'
    };
  }
  
  const [username, bankCode] = upiId.split('@');
  
  // Check username length
  if (username.length < 2 || username.length > 256) {
    return {
      valid: false,
      error: 'Username must be between 2-256 characters'
    };
  }
  
  // Check bank code
  if (bankCode.length < 3 || bankCode.length > 64) {
    return {
      valid: false,
      error: 'Bank code must be between 3-64 characters'
    };
  }
  
  return {
    valid: true,
    username: username,
    bankCode: bankCode
  };
}

Payment Flow

1. UPI Payment Initiation

// Validate UPI ID first
const upiValidation = validateUPIId(paymentData.upiId);
if (!upiValidation.valid) {
  throw new Error(upiValidation.error);
}

// Process UPI payment
const paymentResult = await processUPIPayment({
  customerName: 'Rajesh Kumar',
  upiId: 'rajesh@paytm',
  customerEmail: 'rajesh@example.com',
  customerPhone: '+919876543210',
  customerAddress: {
    street: '123 MG Road',
    city: 'Mumbai',
    state: 'Maharashtra',
    postalCode: '400001',
    country: 'IN'
  },
  amount: 1500.00,
  currency: 'INR',
  merchantDomain: 'shop.example.com',
  orderId: 'UPI-12345',
  webhookUrl: 'https://api.example.com/webhook',
  successUrl: 'https://shop.example.com/success',
  failureUrl: 'https://shop.example.com/failure',
  browserInfo: collectBrowserInfo()
});

2. Handle UPI Response

if (paymentResult.success) {
  if (paymentResult.redirectUrl) {
    // Redirect to UPI app or payment page
    window.location.href = paymentResult.redirectUrl;
  } else {
    // Payment initiated successfully
    showPaymentPending(paymentResult.paymentRequestId);
  }
} else {
  // Handle UPI payment error
  displayUPIError(paymentResult.message);
}

Major UPI Apps

ProviderBank CodeExample UPI ID
Paytm@paytmuser@paytm
Google Pay@okaxis, @okhdfcbankuser@okaxis
PhonePe@ybl, @ibluser@ybl
Amazon Pay@apluser@apl
BHIM@upiuser@upi

Bank UPI Handles

BankUPI HandleExample
SBI@sbiuser@sbi
HDFC@hdfcbankuser@hdfcbank
ICICI@iciciuser@icici
Axis Bank@axisbankuser@axisbank
Kotak@kotakuser@kotak

Error Handling

Common UPI Error Codes

  • INVALID_UPI_ID: UPI ID format is invalid
  • UPI_ID_NOT_FOUND: UPI ID does not exist
  • INSUFFICIENT_FUNDS: Insufficient balance in UPI account
  • UPI_DECLINED: Transaction declined by UPI provider
  • UPI_TIMEOUT: UPI transaction timeout
  • DAILY_LIMIT_EXCEEDED: Daily transaction limit exceeded

Error Response Example

{
  "success": false,
  "error": "UPI_DECLINED",
  "message": "Transaction declined by UPI provider",
  "code": "U001",
  "details": {
    "declineReason": "Invalid UPI PIN",
    "upiResponse": "U30"
  }
}

Transaction Limits

UPI Transaction Limits

  • Per Transaction: ₹1,00,000 (1 Lakh INR)
  • Daily Limit: ₹1,00,000 (1 Lakh INR)
  • Monthly Limit: ₹20,00,000 (20 Lakh INR)
  • Minimum Amount: ₹1 (1 INR)
Limits may vary by bank and UPI provider. Always check with the specific provider for current limits.

Security Features

UPI Security

  • Two-Factor Authentication: UPI PIN + device authentication
  • Encrypted Communication: End-to-end encryption
  • Device Binding: UPI apps are bound to specific devices
  • Transaction Limits: Built-in transaction limits for security

Implementation Security

// Secure UPI payment processing
function secureUPIPayment(paymentData) {
  // Validate UPI ID format
  if (!validateUPIId(paymentData.upiId).valid) {
    throw new Error('Invalid UPI ID');
  }
  
  // Sanitize input data
  const sanitizedData = {
    ...paymentData,
    upiId: paymentData.upiId.toLowerCase().trim(),
    amount: parseFloat(paymentData.amount).toFixed(2)
  };
  
  // Check amount limits
  if (sanitizedData.amount > 100000) {
    throw new Error('Amount exceeds UPI transaction limit');
  }
  
  return processUPIPayment(sanitizedData);
}

Testing

Test UPI IDs

For testing purposes, use these test UPI IDs:
  • Success: success@paytm
  • Failure: failure@paytm
  • Timeout: timeout@paytm
  • Insufficient Funds: insufficient@paytm

Test Scenarios

// Test successful UPI payment
const testPayment = {
  customerName: 'Test User',
  upiId: 'success@paytm',
  customerEmail: 'test@example.com',
  customerPhone: '+919876543210',
  amount: 100.00,
  currency: 'INR'
};

Best Practices

Implementation

  1. UPI ID Validation: Always validate UPI ID format
  2. Amount Validation: Check transaction limits
  3. Mobile Optimization: Optimize for mobile devices
  4. Real-time Status: Provide real-time payment status

User Experience

  1. UPI App Integration: Deep link to UPI apps when possible
  2. QR Code Option: Provide QR code for easy scanning
  3. Clear Instructions: Provide clear payment instructions
  4. Status Updates: Keep users informed of payment progress

Compliance

  1. RBI Guidelines: Follow Reserve Bank of India guidelines
  2. Data Protection: Protect customer financial data
  3. Transaction Records: Maintain proper transaction records
  4. Audit Trail: Keep audit trail of all UPI transactions

Next Steps

Google Pay Integration

Learn about Google Pay payment integration

Payment Status

Track UPI payment status

Webhooks

Handle UPI payment notifications