UPI Omnichannel S2S Integration
This section describes how to integrate UPI for Omnichannel with S2S integration:
1. Initiate Payment
Initiate the UPI Omnichannel payment request with required parameters
2. Check UPI Transaction Status
Monitor and check the real-time status of the UPI transaction
3. PayU Sends S2S Call Back Response
Receive and handle the server-to-server callback response from PayU
4. Verify the payment
Verify the payment status and ensure successful transaction completion
Before you begin:Register for an account with PayU before you start integration. For more information, refer to Register for a Merchant Account.
Step 1: Initiate payment
Environment
| Test Environment | https://test.payu.in/_payment | 
| Production Environment | https://secure.payu.in/_payment | 
The Omni Channel API allows you to call the service request using the specific bank codes.
Post the initiatePayment API to initiate payment with all the required parameters as in the following Parameters table.
Request parameters
For the complete list of parameters, refer to UPI Collection – S2S.
| Parameter | Description | Example | 
|---|---|---|
| key | 
 | Your Test Key | 
| api_version | 
 | 1 | 
| txnid | 
 | s7hhDQVWvbhBdN | 
| amount | 
 | 10.00 | 
| productinfo | 
 | iPhone | 
| email | 
 | |
| phone | 
 | 9876543210 | 
| surl | String Success URL(surl) – It must contain the URL on which PayU will redirect the final response if the transaction is successful. | |
| furl | 
 | |
| pg  | 
 | UPI | 
| bankcode | 
 | INTENT | 
| txn_s2s_flow | 
 | 4 | 
| firstname | 
 | Ashish | 
| lastname | 
 | Verma | 
| address1 | 
 | H.No- 17, Block C, Kalyan Bldg, Khardilkar Road, Mumbai | 
| address2 | 
 | 34 Saikripa-Estate, Tilak Nagar | 
| city | 
 | Mumbai | 
| state | 
 | Maharashtra | 
| country | 
 | India | 
| zipcode | 
 | 400004 | 
| hash | 
 | eabec285da28fd 0e3054d41a4d24fe 9f7599c9d0b6664 6f7a9984303fd612 4044b6206daf831 e9a8bda28a6200d 318293a13d6c193 109b60bd4b4f8b09 c90972 | 
| udf1 | 
 | Payment Preference | 
| udf2 | 
 | Shipping Method | 
| udf3 | 
 | Shipping Address1 | 
| udf4 | 
 | Shipping City | 
| udf5 | 
 | Shipping Zip Code | 
|  s2s_client_ip | 
 | |
| s2s_device_info | 
 | |
| upiAppName | For Specific Intent, merchant should share the app name which is selected by customer on the merchant check-out page. The following are the enum's expected for major apps: | |
| vpa | 
 | 8800411088@upi | 
