[S2S] Net Banking Consent Transaction - Cross-Border
This section describes step-by-step procedure to implement ENACH (Electronic National Automated Clearing House) Consent Transaction (SI mandate registration) for recurring Net Banking 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
Send the ENACH consent transaction request with S2S parameters.
Handle the response for Net Banking flow.
Set up webhooks to receive transaction status updates.
Recurring Payments Flow
Send pre-debit notifications for upcoming recurring debits.
Execute recurring payment transactions using the registered mandate.
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)
Request Parameters
| Parameter | Description | Example |
|---|---|---|
keymandatory | StringThe merchant key is a unique identifier for a merchant account in PayU's database. | JPM7Fg |
txnidmandatory | StringThe transaction ID is a reference number for a specific order generated by the merchant. Must be unique. | enachConsentTxn12345 |
amountmandatory | StringThe payment amount for the transaction. Auto-debit limit is Rs.15,000 (Rs.1,00,000 for insurance/credit card bills). | 10.00 |
productinfomandatory | StringA brief description of the product. Character Limit: 100 | Monthly Subscription |
firstnamemandatory | StringThe first name of the customer. Character Limit: 60 | Ashish |
lastnamemandatory | StringThe last name of the customer. Character Limit: 60 | Verma |
emailmandatory | StringThe email address of the customer. Character Limit: 50 | [email protected] |
phonemandatory | StringThe phone number of the customer. | 9876543210 |
surlmandatory | StringThe Success URL - page PayU will redirect to if the transaction is successful. | https://example.com/success |
furlmandatory | StringThe Failure URL - page PayU will redirect to if the transaction fails. | https://example.com/failure |
pgmandatory | StringPayment gateway type. Must be NB for Net Banking transactions. | NB |
bankcodemandatory | 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 |
simandatory | StringSignifies successful consent taken from the user. Must be 1 for subscription setup. | 1 |
si_detailsmandatory | JSON StringJSON object containing mandate details (billingAmount, billingCurrency, billingCycle, etc.). Refer to si_details JSON Object below. | See si_details accordion |
| beneficiarydetail | ||
mandatory for Net Banking | 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 sectoin |
api_versionmandatory | StringThe API version. Must be 7 for SI transactions. | 7 |
udf1optional but recommended for higher approval rate | StringThe Permanent Account Number (PAN) of the buyer must be collected in this field. | AELPR****E |
udf3optional but recommended for higher approval rate | String Date of Birth (DOB) of buyer in DD-MM-YYYY | 02-02-1980 |
udf4mandatory for payment aggregators | String End merchant legal entity name. For UPI, this field should not be passed. Character limit: 255. | XYZ Pvt. Ltd. |
udf5mandatory for cross-border payments | String Contains invoice ID for the merchant. Character limit: 255. | INV123456 |
address1optional but recommended for higher approval rate | StringFirst line of billing address. Character Limit: 100 | H.No-17, Block C |
address2optional | StringSecond line of billing address. Character Limit: 100 | Tilak Nagar |
cityoptional but recommended for higher approval rate | StringCustomer's city. | Mumbai |
stateoptional but recommended for higher approval rate | StringCustomer's state. | Maharashtra |
countryoptional but recommended for higher approval rate | StringCustomer's country. Character Limit: 50 | India |
zipcodeoptional | StringBilling address zip code. Character Limit: 20 | 400004 |
free_trialoptional | StringSet to 1 for free trial use cases. PayU adjusts the transaction amount as INR 2.00 for Net Banking. | 1 |
buyer_type_businessoptional in case of B2B transaction for cross-border payments | 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_paramsoptional | 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"} |
hashmandatory | String Crucial security parameter using SHA512 hash encryption. Formula incorporates key, txnid, amount, productinfo, firstname, email, udf fields, si_details, and merchant salt. | <Generated Hash> |
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
- 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
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:
|
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 |
|---|---|---|
billingAmountmandatory | StringMaximum amount for recurring transactions. | 10.00 |
billingCurrencymandatory | StringCurrency code. | INR |
billingCyclemandatory | StringBilling frequency: DAILY, WEEKLY, MONTHLY, YEARLY, ADHOC. | MONTHLY |
billingIntervalmandatory | IntegerInterval between billing cycles. | 1 |
paymentStartDatemandatory | StringMandate start date (YYYY-MM-DD). | 2025-06-05 |
paymentEndDatemandatory | 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
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)
# Hash Generation
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()
# Net Banking Payload
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)
# Process the response
else:
print(f'Error: {response.status_code}')<?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'
]);
// Net Banking with S2S parameters
$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 // Generated 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;
}
?>const axios = require('axios');
const qs = require('querystring');
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'
});
// Net Banking payload
const payload = {
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: siDetails,
hash: hash // Generated hash
};
axios.post(url, qs.stringify(payload), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(response => {
console.log('Response:', response.data);
})
.catch(error => {
console.error('Error:', error);
});
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+PGZvcm0gbmFtZT0icGF5bWVudF9wb3N0IiBpZD0icGF5bWVudF9wb3N0IiBhY3Rpb249Imh0dHBzOi8vcGdzaW0wMS5wYXl1LmluL2luaXRpYXRlIiBtZXRob2Q9InBvc3QiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im1lcmNoYW50TmFtZSIgdmFsdWU9IlBBWVUiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im1lcmNoYW50Q29kZSIgdmFsdWU9IlNsRXNjdUpBOTgiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im1lck5hbWUiIHZhbHVlPSJTdWRoYW5zaHUiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InR4bkFtb3VudCIgdmFsdWU9IjIuMDAiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InR4bkRhdGUiIHZhbHVlPSIyMDI1LTEyLTI2Ij48aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0eG5DdXJyZW5jeSIgdmFsdWU9IklOUiI+PGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iY3VzdE5hbWUiIHZhbHVlPSJzdWRoYW5zaHUiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImN1c3RFbWFpbCIgdmFsdWU9InRlc3RAdGVzdC5jb20iPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImN1c3RNb2JpbGUiIHZhbHVlPSI5OTk5OTk5OTk5Ij48aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0eG5SZWZJZCIgdmFsdWU9Im15X29yZGVyXzI1NDIiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImxpdmVtb2RlIiB2YWx1ZT0iZmFsc2UiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InNvdXJjZSIgdmFsdWU9IiI+PGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iUlUiIHZhbHVlPSJodHRwczovL3Rlc3QucGF5dS5pbi9jZjBmNDliYjIxODkzMDU1YzVhZDcxODI2NDJmYzRjZjMyYTNkNjQ3YWUwODA5ZDJhMDM0MzJmOTIxOTg4NzIxL1Rlc3RQZ19yZXNwb25zZS5waHAiPjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im1vZGUiIHZhbHVlPSJUa0k9Ij48aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0eG5EZXNjcmlwdGlvbiIgdmFsdWU9IlRlc3QgTmV0IEJhbmtpbmcgUGF5bWVudCI+PGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iaWJpYm9fY29kZSIgdmFsdWU9IkFYSUIiPjwvZm9ybT48c2NyaXB0IHR5cGU9J3RleHQvamF2YXNjcmlwdCc+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cub25sb2FkPWZ1bmN0aW9uKCl7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZm9ybXNbJ3BheW1lbnRfcG9zdCddLnN1Ym1pdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICA8L3NjcmlwdD48L2JvZHk+PC9odG1sPg==",
"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.
Environment
| 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",
"udf2": "",
"udf3": "22/08/1972",
"udf4": "SellerName",
"udf5": "INV000000005"
}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 |
Request Parameters
| Parameter | Description | Example |
|---|---|---|
key mandatory | String Merchant Key provided by PayU | JPM7Fg |
command mandatory | String API command. Must be si_transaction | si_transaction |
var1 mandatory | JSON Object Transaction details object containing mandatory and optional fields | Refer to var1 Object Fields below |
hash mandatory | String SHA512 hash: sha512(key|command|var1|salt) | 9f5faabedb... |
var1 Object Fields
| Parameter | Description | Example |
|---|---|---|
authpayuid mandatory | String The mihpayid returned in the payment response of the Registration/Consent transaction when transaction is successfully completed. | 6611192557 |
amount mandatory | String The transaction amount which will be deducted from the customer's payment instrument. | 10.00 |
txnid mandatory | String Unique Transaction ID (Order ID) generated by the merchant for this recurring transaction. | REC15113506209 |
firstname mandatory | String First name of the buyer/customer. | John |
lastname mandatory | String Last name of the buyer/customer. | Doe |
address1 mandatory | String Address line 1 of the buyer. | 123 Main Street |
city mandatory | String City of the buyer. | Mumbai |
state mandatory | String State of the buyer. | Maharashtra |
country mandatory | String Country of the buyer. Allowed values: IN or India only. | IN |
zipcode mandatory | String ZIP/PIN code of the buyer. Must be a valid 6-digit Indian PIN code. | 400001 |
phone optional | String The phone number of the customer. | 9999999999 |
email optional | String The email address of the customer. | [email protected] |
invoiceDisplayNumber mandatory for Cards SI | 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 mandatory | 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..."import requests
url = "https://test.payu.in/merchant/postservice?form=2"
payload = {
"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..."
}
headers = {
"accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
}
response = requests.post(url, data=payload, headers=headers)
print(response.json())using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("key", "JPM7Fg"),
new KeyValuePair<string, string>("command", "si_transaction"),
new KeyValuePair<string, string>("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\"}"),
new KeyValuePair<string, string>("hash", "jbUS07Og8BToVZ...")
});
var response = await client.PostAsync("https://test.payu.in/merchant/postservice?form=2", content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}const executeRecurringPayment = async () => {
const url = "https://test.payu.in/merchant/postservice?form=2";
const params = new URLSearchParams();
params.append("key", "JPM7Fg");
params.append("command", "si_transaction");
params.append("var1", JSON.stringify({
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"
}));
params.append("hash", "jbUS07Og8BToVZ...");
const response = await fetch(url, {
method: "POST",
headers: {
"accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
body: params
});
const data = await response.json();
console.log(data);
};
executeRecurringPayment();import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
public class RecurringPaymentTransaction {
public static void main(String[] args) throws Exception {
String url = "https://test.payu.in/merchant/postservice?form=2";
String params = "key=JPM7Fg" +
"&command=si_transaction" +
"&var1=" + URLEncoder.encode("{\"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\"}", StandardCharsets.UTF_8) +
"&hash=jbUS07Og8BToVZ...";
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("accept", "application/json");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
os.write(params.getBytes(StandardCharsets.UTF_8));
}
try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}<?php
$url = "https://test.payu.in/merchant/postservice?form=2";
$data = array(
"key" => "JPM7Fg",
"command" => "si_transaction",
"var1" => json_encode(array(
"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..."
);
$ch = curl_init($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, array(
"accept: application/json",
"Content-Type: application/x-www-form-urlencoded"
));
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>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.
Environment
| 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 17 days ago
