[S2S] Net Banking Consent Transaction - Cross-Border
This section describes step-by-step procedure to implement ENACH (Electronic NACH) Consent transaction (SI Mandate registration) for recurring NB payments using PayU's Server-to-Server (S2S) integration with the Legacy Decoupled flow.
Prerequisites
Before starting the integration, ensure you have:
- Active PayU merchant account with Net Banking recurring payments enabled
- Merchant Key and Salt from PayU dashboard
- Test environment access for development
Payment consent flow
Recurring Payments Flow
Payment Consent Flow
Step 1: Post the Request
Before implementing, familiarize yourself with the required parameters.
Reference: For the ENACH Consent Transaction - Cross Border Payments API Reference, refer to ENACH Consent Transaction - CB.
Key Parameters for ENACH Mandate Registration
Mandatory Parameters:
key,txnid,amount,productinfo,firstname,email,phone,lastnamesurl,furl,hashpg(must beNB)bankcode(Refer to Bank Code List)si(must be1)si_details(JSON object with mandate details)api_version(must be7)
Mandatory Parameters
| Parameter | Description | Example |
|---|---|---|
| key | StringThe merchant key is a unique identifier for a merchant account in PayU's database. | JPM7Fg |
| txnid | StringThe transaction ID is a reference number for a specific order generated by the merchant. Must be unique. | enachConsentTxn12345 |
| amount | StringThe payment amount for the transaction. Auto-debit limit is Rs.15,000 (Rs.1,00,000 for insurance/credit card bills). | 10.00 |
| productinfo | StringA brief description of the product. Character Limit: 100 | Monthly Subscription |
| firstname | StringThe first name of the customer. Character Limit: 60 | Ashish |
| lastname | StringThe last name of the customer. Character Limit: 60 | Verma |
StringThe email address of the customer. Character Limit: 50 | [email protected] | |
| phone | StringThe phone number of the customer. | 9876543210 |
| surl | StringThe Success URL - page PayU will redirect to if the transaction is successful. | https://example.com/success |
| furl | StringThe Failure URL - page PayU will redirect to if the transaction fails. | https://example.com/failure |
| pg | StringPayment gateway type. Must be NB for Net Banking transactions. | NB |
| bankcode | StringBank code for the payment option. Refer to Bank Code List for the list of supported banks and their codes. | Refer to Bank Code List |
| SI | StringSignifies successful consent taken from the user. Must be 1 for subscription setup. | 1 |
| si_details | JSON StringJSON object containing mandate details (billingAmount, billingCurrency, Billing Cycle, etc.). Refer to si_details JSON Object below. | See si_details accordion |
| beneficiarydetail | varchar This object represents bank account details of the customer which involves account number, name on the account and account type and needs to be passed if the recurring transaction needs to be set up against Net Banking. It includes the fields as mentioned in the beneficiarydetail fields description table. | Refer to next section |
| api_version | StringThe API version. Must be 7 for SI transactions. | 7 |
| zipcode | StringBilling address zip code. This field is mandatory. Character Limit: 20 | 400004 |
| udf5 | String Contains invoice ID for the merchant. Character limit: 255. | INV123456 |
| hash | String Crucial security parameter using SHA-512 hash encryption. Formula incorporates key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||si_details|Salt | <Generated Hash> |
Optional Parameters
| Parameter | Description | Example |
|---|---|---|
| udf1 | StringThe Permanent Account Number (PAN - primary taxation ID in India) of the buyer. | AELPR****E |
| udf3 | String Date of Birth (DOB) of buyer in DD-MM-YYYY | 02-02-1980 |
| udf4 | String End merchant legal entity name. For UPI, this field should not be passed. Character limit: 255. | XYZ Pvt. Ltd. |
| address1 | StringFirst line of billing address. Character Limit: 100 | H.No-17, Block C |
| address2 | StringSecond line of billing address. Character Limit: 100 | Tilak Nagar |
| city | StringCustomer's city. | Mumbai |
| state | StringCustomer's state. | Maharashtra |
| country | StringCustomer's country. Character Limit: 50 | India |
| free_trial | StringSet to 1 for free trial use cases. PayU adjusts the transaction amount as INR 2.00 for Net Banking. | 1 |
| buyer_type_business | Binary To be sent as "1" in case the buyer is a business. In case of individual buyers, it can be skipped. Default is "0".Note: This will be included in hash if posted (covered in next section). | 1 |
| udf_params | String JSONUDF7 value to capture "Import or Export Code" of the buyer UDF8 value to capture Airway Bill Number / Consignment Number (in case of goods imports) | {"udf7":"0100000029", "udf8":"99953729071"} |
Hash Logic
Parameters in the below sequence needs to be checked before generating the hash, if these params are being posted, it needs to be added in the hash calculation:
|additional_charges|miles|base_payuid|base_merchantid|paisa_mecode|subvention_amount|subvention_eligibility|merchant_data|payoutdetails|loan_id|twid_customer_hash|splitrequest|percentage_additional_charges|force_pa|udf_params|buyer_type_business|tcs_amount
- Case1 example: Simple Hashing, if the merchant is not sending the api_version in the payment request, then it will be treated as hash sequence version 1.
key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||si_details|salt
- Case2 example: if the merchant is passing the additional_charges in the payment request then they have to append the additional_charges value in the raw hash sequence as below.
key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||si_details|salt|additional_charges
- Case3 example: If the merchant wants to pass additional_charges, buyer_type_business in the payment request, then hash formula for payment request will be:
key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||si_details|salt|additional_charges|buyer_type_business
- Case4 example: if the merchant wants to pass the api_version = 7 and buyer_type_business, udf_params in the payment request.
key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||si_details|salt|udf_params|buyer_type_businessbeneficiarydetail fields description
beneficiarydetail fields description
Sample object
{"beneficiaryName": "Sachin Tendulkar","beneficiaryAccountNumber": "1211450021","beneficiaryAccountType": "SAVINGS", "beneficiaryIfscCode":"ICIC0000046", "verificationMode":"DEBIT_CARD"}description
| Field | Description |
|---|---|
| BeneficiaryName | Registered name against customer's account |
| BeneficiaryAccountNumber | Account number against which recurring transactions need to be executed. |
| BeneficiaryAccountType | SAVINGS or CURRENT |
| beneficiaryIfscCode | 11-digit IFSC code of the customer bank |
| verificationMode | The verification mode can be any of the following: DEBIT_CARD – authentication will be done through a debit card. If no value is provided, then it will trigger Net Banking login password flow. AADHAAR – authentication will be done through an Aadhaar card. If no value is provided, then it will trigger Net Banking login password flow. |
si_details JSON Object
The si_details parameter is a JSON object containing mandate details:
{
"billingAmount": "10.00",
"billingCurrency": "INR",
"billingCycle": "MONTHLY",
"billingInterval": 1,
"paymentStartDate": "2025-06-05",
"paymentEndDate": "2025-12-01"
}| Field | Description | Example |
|---|---|---|
| billingAmount | StringMaximum amount for recurring transactions. | 10.00 |
| billingCurrency | StringCurrency code. | INR |
| billingCycle | StringBilling frequency: DAILY, WEEKLY, MONTHLY, YEARLY, ADHOC. | MONTHLY |
| billingInterval | IntegerInterval between billing cycles. | 1 |
| paymentStartDate | StringMandate start date (YYYY-MM-DD). | 2025-06-05 |
| paymentEndDate | StringMandate end date (YYYY-MM-DD). | 2025-12-01 |
Hash Generation
For ENACH consent transactions with api_version=7, generate the hash using the following formula:
HASH = SHA512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||si_details|SALT)Important: The
si_detailsJSON string must be included in the hash calculation.
Request Payload Structure
Net Banking Flow
{
"key": "JPM7Fg",
"txnid": "enachConsentTxn12345",
"amount": "10.00",
"productinfo": "Monthly Subscription",
"firstname": "Ashish",
"lastname": "Verma",
"email": "[email protected]",
"phone": "9988776655",
"surl": "https://example.com/success",
"furl": "https://example.com/failure",
"udf1": "AELPR1234E",
"udf2": "",
"udf3": "02-02-1980",
"udf4": "XYZ Pvt. Ltd.",
"udf5": "INV123456",
"buyer_type_business": "1",
"udf_params": "{\"udf7\":\"0100000029\",\"udf8\":\"99953729071\"}",
"pg": "NB",
"bankcode": "SBIB",
"api_version": "7",
"si": "1",
"si_details": "{\"billingAmount\":\"10.00\",\"billingCurrency\":\"INR\",\"billingCycle\":\"MONTHLY\",\"billingInterval\":1,\"paymentStartDate\":\"2025-06-05\",\"paymentEndDate\":\"2025-12-01\"}",
"hash": "generated_hash_value"
}Sample Request
Sample request in various language binding
curl --location --request POST 'https://test.payu.in/_payment' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'key=JPM7Fg' \
--data-urlencode 'txnid=enachConsentTxn12345' \
--data-urlencode 'amount=10.00' \
--data-urlencode 'firstname=Ashish' \
--data-urlencode 'lastname=Verma' \
--data-urlencode '[email protected]' \
--data-urlencode 'phone=9988776655' \
--data-urlencode 'productinfo=Monthly Subscription' \
--data-urlencode 'surl=https://example.com/success' \
--data-urlencode 'furl=https://example.com/failure' \
--data-urlencode 'udf1=AELPR1234E' \
--data-urlencode 'udf2=' \
--data-urlencode 'udf3=02-02-1980' \
--data-urlencode 'udf4=XYZ Pvt. Ltd.' \
--data-urlencode 'udf5=INV123456' \
--data-urlencode 'buyer_type_business=1' \
--data-urlencode 'udf_params={"udf7":"0100000029","udf8":"99953729071"}' \
--data-urlencode 'pg=NB' \
--data-urlencode 'bankcode=SBIB' \
--data-urlencode 'api_version=7' \
--data-urlencode 'si=1' \
--data-urlencode 'si_details={"billingAmount":"10.00","billingCurrency":"INR","billingCycle":"MONTHLY","billingInterval":1,"paymentStartDate":"2025-06-05","paymentEndDate":"2025-12-01"}' \
--data-urlencode 'hash=YOUR_CALCULATED_HASH'import requests
import json
import hashlib
url = 'https://test.payu.in/_payment'
si_details = {
'billingAmount': '10.00',
'billingCurrency': 'INR',
'billingCycle': 'MONTHLY',
'billingInterval': 1,
'paymentStartDate': '2025-06-05',
'paymentEndDate': '2025-12-01'
}
si_details_json = json.dumps(si_details)
key = 'JPM7Fg'
salt = 'YOUR_SALT'
txnid = 'enachConsentTxn12345'
amount = '10.00'
productinfo = 'Monthly Subscription'
firstname = 'Ashish'
email = '[email protected]'
udf1 = 'AELPR1234E'
udf2 = ''
udf3 = '02-02-1980'
udf4 = 'XYZ Pvt. Ltd.'
udf5 = 'INV123456'
hash_string = f"{key}|{txnid}|{amount}|{productinfo}|{firstname}|{email}|{udf1}|{udf2}|{udf3}|{udf4}|{udf5}||||||{si_details_json}|{salt}"
hash_value = hashlib.sha512(hash_string.encode()).hexdigest()
payload = {
'key': key,
'txnid': txnid,
'amount': amount,
'productinfo': productinfo,
'firstname': firstname,
'lastname': 'Verma',
'email': email,
'phone': '9988776655',
'surl': 'https://example.com/success',
'furl': 'https://example.com/failure',
'udf1': udf1,
'udf2': udf2,
'udf3': udf3,
'udf4': udf4,
'udf5': udf5,
'buyer_type_business': '1',
'udf_params': '{"udf7":"0100000029","udf8":"99953729071"}',
'pg': 'NB',
'bankcode': 'SBIB',
'api_version': '7',
'si': '1',
'si_details': si_details_json,
'hash': hash_value
}
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
response = requests.post(url, data=payload, headers=headers)
if response.status_code == 200:
response_data = response.json()
print('Response:', response_data)
else:
print(f'Error: {response.status_code}')using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
class ENACHConsentTransaction
{
static async Task Main(string[] args)
{
var url = "https://test.payu.in/_payment";
var siDetails = JsonSerializer.Serialize(new
{
billingAmount = "10.00",
billingCurrency = "INR",
billingCycle = "MONTHLY",
billingInterval = 1,
paymentStartDate = "2025-06-05",
paymentEndDate = "2025-12-01"
});
// compute hash as per Hash Generation logic before using
var formData = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("key", "JPM7Fg"),
new KeyValuePair<string, string>("txnid", "enachConsentTxn12345"),
new KeyValuePair<string, string>("amount", "10.00"),
new KeyValuePair<string, string>("productinfo", "Monthly Subscription"),
new KeyValuePair<string, string>("firstname", "Ashish"),
new KeyValuePair<string, string>("lastname", "Verma"),
new KeyValuePair<string, string>("email", "[email protected]"),
new KeyValuePair<string, string>("phone", "9988776655"),
new KeyValuePair<string, string>("surl", "https://example.com/success"),
new KeyValuePair<string, string>("furl", "https://example.com/failure"),
new KeyValuePair<string, string>("udf1", "AELPR1234E"),
new KeyValuePair<string, string>("udf2", ""),
new KeyValuePair<string, string>("udf3", "02-02-1980"),
new KeyValuePair<string, string>("udf4", "XYZ Pvt. Ltd."),
new KeyValuePair<string, string>("udf5", "INV123456"),
new KeyValuePair<string, string>("buyer_type_business", "1"),
new KeyValuePair<string, string>("udf_params", "{\"udf7\":\"0100000029\",\"udf8\":\"99953729071\"}"),
new KeyValuePair<string, string>("pg", "NB"),
new KeyValuePair<string, string>("bankcode", "SBIB"),
new KeyValuePair<string, string>("api_version", "7"),
new KeyValuePair<string, string>("si", "1"),
new KeyValuePair<string, string>("si_details", siDetails),
new KeyValuePair<string, string>("hash", "YOUR_CALCULATED_HASH")
});
using var client = new HttpClient();
var response = await client.PostAsync(url, formData);
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("Status Code: " + (int)response.StatusCode);
Console.WriteLine("Response: " + responseBody);
}
}const url = 'https://test.payu.in/_payment';
const siDetails = JSON.stringify({
billingAmount: '10.00',
billingCurrency: 'INR',
billingCycle: 'MONTHLY',
billingInterval: 1,
paymentStartDate: '2025-06-05',
paymentEndDate: '2025-12-01'
});
// compute hash as per Hash Generation logic before using
const params = new URLSearchParams();
params.append('key', 'JPM7Fg');
params.append('txnid', 'enachConsentTxn12345');
params.append('amount', '10.00');
params.append('productinfo', 'Monthly Subscription');
params.append('firstname', 'Ashish');
params.append('lastname', 'Verma');
params.append('email', '[email protected]');
params.append('phone', '9988776655');
params.append('surl', 'https://example.com/success');
params.append('furl', 'https://example.com/failure');
params.append('udf1', 'AELPR1234E');
params.append('udf2', '');
params.append('udf3', '02-02-1980');
params.append('udf4', 'XYZ Pvt. Ltd.');
params.append('udf5', 'INV123456');
params.append('buyer_type_business', '1');
params.append('udf_params', '{"udf7":"0100000029","udf8":"99953729071"}');
params.append('pg', 'NB');
params.append('bankcode', 'SBIB');
params.append('api_version', '7');
params.append('si', '1');
params.append('si_details', siDetails);
params.append('hash', 'YOUR_CALCULATED_HASH');
(async () => {
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params.toString()
});
const data = await response.json();
console.log('Response:', data);
} catch (error) {
console.error('Error:', error);
}
})();import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class ENACHConsentTransaction {
public static void main(String[] args) throws Exception {
String url = "https://test.payu.in/_payment";
String siDetails = "{\"billingAmount\":\"10.00\",\"billingCurrency\":\"INR\",\"billingCycle\":\"MONTHLY\",\"billingInterval\":1,\"paymentStartDate\":\"2025-06-05\",\"paymentEndDate\":\"2025-12-01\"}";
String udfParams = "{\"udf7\":\"0100000029\",\"udf8\":\"99953729071\"}";
// compute hash as per Hash Generation logic before using
Map<String, String> formData = new LinkedHashMap<>();
formData.put("key", "JPM7Fg");
formData.put("txnid", "enachConsentTxn12345");
formData.put("amount", "10.00");
formData.put("productinfo", "Monthly Subscription");
formData.put("firstname", "Ashish");
formData.put("lastname", "Verma");
formData.put("email", "[email protected]");
formData.put("phone", "9988776655");
formData.put("surl", "https://example.com/success");
formData.put("furl", "https://example.com/failure");
formData.put("udf1", "AELPR1234E");
formData.put("udf2", "");
formData.put("udf3", "02-02-1980");
formData.put("udf4", "XYZ Pvt. Ltd.");
formData.put("udf5", "INV123456");
formData.put("buyer_type_business", "1");
formData.put("udf_params", udfParams);
formData.put("pg", "NB");
formData.put("bankcode", "SBIB");
formData.put("api_version", "7");
formData.put("si", "1");
formData.put("si_details", siDetails);
formData.put("hash", "YOUR_CALCULATED_HASH");
String formBody = formData.entrySet().stream()
.map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) + "=" +
URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
.collect(Collectors.joining("&"));
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(formBody))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response: " + response.body());
}
}<?php
$url = 'https://test.payu.in/_payment';
$si_details = json_encode([
'billingAmount' => '10.00',
'billingCurrency' => 'INR',
'billingCycle' => 'MONTHLY',
'billingInterval' => 1,
'paymentStartDate' => '2025-06-05',
'paymentEndDate' => '2025-12-01'
]);
$data = [
'key' => 'JPM7Fg',
'txnid' => 'enachConsentTxn12345',
'amount' => '10.00',
'productinfo' => 'Monthly Subscription',
'firstname' => 'Ashish',
'lastname' => 'Verma',
'email' => '[email protected]',
'phone' => '9988776655',
'surl' => 'https://example.com/success',
'furl' => 'https://example.com/failure',
'udf1' => 'AELPR1234E',
'udf2' => '',
'udf3' => '02-02-1980',
'udf4' => 'XYZ Pvt. Ltd.',
'udf5' => 'INV123456',
'buyer_type_business' => '1',
'udf_params' => '{"udf7":"0100000029","udf8":"99953729071"}',
'pg' => 'NB',
'bankcode' => 'SBIB',
'api_version' => '7',
'si' => '1',
'si_details' => $si_details,
'hash' => $hash
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200) {
$responseData = json_decode($response, true);
print_r($responseData);
} else {
echo "Error: " . $httpCode;
}
?>
NoteBefore you make payment request to PayU, ensure you have the correct bank code for the customer's bank. Refer to Bank Code List for the list of supported banks and their codes.
Step 2: Check the Response from PayU
The API returns response structure for Net Banking flow.
Net Banking Response
For Net Banking, the response is returned in URL-encoded format (application/x-www-form-urlencoded):
{
"metaData": {
"message": null,
"referenceId": "cf0f49bb21893055c5ad7182642fc4cf3e1135385b9e55d0b6b0f5e45a19ee74",
"statusCode": null,
"txnId": "my_order_2542",
"txnStatus": "pending",
"unmappedStatus": "pending"
},
"result": {
"acsTemplate": "PGh0bWw+PGJvZHk+PGZvcm0gbmFtZT0icGF5bWVudF9wb3N0IiBpZD0icGF5bWVudF9wb3N0IiBhY3Rpb249Imh0dHBzOi8vcGdzaW0wMS5wYXl1LmluL2luaXRpYXRlIiBtZXRob2Q9InBvc3QiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im1lcmNoYW50TmFtZSIgdmFsdWU9IlBBWVUiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im1lcmNoYW50Q29kZSIgdmFsdWU9IlNsRXNjdUpBOTgiPg==",
"otpPostUrl": "https://test.payu.in/ResponseHandler.php"
}
}Response Handling Logic
Expected Values for Successful Registration
| Response Parameter | Expected Value | Description |
|---|---|---|
| status | success | Indicates that the transaction is successful with the Net Banking provider |
| payment_source | sist | Indicates Net Banking details have been marked correctly for Standing Instruction |
| mihpayid | <mihpayid> | PayU's transaction acknowledgment for a Consent transaction |
Redirect the customer using the result.acsTemplate(base64encoded) to their bank's page for authentication. The final response will be posted to surl/furl and the configured Webhook.
Step 3: Configure Webhooks
Configure webhooks to receive real-time transaction status updates. PayU will send POST requests to your webhook URL.
Webhook Configuration
You can configure the webhook from Payu dashboard directly for payment success/failure events. For more information, refer to Create a New Webhook. Once configured, you will receive transaction updates via HTTP POST.
Webhook Payload Example
unmappedstatus=success&phone=9988776655&txnid=enachConsentTxn12345&hash=84e335094bbcb2ddaa0f9a488eb338e143b273765d89c9dfa502402562d0b6f3c7935e28194ca92f380be7c84c3695415b106dcf52cb016a15fcf6adc98d724&status=success&firstname=Ashish&productinfo=Monthly Subscription&mode=NB&amount=10.00&[email protected]&mihpayid=403993715525317379&surl=https://example.com/success&payment_source=sistWebhook Validation
Always validate the webhook hash before processing:
function validateWebhookHash($response, $salt) {
$hashSequence = "status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key";
$hashVarsSeq = explode('|', $hashSequence);
$hashString = $salt . '|';
foreach(array_reverse($hashVarsSeq) as $hashVar) {
$hashString .= isset($response[$hashVar]) ? $response[$hashVar] : '';
$hashString .= '|';
}
$hashString = rtrim($hashString, '|');
$calculatedHash = strtolower(hash('sha512', $hashString));
$receivedHash = strtolower($response['hash']);
return $calculatedHash === $receivedHash;
}Sample Response
The final response is similar to the following:
{
"mihpayid": "403993715525317379",
"mode": "NB",
"status": "success",
"unmappedstatus": "captured",
"key": "JPM7Fg",
"txnid": "enachConsentTxn12345",
"amount": "10.00",
"discount": "0.00",
"net_amount_debit": "10",
"addedon": "2025-06-05 16:00:53",
"productinfo": "Monthly Subscription",
"firstname": "Ashish",
"lastname": "Verma",
"email": "[email protected]",
"phone": "9988776655",
"hash": "response_hash_value",
"field7": "Transaction completed successfully",
"field9": "Transaction completed successfully",
"payment_source": "sist",
"PG_TYPE": "NB-PG",
"bank_ref_num": "enachConsentTxn12345",
"bankcode": "SBIB",
"error": "E000",
"error_Message": "No Error"
}Handling Mandate Status Updates
If the mandate is not confirmed by the customer or is rejected by the bank, the status is communicated as "failure" over webhook.
| Status | Description |
|---|---|
success | Mandate registered successfully |
failure | Mandate registration failed or rejected |
pending | Mandate registration is pending customer approval |
For more information, refer to Set up WebHook to Receive Cancellation or Modification Update from the Issuer Bank.
Step 4: Update Invoice ID [Conditional]
If the Invoice ID value was unavailable when posting the transaction at Step 1, it can be updated using the UDF Update API by posting it in the UDF5 parameter.
Environments
| Test Environment | https://test.payu.in/merchant/postservice.php?form=2 |
| Production Environment | https://info.payu.in/merchant/postservice.php?form=2 |
Sample request other then UPI AutoPay
curl --location --globoff 'https://test.payu.in/merchant/postservice.php?form=2' \
--form 'key="PRiQvJ"' \
--form 'command="udf_update"' \
--form 'var1="my_order_642"' \
--form 'var2="AAAPZ1234C"' \
--form 'var4="22/08/1972"' \
--form 'var5="SellerName"' \
--form 'var6="INV000000005"' \
--form 'hash="{{hash}}"'Sample response
Success Scenario
- If successfully updated for cards
{
"status": "UDF values updated",
"transaction_id": "my_order_64240",
"udf1": "AAAPZ1234C",
"udf2": "",
"udf3": "22/08/1972",
"udf4": "SellerName",
"udf5": "INV000000005"
}- If successfully updated for UPI autopay:
{
"status": "UDF values updated",
"transaction_id": "my_order_64240",
"udf1": "AAAPZ1234C||22-08-1972",
"udf2": "",
"udf3": "INV_121312||SellerName"
}Failure Scenarios
- If the transaction ID is empty
(
[status] => 0
[msg] => Parameter missing
) - If the transaction ID is invalid
(
[status] => 0
[msg] => Invalid TXN ID
) - If Hash is invalid:
{
"status": 0,
"msg": "Invalid Hash."
}- If the merchant is not enabled for UDF updates:
{
"status": "0",
"msg": "Update not allowed on provided Field"
}- If no data found in the transaction ID:
{
"status": "0",
"msg": "No Data Found for txnid: 3424"
}- If the merchant is inactive:
{
"msg": "Merchant is not authorized to use PayU API",
"status": 0
}Recurring Payments Flow
Note: Pre debit Notification API not required for Netbanking Recurring flow, but it will take upto T+2 days for the consent transaction to be registered. So, you must wait for this period before making a recurring payment on ENACH,
Step 1: Recurring Payment Transaction
Use the Recurring Payment Transaction API to execute recurring payment transactions for customers who have already completed a successful mandate/registration transaction with Net Banking, UPI, or Cards. For detailed API reference, refer to Recurring Payment Transaction API - PACB.
| Environment | URL |
|---|---|
| Production | https://info.payu.in/merchant/postservice?form=2 |
| Test | https://test.payu.in/merchant/postservice?form=2 |
| Parameter | Description | Example | |||
|---|---|---|---|---|---|
| key | String Merchant Key provided by PayU | JPM7Fg | |||
| command | String API command. Must be si_transaction | si_transaction | |||
| var1 | JSON Object Transaction details object containing mandatory and optional fields | Refer to var1 Object Fields below | |||
| hash | String SHA512 hash: `sha512(key\ | command\ | var1\ | salt)` | 9f5faabedb... |
var1 Object Fields
| Parameter | Description | Example |
|---|---|---|
| authpayuid | String The mihpayid returned in the payment response of the Registration/Consent transaction when transaction is successfully completed. | 6611192557 |
| amount | String The transaction amount which will be deducted from the customer's payment instrument. | 10.00 |
| txnid | String Unique Transaction ID (Order ID) generated by the merchant for this recurring transaction. | REC15113506209 |
| firstname | String First name of the buyer/customer. | John |
| lastname | String Last name of the buyer/customer. | Doe |
| address1 | String Address line 1 of the buyer. | 123 Main Street |
| address2 | String Address line 2 of the buyer. | Anytown |
| city | String City of the buyer. | Mumbai |
| state | String State of the buyer. | Maharashtra |
| country | String Country of the buyer. Allowed values: IN or India only. | IN |
| zipcode | String ZIP/PIN code of the buyer. Must be a valid 6-digit Indian PIN code. | 400001 |
| phone | String The phone number of the customer. | 9999999999 |
String The email address of the customer. | [email protected] | |
| invoiceDisplayNumber | String A unique display number by merchant for every subsequent invoice/recurring charge. This must be the same value passed during pre_debit_si API call. | 12345678910 |
| udf5 | String Invoice ID for every merchant. This field is mandatory during or after the transaction. | INV789012 |
Sample Request
curl -X POST "https://test.payu.in/merchant/postservice?form=2" \
-H "accept: application/json" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "key=JPM7Fg&command=si_transaction&var1={
\"authpayuid\": \"6611192557\",
\"amount\": \"100.00\",
\"txnid\": \"REC15113506209\",
\"phone\": \"9999999999\",
\"email\": \"[email protected]\",
\"firstname\": \"John\",
\"lastname\": \"Doe\",
\"address1\": \"123 Main Street\",
\"city\": \"Mumbai\",
\"state\": \"Maharashtra\",
\"country\": \"IN\",
\"zipcode\": \"400001\",
\"invoiceDisplayNumber\": \"12345678910\",
\"udf1\": \"ABCDE1234F\",
\"udf2\": \"\",
\"udf3\": \"15-08-1990\",
\"udf4\": \"\",
\"udf5\": \"INV789012\"
}&hash=jbUS07Og8BToVZ..."Sample Response
Success Response
{
"status": 1,
"message": "Transaction Processed successfully",
"details": {
"REC15113506209": {
"transactionid": "REC15113506209",
"amount": "100.00",
"payuid": "6611427463",
"status": "captured",
"field9": "Transaction Completed Successfully",
"phone": "9999999999",
"email": "[email protected]",
"udf1": "ABCDE1234F",
"udf2": "",
"udf3": "15-08-1990",
"udf4": "",
"udf5": "INV789012"
}
}
}Failure Responses
| Scenario | Response |
|---|---|
| Invalid Hash | {"status": 0, "msg": "Invalid Hash."} |
| Basic Authentication Failed | {"status": 1, "message": "Transaction Processed successfully", "details": {"REC9812123123": {"status": "failed", "field9": "Basic authentication check failed"}}} |
| Invalid Country | {"status": 0, "message": "Invalid country. Only 'IN' or 'India' is allowed."} |
| Missing Mandatory Fields | {"status": 0, "message": "Missing mandatory field: firstname/lastname/address1/city/state/country/zipcode"} |
Transaction Status Values
Status Description captured Transaction successful pending Payment initiated with bank/NPCI. Final status will be notified via webhook. failed Transaction failed in-progress Transaction is being processed
Step 2: Update Invoice ID [Conditional]
If the Invoice ID value was unavailable when posting the transaction or you missed to include invoice ID, it can be updated using the UDF Update API by posting it in the UDF5 parameter.
Environments
| Test Environment | https://test.payu.in/merchant/postservice.php?form=2 |
| Production Environment | https://info.payu.in/merchant/postservice.php?form=2 |
Sample request other then UPI AutoPay
curl --location --globoff 'https://test.payu.in/merchant/postservice.php?form=2' \
--form 'key="PRiQvJ"' \
--form 'command="udf_update"' \
--form 'var1="my_order_642"' \
--form 'var2="AAAPZ1234C"' \
--form 'var4="22/08/1972"' \
--form 'var5="SellerName"' \
--form 'var6="INV000000005"' \
--form 'hash="{{hash}}"'Sample request for UPI AutoPay
curl --location 'https://test.payu.in/merchant/postservice.php?form=2' \
--form 'key="PRiQvJ"' \
--form 'command="udf_update"' \
--form 'var1="my_order_642"' \
--form 'var2="AAAPZ1234C||22-08-1972"' \
--form 'var4="INV_121312||SellerName"' \
--form 'hash="{{hash}}"'Sample response
Success Scenario
- If successfully updated for cards
{
"status": "UDF values updated",
"transaction_id": "my_order_64240",
"udf1": "AAAPZ1234C",
"udf2": "",
"udf3": "22/08/1972",
"udf4": "SellerName",
"udf5": "INV000000005"
}- If successfully updated for UPI autopay:
{
"status": "UDF values updated",
"transaction_id": "my_order_64240",
"udf1": "AAAPZ1234C||22-08-1972",
"udf2": "",
"udf3": "INV_121312||SellerName"
}Failure Scenarios
- If the transaction ID is empty
(
[status] => 0
[msg] => Parameter missing
) - If the transaction ID is invalid
(
[status] => 0
[msg] => Invalid TXN ID
) - If Hash is invalid:
{
"status": 0,
"msg": "Invalid Hash."
}- If the merchant is not enabled for UDF updates:
{
"status": "0",
"msg": "Update not allowed on provided Field"
}- If no data found in the transaction ID:
{
"status": "0",
"msg": "No Data Found for txnid: 3424"
}- If the merchant is inactive:
{
"msg": "Merchant is not authorized to use PayU API",
"status": 0
}Updated 15 days ago
