Net Banking Subscriptions Integration - Merchant Hosted
PayU's Recurring Payment Integration enables merchants to set up automated subscription billing through various payment methods including Net Banking (e-NACH), UPI, and Cards. This comprehensive guide walks you through the complete workflow from capturing initial customer consent and mandate registration to executing seamless recurring transactions without additional customer intervention. The integration ensures full compliance with RBI guidelines while providing essential features.InvoiceDisplayNumber
I. Payment Consent Flow
Initiate the recurring payment process by capturing user consent for the mandate with required parameters including pg='ENACH', bankcode, si=1, and si_details
Ensure the initial consent transaction or registration is successfully processed before proceeding with recurring charges
II. Recurring Payments Flow
I. Payment Consent Flow
Step 1: Consent Transaction
HTTP Method: POST
Environment
| Test Environment | https://test.payu.in/_payment |
| Production Environment | https://secure.payu.in/_payment |
Request Parameters
| Parameter | Description | Value |
|---|---|---|
| key mandatory |
String The merchant key is a unique identifier for a merchant account in PayU's database. |
Your Test Key |
| api_version optional |
String The API version for this API. |
7 |
| txnid mandatory |
String The transaction ID is a reference number for a specific order that is generated by the merchant. It is used to track the order and must be unique. PayU's system will not accept duplicate transaction IDs.Note: Ensure that the transaction ID sent to us has not been successful earlier. In case of this duplication, the customer would get an error of 'duplicate Order ID.' |
s7hhDQVWvbhBdN |
| amount mandatory |
String This field should contain the payment amount for the transaction.The transaction limit is as follows:
|
10.00 |
| productinfo mandatory |
String It should be a string containing a brief description of the product. Character Limit-100 |
iPhone |
| firstname mandatory |
String The first name of the customer. Character Limit-60 |
Ashish |
| email mandatory |
String The email of the customer. Character Limit-50 |
[email protected] |
| phone mandatory |
String The phone number of the customer. |
9876543210 |
| lastname mandatory |
String The last name of the customer. Character Limit-60 |
Verma |
| address1 optional |
String The first line of the billing address. Character Limit-100 |
H.No- 17, Block C, Kalyan Bldg, Khardilkar Road, Mumbai |
| address2 optional |
String The second line of the billing address. Character Limit-100 |
34 Saikripa-Estate, Tilak Nagar |
| city optional |
String The city where your customer resides as part of the billing address. |
Mumbai |
| state optional |
String The state where your customer resides as part of the billing address. |
Maharashtra |
| country optional |
String The country where your customer resides. Character Limit-50 |
India |
| zipcode optional |
String Billing address zip code is mandatory for the cardless EMI option. Character Limit-20 |
400004 |
| si mandatory |
This parameter signifies a successful consent taken from the user by the merchant. This parameter must contain 1 for a successful consent. Without this parameter sent as 1, subscription cannot be set up. Notes: You can modify or cancel existing recurring payment registration as described in the following sections: |
1 |
| si_details mandatory |
This parameter represents mandatory details which need to be passed during the registration transaction from the merchant system to PayU. Note: It is mandatory as per the latest RBI guidelines to pass this information to the payment processor so that it can be forwarded to acquirers and issuers. For more information, refer to the RBI guidelines. This is a JSON object and it includes a set of fields. For more information, refer to SI Parameter JSON Details. |
|
| beneficiarydetail mandatory for Net Banking |
varchar This object represents the customer's bank account details, including the account number, name on the account, and account type. It must be passed when the recurring transaction is set up against Net Banking. It includes the fields listed in the beneficiary detail fields description table. |
Refer to next section |
| hash mandatory |
String It is used to avoid the possibility of transaction tampering. For more information on hash generation, refer to Generate Hash.For a registration transaction, calculate the hash using the following formula: HASH = SHA512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||si_details|SALT) |
eabec285da28fd0e3054d41a4d24fe9f7599c9d0b66646f7a9984303fd6124044b6206daf831e9a8bda28a6200d318293a13d6c193109b60bd4b4f8b09c90972 |
| pg mandatory |
String The pg parameter must include ENACH for Net Banking. |
ENACH |
| bankcode mandatory |
String The merchant must post this parameter with the corresponding payment option's bank code. For more information, refer to Bank Codes - Recurring Payments. |
ICICENCC |
| udf1 - udf5 optional |
String User-defined fields (udf) store information corresponding to a transaction. You can use up to five fields, designated as udf1, udf2, udf3, udf4, and udf5. Character Limit-255 |
Payment Preference, Shipping Method, Shipping Address1, Shipping City, Shipping Zip Code, etc. |
| free_trial optional |
This is mandatory only if the merchant wants to support free trial use cases. In this case, PayU adjusts the transaction amount to INR 2.00 for Cards and UPI and INR 0.00 for Net Banking, irrespective of the amount passed in the request. This parameter has no significance in the seamless flow. |
Beneficiary Detail 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:
|
Sample Request Examples
Sample request
If the merchant sends any other special characters, then they will be automatically removed. The address parameter will consider only the first 100 characters.
When the transaction POST REQUEST hits the PayU server, a new transaction entry is created in the PayU Database. A unique identifier is created in the PayU database to identify each new transaction. This identifier is known as the PayU ID (or mihpayid).
The Net Banking recurring payment registration is also known as e-Mandate. The request for Net Banking involves the following extra parameters posted compared to Cards or UPI:
- billingCycle
- billingInterval
- paymentStartDate
- paymentEndDate
- billingAmount
- beneficiaryName
- beneficiaryAccountNumber
- beneficiaryAccountType
- ifscCode
- verificationMode (optional)
Sample request with Debit Card as Verification mode
The sample code block for Net Banking Seamless integration (Merchant-Hosted Checkout) with the verificationMode field of the beneficiaryDetail JSON parameter with the values as DEBIT_CARD is similar to the following:
curl -X POST "https://test.payu.in/_payment" \
-H "accept: application/json" -H \
"Content-Type: application/x-www-form-urlencoded" -d \
"key=JP***g&txnid=oRWSUMU4XSQBZn&amount=0.0&firstname=Ashish&[email protected]&phone=9876543210&productinfo=iPhone&si=1&pg=ENACH&bankcode=ICICENCC&surl=https://apiplayground-response.herokuapp.com/&furl=&api_version=7&beneficiarydetail={"beneficiaryName": "Ashish Kumar","beneficiaryAccountNumber": "1211450021","beneficiaryAccountType": "SAVINGS", "beneficiaryIfscCode":"ICIC0000046", "verificationMode":"DEBIT_CARD"} Kumar&hash=dbe874c46dcd68ae8c6dd14d04e213f4dff1f2f89106653f61df3e8cee900df33d976e737a82291dfbea3d54d3c67c403d7371c387a1e9652e27ec682d3dce21"Sample request with Aadhaar as Verification mode
The sample code block for Net Banking Seamless integration (Merchant-Hosted Checkout) with the verificationMode field of the beneficiaryDetail JSON parameter with the values as Aadhaar is similar to the following:
curl -X POST "https://test.payu.in/_payment" \
-H "accept: application/json" -H \
"Content-Type: application/x-www-form-urlencoded" -d \
"key=JP***g&txnid=oRWSUMU4XSQBZn&amount=0.0&firstname=Ashish&[email protected]&phone=9876543210&productinfo=iPhone&si=1&pg=ENACH&bankcode=ICICENCC&surl=https://apiplayground-response.herokuapp.com/&furl=&api_version=7&beneficiarydetail={"beneficiaryName": "Ashish Kumar","beneficiaryAccountNumber": "1211450021","beneficiaryAccountType": "SAVINGS", "beneficiaryIfscCode":"ICIC0000046", "verificationMode":"AADHAAR"} Kumar&hash=dbe874c46dcd68ae8c6dd14d04e213f4dff1f2f89106653f61df3e8cee900df33d976e737a82291dfbea3d54d3c67c403d7371c387a1e9652e27ec682d3dce21"Sample Response
Sample response
For Net Banking, you must ensure that the payment response from PayU has the expected values as described in the following table so that Net Banking registration is successful or initiated successfully with the customer's bank.
| Response Parameter | Expected Value | Description |
|---|---|---|
| status | success | This indicates that the transaction is successful |
| payment_source | sist | Indicates that bank details have been marked correctly for Standing Instruction |
| mihpayid | <mihpayid number> sent. by PayU | Indicates PayU's transaction acknowledgment for a Consent transaction |
The response URL returned from PayU is in the form URL format (application/x-www-form-urlencoded).
Parsed response
Array
(
[mihpayid] => 403993715525331373
[mode] => ENACH
[status] => success
[unmappedstatus] => captured
[key] => JPM7Fg
[txnid] => oRWSUMU4XSQBZn
[amount] => 0.00
[discount] => 0.00
[net_amount_debit] => 0
[addedon] => 2022-02-03 19:06:55
[productinfo] => iPhone
[firstname] => Ashish
[lastname] =>
[address1] =>
[address2] =>
[city] =>
[state] =>
[country] =>
[zipcode] =>
[email] => [email protected]
[phone] => 9876543210
[udf1] =>
[udf2] =>
[udf3] =>
[udf4] =>
[udf5] =>
[udf6] =>
[udf7] =>
[udf8] =>
[udf9] =>
[udf10] =>
[hash] => f3f8e4088231b190930fc4b87d3f39397d1a1d02622ef4683a983244e1cd5158f39adbb67c3d87dcb4da25ae4a941ebbf55918e4575fa1c39677a774d02c0d2d
[field1] => ENACH285259747472911093
[field2] => 337026657857179355
[field3] =>
[field4] =>
[field5] =>
[field6] =>
[field7] =>
[field8] =>
[field9] => Mandate successfully scheduled at bank end: Your payment is scheduled successfully
[payment_source] => sist
[PG_TYPE] => ENACH-PG
[bank_ref_num] => 450699821592111537
[bankcode] => ICICENCC
[error] => E000
[error_Message] => No Error
)Step 2: Verify the payment
The payment verification step ensures the transaction has been processed successfully before proceeding to subsequent recurring payments.
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.
II. Recurring Payments Flow
Recurring Payment Transaction
All successful registration transactions are charged over the recurring interface with server-to-server API without any additional 2FA or the customers' involvement.
Notes:
- Banks do not support refunds for Net Banking Recurring Payment transactions (or e-NACH transaction) so you will get an error message, "Refund not accepted for txn" or Error 232. To handle the refunds in this regard, PayU offers an alternate way to perform refunds. You must request your PayU Key Account Manager to enable refunds for Net Banking. For the list of banks supporting e-NACH, refer to Recurring Payments Bank Codes.
- Call the Recurring Payment Transaction API to make a recurring payment transaction.
Assumptions: If the merchant has already performed a successful registration transaction with Net Banking/UPI/Card and mihpayid is received in response to the registration transaction captured successfully and mapped to the customer at the merchant's end.
Environment
| Production Environment | https://info.payu.in/merchant/ |
| Test Environment | https://test.payu.in/merchant/ |
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=JP***g&command=si_transaction&var1={"authpayuid": "6611192557","invoiceDisplayNumber":"12345678910","amount": 3,"txnid": "REC15113506209","phone": "9999999999","email": "[email protected]","udf2": "","udf3": "","udf4": "","udf5": ""}&hash=jbUS07Og8BToVZ"import requests
import urllib.parse
# PayU API endpoint
url = "https://test.payu.in/merchant/postservice?form=2"
# Headers
headers = {
"accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
}
# Form data
form_data = {
"key": "JP***g",
"command": "si_transaction",
"var1": '{"authpayuid": "6611192557","invoiceDisplayNumber":"12345678910","amount": 3,"txnid": "REC15113506209","phone": "9999999999","email": "[email protected]","udf2": "","udf3": "","udf4": "","udf5": ""}',
"hash": "jbUS07Og8BToVZ"
}
# Make the POST request
try:
response = requests.post(url, headers=headers, data=form_data)
print(f"Status Code: {response.status_code}")
print(f"Response: {response.text}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")import java.io.IOException;
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.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class PayUApiClient {
private static final HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30))
.build();
public static void main(String[] args) {
try {
makePayURequest();
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
public static void makePayURequest() throws IOException, InterruptedException {
String url = "https://test.payu.in/merchant/postservice?form=2";
// Prepare form data
Map<String, String> formData = new HashMap<>();
formData.put("key", "JP***g");
formData.put("command", "si_transaction");
formData.put("var1", "{\"authpayuid\": \"6611192557\",\"invoiceDisplayNumber\":\"12345678910\",\"amount\": 3,\"txnid\": \"REC15113506209\",\"phone\": \"9999999999\",\"email\": \"[email protected]\",\"udf2\": \"\",\"udf3\": \"\",\"udf4\": \"\",\"udf5\": \"\"}");
formData.put("hash", "jbUS07Og8BToVZ");
// Convert to URL encoded string
String formBody = formData.entrySet().stream()
.map(entry -> URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) +
"=" + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8))
.collect(Collectors.joining("&"));
// Build request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("accept", "application/json")
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(formBody))
.build();
// Send request
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response: " + response.body());
}
}// PayU API call using modern Async/Await Fetch
async function makePayURequest() {
const url = "https://test.payu.in/merchant/postservice?form=2";
// Headers
const headers = {
"accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
};
// Form data
const formData = new URLSearchParams({
"key": "JP***g",
"command": "si_transaction",
"var1": '{"authpayuid": "6611192557","invoiceDisplayNumber":"12345678910","amount": 3,"txnid": "REC15113506209","phone": "9999999999","email": "[email protected]","udf2": "","udf3": "","udf4": "","udf5": ""}',
"hash": "jbUS07Og8BToVZ"
});
try {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: formData
});
const responseText = await response.text();
console.log(`Status: ${response.status}`);
console.log(`Response: ${responseText}`);
return {
status: response.status,
data: responseText
};
} catch (error) {
console.error("Error:", error);
throw error;
}
}
// Call the function
makePayURequest()
.then(result => console.log("Success:", result))
.catch(error => console.error("Failed:", error));using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string url = "https://test.payu.in/merchant/postservice?form=2";
// Set headers
client.DefaultRequestHeaders.Add("accept", "application/json");
// Prepare form data
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("key", "JP***g"),
new KeyValuePair<string, string>("command", "si_transaction"),
new KeyValuePair<string, string>("var1", "{\"authpayuid\": \"6611192557\",\"invoiceDisplayNumber\":\"12345678910\",\"amount\": 3,\"txnid\": \"REC15113506209\",\"phone\": \"9999999999\",\"email\": \"[email protected]\",\"udf2\": \"\",\"udf3\": \"\",\"udf4\": \"\",\"udf5\": \"\"}"),
new KeyValuePair<string, string>("hash", "jbUS07Og8BToVZ")
};
var formContent = new FormUrlEncodedContent(formData);
try
{
HttpResponseMessage response = await client.PostAsync(url, formContent);
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Status Code: {response.StatusCode}");
Console.WriteLine($"Response: {responseContent}");
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}// PayU API endpoint
$url = "https://test.payu.in/merchant/postservice?form=2";
// Form data
$postData = [
'key' => 'JP***g',
'command' => 'si_transaction',
'var1' => '{"authpayuid": "6611192557","invoiceDisplayNumber":"12345678910","amount": 3,"txnid": "REC15113506209","phone": "9999999999","email": "[email protected]","udf2": "","udf3": "","udf4": "","udf5": ""}',
'hash' => 'jbUS07Og8BToVZ'
];
// Initialize cURL
$ch = curl_init();
// Set cURL options
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($postData),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'accept: application/json',
'Content-Type: application/x-www-form-urlencoded'
],
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false, // Only for testing
]);
// Execute request
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
// Close cURL
curl_close($ch);
// Handle response
if ($error) {
echo "cURL Error: " . $error . PHP_EOL;
} else {
echo "Status Code: " . $httpCode . PHP_EOL;
echo "Response: " . $response . PHP_EOL;
}Sample Response
###Success Scenario
Here is a sample response object returned against recurring payment API when the transaction is successfully charged.
{
"status": 1,
"message": "Transaction Processed successfully",
"details": {
"REC15113506209": {
"authpayuid": "25600342065",
"transactionid": "REC15113506209",
"amount": "1.00",
"user_credentials": "",
"card_token": "",
"payuid": "",
"status": "captured",
"udf1": "",
"field9": "Transaction Completed Successfully",
"udf2": "",
"udf3": "",
"udf4": "",
"udf5": "",
"phone": "9999999999",
"email": "[email protected]"
}
}
}Failure Scenarios
- Invalid hash
{
"status": 0,
"msg": "Invalid Hash."
}- Basic authentication check failed
{
"status": 1,
"message": "Transaction Processed successfully",
"details": {
"REC9812123123": {
"authpayuid": "6611192559",
"transactionid": "REC9812123123",
"amount": "1",
"user_credentials": " ",
"card_token": " ",
"payuid": "",
"status": "failed",
"field9": "Basic authentication check failed",
"phone": "",
"email": ""
}
}
}Response Parameters
JSON fields description of the Details parameter
| JSON Field | Description |
|---|---|
| transactionid | This field contains the value of transaction ID parameter which is echoed back in the response. This is unique transaction ID generated by merchant during calling recurring API. |
| amount | This field contains the requested transaction amount is echoed back in the payment response. |
| payuid | This field contains the PayU's transaction ID for processed recurring transaction. Merchant can use this field for reference point in the settlement report. |
| status | This field gives the status of the transaction. Hence, the value of this field depends on whether the transaction was successful or not. |
| field9 | This field returns the description of transaction status which can help the merchant in providing better customer communication. |
| phone | The mobile number of the customer echoed back. |
| Email ID of the customer echoed back. | |
| udf1 | Extra information received in the request echoed back. |
| udf2 | Extra information received in the request echoed back. |
| udf3 | Extra information received in the request echoed back. |
| udf4 | Extra information received in the request echoed back. |
| udf5 | Extra information received in the request echoed back. |
status field description
This field gives the status of the transaction. Hence, the value of this field depends on whether the transaction was successful or not.
You must map the order status using this parameter only. The possible values of this parameter are:
- captured: If the transaction is successful, the value will be captured. In some cases, the response of Net banking recurring can be captured over real-time basis (ICICI bank in the specific scenario).
- pending: This is common with most Net Banking (except ICICI in the specific scenario) or UPI recurring transaction. In that case, the merchant should consider this as successful initiation of payment with bank / NPCI. The status will be notified back to the merchant over payment processing with individual bank gets completed.
For UPI, "pending" transactions get usually get converted into captured or failed within 10 mins from the time of initiation. The Query API can be called post 10 mins from initiation, whereas for Net Banking, it can be called up to T+2 once a day. For more information, refer to Capture response of Recurring Transaction for Net Banking and UPI.
For Net Banking, "pending" transaction gets converted into "captured" or "failed" from the same day till T+2 anytime, depending upon the bank account used by the customer in setting up registration. - failed: The value of the status as "failed" or blank must be treated as a failed transaction only.
- in-progress: The status of transaction is in progress.
To capture the final status of "pending" transaction to either "captured" or "failed", PayU recommends merchants to either implement Webhook URL or call verify_payment API after regular intervals. For more information on:
- Webhook: Refer to Webhooks
- verify_payment API: Refer to Verify Payment API
Note:For UPI, call the verify_settlement API after 10 mins from time of initiation whereas for Net Banking it can be called up to T+2 once in a day.
Additional Resources
• SI Parameter JSON Details - Detailed subscription parameter specifications
Updated about 1 hour ago
