UPI Integration
The UPI Seamless Integration allows merchants to process UPI payments directly through a server-to-server (S2S) flow without redirecting customers to external payment pages. This integration provides a smooth payment experience by handling UPI transactions programmatically using customer Virtual Payment Address (VPA) for UPI Collect or generating payment intents for mobile UPI apps.
When to Use UPI Seamless Integration
Use this integration when:
- You want to accept UPI payments without redirecting customers away from your checkout interface
- You support UPI Intent on mobile apps (directly invoking Google Pay, PhonePe, Paytm, BHIM, etc.)
- You support UPI Collect by soliciting the customer's VPA and sending a collect request
- You want faster transaction processing and direct programmatic control over UPI payments
Environment
| Test Environment | https://apitest.payu.in/v2/payments |
| Production Environment | https://api.payu.in/v2/payments |
Request header
| Parameter | Description |
|---|---|
| date | The current date and time. For example, format of the date is Wed, 28 Jun 2023 11:25:19 GMT. |
| authorization | The actual HMAC signature generated using the specified algorithm (sha512) and includes the hashed data. For more information, refer to authorization fields description. |
authorization fields description
| Field | Description |
|---|---|
| username | Represents the username or identifier for the client or merchant, for example smsplus. |
| algorithm | Use SHA512 algorithm for hashing and send this as header value. |
| headers | Specifies which headers have been used in generating the hash, for example date. |
| signature | The HMAC signature generated using the specified algorithm. For more information, refer to hashing algorithm. |
hashing algorithm
You must hash the request parameters using the following hash logic:
Hash logic: sha512(`<Body data>` + '|' + date + '|' + merchant_secret)
Where <Body data> contains the request body posted with the request.
Sample header code
var merchant_key = '<YOUR_TEST_KEY>';
var merchant_secret = 'YOUR_TEST_SALT';
// date
var date = new Date();
date = date.toUTCString();
// authorization
var authorization = getAuthHeader(date);
function getAuthHeader(date) {
var AUTH_TYPE = 'sha512';
var data = isEmpty(request['data']) ? "" : request['data'];
var hash_string = data + '|' + date + '|' + merchant_secret;
var hash = CryptoJS.SHA512(hash_string).toString(CryptoJS.enc.Hex);
return `hmac username="${merchant_key}", algorithm="${AUTH_TYPE}", headers="date", signature="${hash}"`;
}Request parameters
The table has 8 rows, so here it is in HTML format:
Mandatory parameters
| Parameter | Description | Example |
|---|---|---|
accountId |
String The merchant key provided by PayU during onboarding. |
<YOUR_TEST_KEY> |
txnId |
String Transaction ID provided by the merchant and this must be unique for every transaction. |
ZP6267f0d2996ce |
amount |
Number The transaction amount to be charged. |
424.38 |
paymentMethod |
Object Details about the payment method used. For UPI, specify name as "UPI" and bankCode as "UPI". |
{"name": "UPI", "bankCode": "UPI"} |
order |
Object Details about the transaction order including product information, ordered items, user-defined fields, and payment charge specifications. For more information, refer to order object fields description. |
|
additionalInfo |
Object Additional information including S2S flow configuration and customer VPA. For more information, refer to additionalInfo object fields description. |
|
callBackActions |
Object Actions to perform on the payment server in different scenarios. For more information, refer to callBackActions object fields description. |
|
billingDetails |
Object Billing details of the customer including name, phone number, and email. For more information, refer to billingDetails object fields description. |
paymentMethod object fields description
Mandatory parameters
| Parameter | Description | Example |
|---|---|---|
name | String Payment mode name. Must be set to "UPI". | UPI |
bankCode | String Bank code for UPI transactions. Must be set to "UPI" (or specific UPI handle code if instructed by PayU). | UPI |
Optional parameters
| Parameter | Description | Example |
|---|---|---|
upi | Object Object containing customer VPA for UPI Collect transactions. | {"vpa": "customer@upi"} |
order object fields description
| Parameter | Description | Example |
|---|---|---|
productInfomandatory | Product details. Type: String | Product details |
orderedItemoptional | Details about the items ordered. Type: Array of Objects | |
userDefinedFieldsoptional | Custom fields for additional information. Type: Object. Fields: udf1, udf2, udf3, udf4, udf5, udf6, udf7, udf8, udf9, udf10. | |
paymentChargeSpecificationmandatory | Includes amount and charges. Type: Object. For more information, refer to paymentChargeSpecification object fields description |
paymentChargeSpecification object fields description
| Parameter | Description | Example |
|---|---|---|
pricemandatory | The transaction amount. Type: Number | 1000 |
netAmountDebitoptional | Net amount to be debited. Type: Number | 1000 |
taxSpecificationoptional | Tax details of the product/order. Type: Object | |
convenienceFeeoptional | Fees format. Type: String | CC:12 |
offersoptional | Offers applied or available for the payment. Type: Object |
userDefinedFields object fields description
| Field | Description |
|---|---|
| udf1 | User defined field. |
| udf2 | User defined field. |
| udf3 | User defined field. |
| udf4 | User defined field. |
| udf5 | User defined field. |
| udf6 | User defined field. |
| udf7 | User defined field. |
| udf8 | User defined field. |
| udf9 | User defined field. |
| udf10 | User defined field. |
additionalInfo object fields description
Mandatory parameters
| Parameter | Description | Example |
|---|---|---|
txnS2sFlow | String Indicates the S2S flow type. Must be set to "4" for UPI seamless flow. | 4 |
Conditional parameters
| Parameter | Description | Example |
|---|---|---|
vpa | String Customer's Virtual Payment Address. Mandatory for UPI Collect flow. Leave omitted or empty for UPI Intent flow. | customer@okhdfcbank |
Optional parameters
| Parameter | Description | Example |
|---|---|---|
createOrder | Boolean Set to true to create an order identifier in PayU system. | true |
callBackActions object fields description
Mandatory parameters
| Parameter | Description | Example |
|---|---|---|
successAction | String URL where merchant receives notification or redirects customer upon success. | <redacted URL> |
failureAction | String URL where merchant receives notification or redirects customer upon failure. | <redacted URL> |
Optional parameters
| Parameter | Description | Example |
|---|---|---|
cancelAction | String URL where customer is redirected if transaction is cancelled. | <redacted URL> |
billingDetails object fields description
| Parameter | Description | Example |
|---|---|---|
firstNamemandatory |
First name of the billing contact. | Ashish |
lastNameoptional |
Last name of the billing contact. | Kumar |
address1mandatory |
Primary billing address. | 123 Main Street |
address2optional |
Secondary billing address. | Apt 4B |
phoneoptional |
Phone number of the billing contact. | 9123456789 |
emailmandatory |
Email address of the billing contact. | [email protected] |
cityoptional |
City of the billing address. | Bharatpur |
stateoptional |
State of the billing address. | Rajasthan |
countryoptional |
Country of the billing address. | India |
zipCodeoptional |
Postal/Zip code of the billing address. | 321028 |
Sample request
curl --location '<redacted URL>' \
--header 'date: <CURRENT_DATE_GMT>' \
--header 'authorization: hmac username="<YOUR_TEST_KEY>", algorithm="sha512", headers="date", signature="<YOUR_SIGNATURE>"' \
--header 'Content-Type: application/json' \
--data-raw '{
"accountId": "<YOUR_TEST_KEY>",
"txnId": "ZP6267f0d2996ce",
"amount": 424.38,
"paymentMethod": {
"name": "UPI",
"bankCode": "UPI",
"upi": {
"vpa": "customer@okhdfcbank"
}
},
"order": {
"productInfo": "Example Product",
"paymentChargeSpecification": {
"price": 424.38,
"netAmountDebit": 424.38
}
},
"additionalInfo": {
"vpa": "customer@okhdfcbank",
"txnS2sFlow": "4",
"createOrder": true
},
"callBackActions": {
"successAction": "<redacted URL>",
"failureAction": "<redacted URL>",
"cancelAction": "<redacted URL>"
},
"billingDetails": {
"firstName": "John",
"phone": "9876543210",
"email": "[email protected]"
}
}'import requests
import json
url = "<redacted URL>"
headers = {
"Content-Type": "application/json",
"date": "<CURRENT_DATE_GMT>",
"authorization": "hmac username=\"<YOUR_TEST_KEY>\", algorithm=\"sha512\", headers=\"date\", signature=\"<YOUR_SIGNATURE>\""
}
payload = {
"accountId": "<YOUR_TEST_KEY>",
"txnId": "ZP6267f0d2996ce",
"amount": 424.38,
"paymentMethod": {
"name": "UPI",
"bankCode": "UPI",
"upi": {
"vpa": "customer@okhdfcbank"
}
},
"order": {
"productInfo": "Example Product",
"paymentChargeSpecification": {
"price": 424.38,
"netAmountDebit": 424.38
}
},
"additionalInfo": {
"vpa": "customer@okhdfcbank",
"txnS2sFlow": "4",
"createOrder": True
},
"callBackActions": {
"successAction": "<redacted URL>",
"failureAction": "<redacted URL>",
"cancelAction": "<redacted URL>"
},
"billingDetails": {
"firstName": "John",
"phone": "9876543210",
"email": "[email protected]"
}
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())<?php
$url = "<redacted URL>";
$payload = json_encode([
"accountId" => "<YOUR_TEST_KEY>",
"txnId" => "ZP6267f0d2996ce",
"amount" => 424.38,
"paymentMethod" => [
"name" => "UPI",
"bankCode" => "UPI",
"upi" => [
"vpa" => "customer@okhdfcbank"
]
],
"order" => [
"productInfo" => "Example Product",
"paymentChargeSpecification" => [
"price" => 424.38,
"netAmountDebit" => 424.38
]
],
"additionalInfo" => [
"vpa" => "customer@okhdfcbank",
"txnS2sFlow" => "4",
"createOrder" => true
],
"callBackActions" => [
"successAction" => "<redacted URL>",
"failureAction" => "<redacted URL>",
"cancelAction" => "<redacted URL>"
],
"billingDetails" => [
"firstName" => "John",
"phone" => "9876543210",
"email" => "[email protected]"
]
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"date: <CURRENT_DATE_GMT>",
"authorization: hmac username=\"<YOUR_TEST_KEY>\", algorithm=\"sha512\", headers=\"date\", signature=\"<YOUR_SIGNATURE>\""
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class UpiRequest {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
String payload = """
{
"accountId": "<YOUR_TEST_KEY>",
"txnId": "ZP6267f0d2996ce",
"amount": 424.38,
"paymentMethod": {
"name": "UPI",
"bankCode": "UPI",
"upi": {
"vpa": "customer@okhdfcbank"
}
},
"order": {
"productInfo": "Example Product",
"paymentChargeSpecification": {
"price": 424.38,
"netAmountDebit": 424.38
}
},
"additionalInfo": {
"vpa": "customer@okhdfcbank",
"txnS2sFlow": "4",
"createOrder": true
},
"callBackActions": {
"successAction": "<redacted URL>",
"failureAction": "<redacted URL>",
"cancelAction": "<redacted URL>"
},
"billingDetails": {
"firstName": "John",
"phone": "9876543210",
"email": "[email protected]"
}
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("<redacted URL>"))
.header("Content-Type", "application/json")
.header("date", "<CURRENT_DATE_GMT>")
.header("authorization", "hmac username=\"<YOUR_TEST_KEY>\", algorithm=\"sha512\", headers=\"date\", signature=\"<YOUR_SIGNATURE>\"")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}const url = "<redacted URL>";
const payload = {
accountId: "<YOUR_TEST_KEY>",
txnId: "ZP6267f0d2996ce",
amount: 424.38,
paymentMethod: {
name: "UPI",
bankCode: "UPI",
upi: {
vpa: "customer@okhdfcbank"
}
},
order: {
productInfo: "Example Product",
paymentChargeSpecification: {
price: 424.38,
netAmountDebit: 424.38
}
},
additionalInfo: {
vpa: "customer@okhdfcbank",
txnS2sFlow: "4",
createOrder: true
},
callBackActions: {
successAction: "<redacted URL>",
failureAction: "<redacted URL>",
cancelAction: "<redacted URL>"
},
billingDetails: {
firstName: "John",
phone: "9876543210",
email: "[email protected]"
}
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
"date": "<CURRENT_DATE_GMT>",
"authorization": "hmac username=\"<YOUR_TEST_KEY>\", algorithm=\"sha512\", headers=\"date\", signature=\"<YOUR_SIGNATURE>\""
},
body: JSON.stringify(payload)
};
fetch(url, options)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));Sample response
{
"status": "PENDING",
"result": {
"paymentId": "21667772394",
"authAction": "https://api.payu.in/payments/21667772394/otps",
"upi": {
"amount": "424.38",
"merchantVpa": "<MERCHANT_VPA>",
"intentURIData": "upi://pay?pa=<MERCHANT_VPA>&pn=<MERCHANT_NAME>&tr=ZP6267f0d2996ce&am=424.38&cu=INR",
"merchantName": "<MERCHANT_NAME>"
}
},
"orderId": "b5f2d8785768087678f4"
}Response Parameters
| Parameter | Description | Example |
|---|---|---|
status |
Status of transaction initiation (PENDING until customer approves payment in UPI app). |
PENDING |
result.paymentId |
PayU's unique payment identifier. |
21667772394 |
result.upi.amount |
Transaction amount formatted for UPI. |
424.38 |
result.upi.merchantVpa |
Merchant VPA handle where the funds are transferred. |
payu.merchant@hdfcbank |
result.upi.intentURIData |
Standard UPI intent URI used to launch installed UPI apps on customer devices. |
upi://pay?pa=... |
result.upi.merchantName |
Merchant legal/display name shown in the customer UPI app. |
PayU Merchant |
orderId |
Unique order identifier generated by PayU if createOrder was true. |
b5f2d8785768087678f4 |
Implementation Steps
Step 1: Select Flow & Collect VPA
- UPI Intent (Mobile): Do not require customer to enter VPA. Omit
vpain the request. PayU returnsintentURIDatawhich your app passes to mobile OS intents. - UPI Collect (Web / Desktop): Solicit customer's Virtual Payment Address (e.g.,
user@upi) and pass it inadditionalInfo.vpaandpaymentMethod.upi.vpa.
Step 2: Create Payment Request
Submit the payment request with txnS2sFlow: "4" and bankCode: "UPI".
Step 3: Handle UPI Response
- For UPI Collect: Inform customer that a collect request notification has been sent to their UPI app. Prompt them to open their UPI app and enter their MPIN.
- For UPI Intent: Launch the UPI intent URL (
intentURIData) via Android Intent or iOS deep link.
Step 4: Verify Payment Status
Poll or call the Verify Payment API to confirm transaction outcome:
curl --location '<redacted URL>' \
--header 'date: <CURRENT_DATE_GMT>' \
--header 'authorization: hmac username="<YOUR_TEST_KEY>", algorithm="sha512", headers="date", signature="<YOUR_SIGNATURE>"' \
--header 'Content-Type: application/json' \
--data-raw '{
"txnId": [
"ZP6267f0d2996ce"
]
}'Sample Responses
Success Response
{
"status": "SUCCESS",
"result": {
"paymentId": "21667772394",
"orderId": "ZP6267f0d2996ce",
"amount": 424.38,
"currency": "INR"
},
"message": "Transaction successful"
}Pending Response
{
"status": "PENDING",
"result": {
"paymentId": "21667772394",
"upi": {
"amount": "424.38",
"merchantVpa": "payu.merchant@hdfcbank"
}
},
"message": "Awaiting customer approval in UPI app"
}Failure Response
{
"status": "FAILED",
"error": {
"code": "PAYMENT_DECLINED",
"message": "Customer rejected collect request or transaction timed out"
},
"result": {
"paymentId": "21667772394"
}
}Error Codes
| Code | HTTP Status | Description | Resolution |
|---|---|---|---|
INVALID_AMOUNT | 400 | Invalid amount value | Check amount format and value |
INVALID_VPA | 400 | Invalid UPI VPA handle | Ensure VPA follows user@bank format |
AUTHENTICATION_FAILED | 401 | Invalid signature or key | Verify HMAC credentials and signature header |
DUPLICATE_REFERENCE | 409 | Reference ID already used | Use unique transaction reference ID |
PAYMENT_DECLINED | 422 | Payment declined or expired | Customer declined request or bank timeout |
For complete error code list, see Error Codes Reference.
Next Steps
- Verify transaction using Verify Payment API
- Handle webhooks for asynchronous status updates
- Check Dashboard for reconciliation
Always verify payment status before order fulfillment.
Updated 21 days ago
