UPI Intent Integration
This section includes the workflow and steps to integrate UPI Intent with Server-to-Server integration.
NPCI Mandate: The UPI Collect flow will be sunset effective 28 February 2026. After this date, your customers will no longer be able to initiate payments or register UPI mandates by manually entering a Virtual Payment Address (VPA), UPI ID, or mobile number. For more information, refer to UPI Collect Disablement Information.
Note:Experience the end-to-end Merchant Hosted Checkout > UPI flow and instantly generate the complete code for seamless, zero-coding integration into your website.
Smart Intent Flow
Workflow

Steps to integrate
Add package IDs in your app's manifest so the app can access UPI apps installed on the customer's device
List the specific UPI apps supported for app, webview, and m-web integrations
Call the payment API to get the Intent URI and transaction details for the UPI app selected by the customer
Extract intentURIData from the response and build the platform-specific URI using the Android or iOS prefix/suffix
Prepend the appropriate Android or iOS prefix to create the fully qualified deeplink to trigger the UPI app
Verify the payment status and ensure transaction completion
Update Manifest File [One-Time]
Add package ids in your apps manifest file to allow your application to access apps installed on the customer's device.
Step 1: Fetch the List of UPI and Smart Intent Supported Apps
List the specific apps for app/webview/m-web.
Step 2: Get Intent URI
Use the _payment API to get Intent URI and transaction details for the UPI app selected by the customer.
Mandatory Parameters
| Parameter | Description |
|---|---|
| key | String Merchant key provided by PayU during onboarding. |
| txnid | String The transaction ID is a reference number for a specific order that is generated by the merchant. |
| amount | String The payment amount for the transaction. |
| productinfo | String A brief description of the product. |
| firstname | String The first name of the customer. |
String The email address of the customer. | |
| phone | String The phone number of the customer. |
| surl | String The success URL, which is the page PayU will redirect to if the transaction is successful. |
| furl | String The failure URL, which is the page PayU will redirect to if the transaction fails. |
| hash | String SHA-512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||Salt) |
| pg | String For UPI Intent, use UPI. |
| bankcode | String For UPI Intent, use INTENT. |
| txn_s2s_flow | String This parameter must be passed with value 4 for Intent flow. |
| s2s_client_ip | String The IP address of the client device. |
| s2s_device_info | String Device information/user-agent string of the client. |
Optional Parameters
| Parameter | Description |
|---|---|
| api_version | String The API version. |
| address1 | String The first line of the billing address. |
| address2 | String The second line of the billing address. |
| city | String The city where the customer resides. |
| state | String The state where the customer resides. |
| country | String The country where the customer resides. |
| zipcode | String Billing address zip code. Mandatory for cardless EMI option. Character Limit: 20. |
| udf1–udf5 | String User-defined fields for storing transaction-specific data. |
| notifyurl | String The URL where PayU sends the server-to-server callback. |
curl --location 'https://test.payu.in/_payment' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'key=YOUR_MERCHANT_KEY' \
--data-urlencode 'txnid=TXN_12345' \
--data-urlencode 'amount=10.00' \
--data-urlencode 'productinfo=iPhone' \
--data-urlencode 'firstname=Ashish' \
--data-urlencode '[email protected]' \
--data-urlencode 'phone=9876543210' \
--data-urlencode 'pg=UPI' \
--data-urlencode 'bankcode=INTENT' \
--data-urlencode 'surl=https://apiplayground-response.herokuapp.com/' \
--data-urlencode 'furl=https://apiplayground-response.herokuapp.com/' \
--data-urlencode 'txn_s2s_flow=4' \
--data-urlencode 's2s_client_ip=10.200.12.12' \
--data-urlencode 's2s_device_info=Mozilla/5.0' \
--data-urlencode 'hash=YOUR_HASH_VALUE'import requests
url = "https://test.payu.in/_payment"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {
"key": "YOUR_MERCHANT_KEY",
"txnid": "TXN_12345",
"amount": "10.00",
"productinfo": "iPhone",
"firstname": "Ashish",
"email": "[email protected]",
"phone": "9876543210",
"pg": "UPI",
"bankcode": "INTENT",
"surl": "https://apiplayground-response.herokuapp.com/",
"furl": "https://apiplayground-response.herokuapp.com/",
"txn_s2s_flow": "4",
"s2s_client_ip": "10.200.12.12",
"s2s_device_info": "Mozilla/5.0",
"hash": "YOUR_HASH_VALUE"
}
response = requests.post(url, headers=headers, data=data)
print(response.status_code)
print(response.text)<?php
$url = "https://test.payu.in/_payment";
$data = http_build_query([
"key" => "YOUR_MERCHANT_KEY",
"txnid" => "TXN_12345",
"amount" => "10.00",
"productinfo" => "iPhone",
"firstname" => "Ashish",
"email" => "[email protected]",
"phone" => "9876543210",
"pg" => "UPI",
"bankcode" => "INTENT",
"surl" => "https://apiplayground-response.herokuapp.com/",
"furl" => "https://apiplayground-response.herokuapp.com/",
"txn_s2s_flow" => "4",
"s2s_client_ip" => "10.200.12.12",
"s2s_device_info"=> "Mozilla/5.0",
"hash" => "YOUR_HASH_VALUE"
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/x-www-form-urlencoded"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
echo "Status: " . curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n";
echo $response;
curl_close($ch);
?>import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class UpiIntentS2S {
public static void main(String[] args) throws Exception {
Map<String,String> params = new LinkedHashMap<>();
params.put("key","YOUR_MERCHANT_KEY"); params.put("txnid","TXN_12345");
params.put("amount","10.00"); params.put("productinfo","iPhone");
params.put("firstname","Ashish"); params.put("email","[email protected]");
params.put("phone","9876543210"); params.put("pg","UPI"); params.put("bankcode","INTENT");
params.put("surl","https://apiplayground-response.herokuapp.com/");
params.put("furl","https://apiplayground-response.herokuapp.com/");
params.put("txn_s2s_flow","4"); params.put("s2s_client_ip","10.200.12.12");
params.put("s2s_device_info","Mozilla/5.0"); params.put("hash","YOUR_HASH_VALUE");
StringJoiner sj = new StringJoiner("&");
for (Map.Entry<String,String> e : params.entrySet())
sj.add(URLEncoder.encode(e.getKey(),StandardCharsets.UTF_8)+"="+URLEncoder.encode(e.getValue(),StandardCharsets.UTF_8));
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://test.payu.in/_payment"))
.header("Content-Type","application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(sj.toString())).build();
HttpResponse<String> response = client.send(request,HttpResponse.BodyHandlers.ofString());
System.out.println("Status: "+response.statusCode()); System.out.println(response.body());
}
}using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
class UpiIntentS2S {
static async Task Main() {
using var client = new HttpClient();
var data = new FormUrlEncodedContent(new Dictionary<string,string> {
{"key","YOUR_MERCHANT_KEY"},{"txnid","TXN_12345"},{"amount","10.00"},
{"productinfo","iPhone"},{"firstname","Ashish"},{"email","[email protected]"},
{"phone","9876543210"},{"pg","UPI"},{"bankcode","INTENT"},
{"surl","https://apiplayground-response.herokuapp.com/"},
{"furl","https://apiplayground-response.herokuapp.com/"},
{"txn_s2s_flow","4"},{"s2s_client_ip","10.200.12.12"},
{"s2s_device_info","Mozilla/5.0"},{"hash","YOUR_HASH_VALUE"}
});
var response = await client.PostAsync("https://test.payu.in/_payment", data);
Console.WriteLine("Status: "+(int)response.StatusCode);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}Step 3: Construct the Intent URI
Extract the intentURIData from the response and construct the URI using the platform-specific prefix.
Android Specific Intent prefix
androidPrefix="intent://pay?"
suffix = "#Intent;scheme=upi;package=<package name>;"
IOS Specific Intent prefix
phonepe = phonepe://upi/pay?
paytm = paytm://upi/pay?
googlepay = gpay://upi/pay?
Step 4: Add the prefix
Add the prefix as per the Android/IOS to create a fully qualified deeplink to trigger the UPI App.
Step 5: Verify the payment
Upon receiving the response, PayU recommends you 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.
Know how to manage Webhooks for Payments.
Environment
| Test Environment | https://test.payu.in/merchant/postservice.php?form=2 |
| Production Environment | https://info.payu.in/merchant/postservice.php?form=2 |
Note: The hash logic for Verify Payment API is:
sha512(key|command|var1|salt) sha512
Sample request
curl --request POST
--url 'https://test.payu.in/merchant/postservice?form=2'
--header 'Content-Type: application/x-www-form-urlencoded'
--data key=JPM7Fg
--data command=verify_payment
--data var1=IhfgcZnXR4o4nB
--data hash=a0ae79fdd66c875af6e9b21c4a67f1822deb00f2df5e9f0b1948f3222f536a9bf741b24efbb1874ca0f84f76b036e6c0d641581d0100f7abe4aeed2f3264f5c9
Sample response
If credit card payment is made, the response is similar to the following:
{
"status":0,
"msg":"0 out of 1 Transactions Fetched Successfully",
"transaction_details":
{
"IhfgcZnXR4o4nB":
{
"mihpayid":"Not Found",
"status":"Not Found"
}
}
}If txnID is not found, the response is similar to the following:
{
"status":0,
"msg":"0 out of 1 Transactions Fetched Successfully",
"transaction_details":
{
"IhfgcZnXR4o4nB":
{
"mihpayid":"Not Found",
"status":"Not Found"
}
}
}Response parameters
| Parameter | Description | Example |
|---|---|---|
| status | This parameter returns the status of web service call. The status can be any of the following:
| 0 |
| msg | This parameter returns the reason string. | For example, any of the following messages are displayed:
|
| transaction_details | This parameter contains the response in a JSON format. For more information refer to JSON fields description for transaction_details parameter . | |
| request_id | PayU Request ID for a request in a Transaction. For example, a transaction can have a refund request. | 7800456 |
| bank_ref_num | This parameter returns the bank reference number. If the bank provides after a successful action. | 204519474956 |
To learn more about the possible error codes and their description, refer to Error Codes.
Updated 15 days ago