This needs to be a server-to-server curl call request. This API is used for both Cards and UPI for generating a new transaction.
If specific intent has to be opened instead of Generic Intent, the bankcode values will change accordingly as listed in the following table:
| App/Mode | bankcode | 
|---|---|
| Omnichannel Flow | TEZOMNI | 
| Generic Intent | INTENT | 
| GPay | TEZ | 
| PhonePe | PPINTENT | 
Note: User VPA is not required for this flow. The different parameters and their descriptions are in the following table.
Understanding Hashing and sample code
Hashing
You must hash the request parameters using the following hash logic:
sha512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||SALT)For more information, refer to Generate Hash.
Hashing Sample Code
<?php
function generateHash($params, $salt) {
    // Extract parameters or use empty string if not provided
    $key = $params['key'];
    $txnid = $params['txnid'];
    $amount = $params['amount'];
    $productinfo = $params['productinfo'];
    $firstname = $params['firstname'];
    $email = $params['email'];
    $udf1 = isset($params['udf1']) ? $params['udf1'] : '';
    $udf2 = isset($params['udf2']) ? $params['udf2'] : '';
    $udf3 = isset($params['udf3']) ? $params['udf3'] : '';
    $udf4 = isset($params['udf4']) ? $params['udf4'] : '';
    $udf5 = isset($params['udf5']) ? $params['udf5'] : '';
    
    // Construct hash string with exact parameter sequence
    $hashString = $key . '|' . $txnid . '|' . $amount . '|' . $productinfo . '|' . 
                  $firstname . '|' . $email . '|' . $udf1 . '|' . $udf2 . '|' . 
                  $udf3 . '|' . $udf4 . '|' . $udf5 . '||||||' . $salt;
    
    // Generate hash and convert to lowercase
    return strtolower(hash('sha512', $hashString));
}
// Example usage
$params = [
    'key' => 'yourKey',
    'txnid' => 'yourTxnId',
    'amount' => 'yourAmount',
    'productinfo' => 'yourProductInfo',
    'firstname' => 'yourFirstName',
    'email' => 'yourEmail',
    'udf1' => 'optional_value1'
    // udf2, udf3, udf4, udf5 not provided - will be empty strings
];
$salt = 'yourSalt';
$hash = generateHash($params, $salt);
echo 'Generated Hash: ' . $hash;
?>
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
public class ImprovedHashGenerator {
    public static String generateHash(Map<String, String> params, String salt) {
        // Extract parameters or use empty string if not provided
        String key = params.get("key");
        String txnid = params.get("txnid");
        String amount = params.get("amount");
        String productinfo = params.get("productinfo");
        String firstname = params.get("firstname");
        String email = params.get("email");
        String udf1 = params.getOrDefault("udf1", "");
        String udf2 = params.getOrDefault("udf2", "");
        String udf3 = params.getOrDefault("udf3", "");
        String udf4 = params.getOrDefault("udf4", "");
        String udf5 = params.getOrDefault("udf5", "");
        
        // Construct hash string with exact parameter sequence
        String hashString = key + "|" + txnid + "|" + amount + "|" + productinfo + "|" + 
                         firstname + "|" + email + "|" + udf1 + "|" + udf2 + "|" + 
                         udf3 + "|" + udf4 + "|" + udf5 + "||||||" + salt;
        
        return sha512(hashString);
    }
    private static String sha512(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString().toLowerCase();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        // Example usage with parameters map
        Map<String, String> params = new HashMap<>();
        params.put("key", "yourKey");
        params.put("txnid", "yourTxnId");
        params.put("amount", "yourAmount");
        params.put("productinfo", "yourProductInfo");
        params.put("firstname", "yourFirstName");
        params.put("email", "yourEmail");
        params.put("udf1", "optional_value1");
        // udf2, udf3, udf4, udf5 not provided - will be empty strings
        
        String salt = "yourSalt";
        String hash = generateHash(params, salt);
        System.out.println("Generated Hash: " + hash);
    }
}
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
public class ImprovedHashGenerator
{
    public static string GenerateHash(Dictionary<string, string> parameters, string salt)
    {
        // Extract parameters or use empty string if not provided
        string key = parameters["key"];
        string txnid = parameters["txnid"];
        string amount = parameters["amount"];
        string productinfo = parameters["productinfo"];
        string firstname = parameters["firstname"];
        string email = parameters["email"];
        
        // Get UDF values if present, otherwise use empty string
        string udf1 = parameters.ContainsKey("udf1") ? parameters["udf1"] : "";
        string udf2 = parameters.ContainsKey("udf2") ? parameters["udf2"] : "";
        string udf3 = parameters.ContainsKey("udf3") ? parameters["udf3"] : "";
        string udf4 = parameters.ContainsKey("udf4") ? parameters["udf4"] : "";
        string udf5 = parameters.ContainsKey("udf5") ? parameters["udf5"] : "";
        
        // Construct hash string with exact parameter sequence
        string hashString = $"{key}|{txnid}|{amount}|{productinfo}|{firstname}|{email}|{udf1}|{udf2}|{udf3}|{udf4}|{udf5}||||||{salt}";
        
        return Sha512(hashString);
    }
    private static string Sha512(string input)
    {
        using (SHA512 sha512 = SHA512.Create())
        {
            byte[] bytes = sha512.ComputeHash(Encoding.UTF8.GetBytes(input));
            StringBuilder sb = new StringBuilder();
            foreach (byte b in bytes)
            {
                sb.Append(b.ToString("x2"));
            }
            return sb.ToString().ToLower();
        }
    }
    public static void Main(string[] args)
    {
        // Example usage with parameters dictionary
        Dictionary<string, string> parameters = new Dictionary<string, string>
        {
            ["key"] = "yourKey",
            ["txnid"] = "yourTxnId",
            ["amount"] = "yourAmount",
            ["productinfo"] = "yourProductInfo",
            ["firstname"] = "yourFirstName",
            ["email"] = "yourEmail",
            ["udf1"] = "optional_value1"
            // udf2, udf3, udf4, udf5 not provided - will be empty strings
        };
        
        string salt = "yourSalt";
        string hash = GenerateHash(parameters, salt);
        Console.WriteLine("Generated Hash: " + hash);
    }
}import hashlib
def generate_hash(params, salt):
    # Extract parameters or use empty string if not provided
    key = params['key']
    txnid = params['txnid']
    amount = params['amount']
    productinfo = params['productinfo']
    firstname = params['firstname']
    email = params['email']
    udf1 = params.get('udf1', '')
    udf2 = params.get('udf2', '')
    udf3 = params.get('udf3', '')
    udf4 = params.get('udf4', '')
    udf5 = params.get('udf5', '')
    
    # Construct hash string with exact parameter sequence
    hash_string = f"{key}|{txnid}|{amount}|{productinfo}|{firstname}|{email}|{udf1}|{udf2}|{udf3}|{udf4}|{udf5}||||||{salt}"
    
    # Generate SHA-512 hash
    return hashlib.sha512(hash_string.encode('utf-8')).hexdigest()
# Example usage
params = {
    'key': 'yourKey',
    'txnid': 'yourTxnId',
    'amount': 'yourAmount',
    'productinfo': 'yourProductInfo',
    'firstname': 'yourFirstName',
    'email': 'yourEmail',
    'udf1': 'optional_value1'
    # udf2, udf3, udf4, udf5 not provided - will default to empty strings
}
salt = 'yourSalt'
hash_value = generate_hash(params, salt)
print("Generated Hash:", hash_value)
const crypto = require('crypto');
function generateHash(params, salt) {
    // Extract parameters or use empty string if not provided
    const key = params.key;
    const txnid = params.txnid;
    const amount = params.amount;
    const productinfo = params.productinfo;
    const firstname = params.firstname;
    const email = params.email;
    const udf1 = params.udf1 || '';
    const udf2 = params.udf2 || '';
    const udf3 = params.udf3 || '';
    const udf4 = params.udf4 || '';
    const udf5 = params.udf5 || '';
    
    // Construct hash string with exact parameter sequence
    const hashString = `${key}|${txnid}|${amount}|${productinfo}|${firstname}|${email}|${udf1}|${udf2}|${udf3}|${udf4}|${udf5}||||||${salt}`;
    
    // Generate SHA-512 hash
    return crypto.createHash('sha512').update(hashString).digest('hex');
}
// Example usage
const params = {
    key: 'yourKey',
    txnid: 'yourTxnId',
    amount: 'yourAmount',
    productinfo: 'yourProductInfo',
    firstname: 'yourFirstName',
    email: 'yourEmail',
    udf1: 'optional_value1'
    // udf2, udf3, udf4, udf5 not provided - will default to empty strings
};
const salt = 'yourSalt';
const hash = generateHash(params, salt);
console.log("Generated Hash:", hash);
Collect the response in the UPI Collection - S2S under API Reference. The response for the S2S payment request is not similar to Merchant Hosted or PayU Hosted Checkout. For description of response parameters, refer to Additional Info for Payment APIs .
Step 2: Check UPI transaction status
After receiving a successful response from the above API, the need to check the status of the transaction using the **Verify Payment **API. Web services can be accessed by making a server to server call on the following PayU URLs. For a sample request or response, refer to Verify Payment APIunder API Reference.
Step 3: PayU sends S2S callback response
PayU can also send a server-to-server callback response whenever the transaction status gets updated.
Implementation
The server to server response would be sent by PayU on a pre-set URL, which has to be provided by the merchant. PayU will configure it at the back-end for the merchant.
This response would be sent in key/value pair separated by the ampersand (&) character. In case any parameter is empty or not used, PayU will send it back to the merchant with an empty string.
Sample response
unmappedstatus=success&phone=9999999999&txnid=FCDA1R100870163781&hash=84e3 35094bbcb2ddaa0f9a488eb338e143b273765d89c9dfa502402562d0b6f3c7935e28194ca92f7 380be7c84c3695415b106dcf52cb016a15fcf6adc98d724&status=success&curl=https://www. abc.in/payment/handlepayuresposne&firstname=NA&card_no=519619XXXXXX5049&furl= https://www.abc.in/payment/handlepayuresposne&productinfo=2&mode=DC&amount=800.  00&field4=6807112311042810&field3=6807112311042810&field2=838264&field9=SUCC ESS&email=NA&mihpayid=175477248&surl=https://www.ABC.in/payment/handlepayuresp osne&card_hash=9e88cb0573d4a826b61d808c0a870ed4a990682459b0ec9e95ea421e8e47b e8c&field1=42812 The parameter list includes:
mihpayid, mode, status, key, txnid, amount, productinfo, firstname, lastname, address1, address2, cit y, state, country, zipcode, email, phone, udf1, udf2, udf3, udf4, udf5, udf6, udf7, udf8, udf9, udf10, car d_token,card_no, field0, field1, field2, field3, field4, field5, field6, field7, field8, field9, offer, discou nt, offer_availed,unmappedstatus, hash, bank_ref_no, surl, curl, furl, and card_hashWhitelisting required
Whitelisting is required at both merchant's and PayU's end to establish this connection.
- You need to white list the following IP address on your Firewall:
- 180.179.174.1
- 180.179.174.2
 
- PayU will white list merchant server side IP address that you have provided to PayU.
Step 4. Verify the payment
Upon receiving the response, we recommend performing a reconciliation step to validate all transaction details.
You can verify your payments using either of the following methods:
Configure the webhooks to monitor the status of payments.
Webhooks enable a server to communicate with another server by sending an HTTP callback or message.
These callbacks are triggered by specific events or instances and operate at the server-to-server (S2S) level.
👉 For more details, refer to Webhooks for Payments. 
Updated 7 days ago
