PayU Hosted Integration - Wealth Tech Payment
This section explains how to implement the _payment API for Wealth Tech merchants using PayU Hosted Checkout integration. The _payment includes the *more_info parameter contains various fields including the Wealth Tech object (wtParams).
Note: Currently, PayU supports Net Banking and Card payment modes for Wealth Tech payments.
1. Initiate the Payment to PayU
Send payment request to PayU through POST endpoint with mandatory parameters including merchant key, transaction ID, amount, customer details, and Wealth Tech specific wtParams object for mutual fund transactions
2. Check Response from PayU
Handle the response from PayU after transaction processing, including success/failure status, transaction details, and verify the reverse hash for data authenticity
3. Verify the Payment
Reconcile payment details through webhooks or Verify Payments API to ensure accuracy and completeness of each transaction
Step 1: Initiate the Payment to PayU
Environment
POST https://test.payu.in/_payment
Content-Type: application/x-www-form-urlencodedRequest Parameters
| Parameter | Description | Example |
|---|---|---|
keymandatory | String This parameter is the unique merchant key provided by PayU for your merchant account. For more information, refer to Generate Merchant Key and Salt. | 8488225 |
txnidmandatory | Varchar This parameter is known as Transaction ID (or OrderID). It is the order reference number generated at your (Merchant's) end. It is an identifier which you(merchant) would use to track a particular order. If a transaction using a particular transaction ID has already been successful at PayU, the usage of same Transaction ID again would fail. Hence, it is essential that you post us a unique transaction ID for every new transaction (Please make sure that the transaction ID being sent to us hasn't been successful earlier. In case of this duplication, the customer would get an error of 'duplicate Order ID'). | fd3e847h2 |
amountmandatory | float This parameter should contain the payment amount of the particular transaction. Note: Type-cast the amount to float type | 10 |
productinfomandatory | Varchar This parameter should contain a brief product description. It should be a string describing the product (The description type is entirely your choice). | T-shirt |
firstnamemandatory | Varchar This parameter must contain the first name of the customer. | Ankit |
emailmandatory | Varchar This parameter must contain the email of the customer | [email protected] |
phonemandatory | Integer Merchant needs to take the customer's GPay registered phone number and pass in this field. This field will be used for further mapping the customer VPA and initiate a collect request. | 9876543210 |
surlmandatory | string The "surl" field is the success URL, which is the page PayU will redirect to if the transaction is successful. The merchant can handle the response at this URL after the customer is redirected there. | https://apiplayground-response.herokuapp.com/ |
furlmandatory | String The "furl" field is the Failure URL, which is the page PayU will redirect to if the transaction is failed. The merchant can handle the response at this URL after the customer is redirected there. | https://apiplayground-response.herokuapp.com/ |
api_version mandatory | API version must be posted as 21 | 21 |
hashmandatory | String The hash calculated by the merchant using the key and salt provided by PayU. The format for calculating the hash: sha512(key\|txnid\|amount\|productinfo\|firstname\|email\|udf1\|udf2\|udf3\|udf4\|udf5\|\|\|\|\|\|SALT) For more information, refer to Generate Hash. | a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0 |
more_infomandatory for Wealth Tech | JSON This parameter contains various fields including the Wealth Tech object (wtParams). For more information on wtParams object field, refer to Wealth Tech object (wtParams) fields Description. | Refer to Wealth Tech object (wtParams) fields Description |
lastnameoptional | String The last name of the customer. | Sharma |
address1optional | String The first line of the billing address. | 123 Main Street |
address2optional | String The second line of the billing address. | Apartment 4B |
cityoptional | String The city where your customer resides as part of the billing address. | Mumbai |
stateoptional | String The state where your customer resides as part of the billing address. | Maharashtra |
countryoptional | String The country where your customer resides. | India |
zipcodeoptional | String Billing address zip code is mandatory for the cardless EMI option. | 400001 |
udf1mandatory for Cross-Border Payments | String This parameter has been made for you to keep any information corresponding to the transaction. Note: This parameter must contain buyer's PAN number for Cross-Border Payments. | ABCDE1234F |
udf2optional | string This parameter has been made for you to keep any information corresponding to the transaction. | Additional Info 1 |
udf3mandatory for Cross-Border Payments | String This parameter has been made for you to keep any information corresponding to the transaction. | GSTIN123456 |
udf4optional | String This parameter has been made for you to keep any information corresponding to the transaction. | Additional Info 2 |
udf5optional | String This parameter has been made for you to keep any information corresponding to the transaction. | Additional Info 3 |
additional_chargesoptional | String Collect additional charges for the transaction. For example, platform fee | 10.00 |
Wealth Tech Object (wtParams) Fields
Wealth Tech object wtparams fields description
Sample JSON Structure:
"more_info": {
"wtParams": [
{
"type": "mutual_fund",
"plan": "GD",
"amount": "50000",
"option": "G",
"scheme": "LT",
"receipt": "77407",
"mf_member_id": "123445",
"mf_user_id": "77407",
"mf_partner": "cams",
"mf_investment_type": "L",
"mf_amc_code": "UTB"
}
]
}Wealth Tech object (wtParams) fields Description
Sample JSON
"more_info": {
"wtParams": [
{
"type": "mutual_fund",
"plan": "GD",
"amount": "50000",
"option": "G",
"scheme": "LT",
"receipt": "77407",
"mf_member_id": "123445",
"mf_user_id": "77407",
"mf_partner": "cams",
"mf_investment_type": "L",
"mf_amc_code": "UTB"
}
]
}Fields description
These parameters are included within the more_info field as a JSON array under the fiedl wtParams:
Parameter | Description | Example |
|---|---|---|
type |
|
|
amount |
|
|
receipt |
|
|
mf_member_id |
|
|
mf_user_id |
|
|
mf_partner |
|
|
mf_investment_type |
|
|
plan |
|
|
folio
|
|
|
option |
|
|
scheme |
|
|
mf_amc_code |
|
|
Validation Rules
Mandatory Field Validations
- type: Must always be
"mutual_fund" - amount: Must match the overall order amount and be in paise
- receipt: Must be unique across transactions
- mf_member_id: Must be numeric with length between 5-20 characters
- mf_user_id: Maximum 10 characters allowed
- mf_partner: Must be one of:
"cams","kfin","bse","nse" - mf_investment_type: Only
"L"(Lump Sum) or"S"(SIP) allowed
Optional Field Validations
- mf_amc_code: Maximum 5 characters
- receipt: Maximum 25 characters for SIP registration ID
Hash Calculation
Concatenate fields in this exact sequence, then SHA-512:
key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5|SALT- Use empty strings for missing udf*.
- Compute on your server and include the lowercase hex digest as hash.
For more information, refer to Generate Hash.
Sample Code for Hashing
Concatenate fields in this exact sequence, then SHA-512:
key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5|SALT- Use empty strings for missing udf*.
- Compute on your server and include the lowercase hex digest as hash.
For more information, refer to Generate Hash.
Sample Code for Hashing
<?php
function generateHash($params, $salt) {
// Extract parameters or use empty string if not provided
$key = $params['key'];
$txnid = $params['txnid'];
$amount = $params['amount'];
$productinfo = $params['productinfo'];
$firstname = $params['firstname'];
$email = $params['email'];
$udf1 = isset($params['udf1']) ? $params['udf1'] : '';
$udf2 = isset($params['udf2']) ? $params['udf2'] : '';
$udf3 = isset($params['udf3']) ? $params['udf3'] : '';
$udf4 = isset($params['udf4']) ? $params['udf4'] : '';
$udf5 = isset($params['udf5']) ? $params['udf5'] : '';
// Construct hash string with exact parameter sequence
$hashString = $key . '|' . $txnid . '|' . $amount . '|' . $productinfo . '|' .
$firstname . '|' . $email . '|' . $udf1 . '|' . $udf2 . '|' .
$udf3 . '|' . $udf4 . '|' . $udf5 . '||||||' . $salt;
// Generate hash and convert to lowercase
return strtolower(hash('sha512', $hashString));
}
// Example usage
$params = [
'key' => 'yourKey',
'txnid' => 'yourTxnId',
'amount' => 'yourAmount',
'productinfo' => 'yourProductInfo',
'firstname' => 'yourFirstName',
'email' => 'yourEmail',
'udf1' => 'optional_value1'
// udf2, udf3, udf4, udf5 not provided - will be empty strings
];
$salt = 'yourSalt';
$hash = generateHash($params, $salt);
echo 'Generated Hash: ' . $hash;
?>
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
public class ImprovedHashGenerator {
public static String generateHash(Map<String, String> params, String salt) {
// Extract parameters or use empty string if not provided
String key = params.get("key");
String txnid = params.get("txnid");
String amount = params.get("amount");
String productinfo = params.get("productinfo");
String firstname = params.get("firstname");
String email = params.get("email");
String udf1 = params.getOrDefault("udf1", "");
String udf2 = params.getOrDefault("udf2", "");
String udf3 = params.getOrDefault("udf3", "");
String udf4 = params.getOrDefault("udf4", "");
String udf5 = params.getOrDefault("udf5", "");
// Construct hash string with exact parameter sequence
String hashString = key + "|" + txnid + "|" + amount + "|" + productinfo + "|" +
firstname + "|" + email + "|" + udf1 + "|" + udf2 + "|" +
udf3 + "|" + udf4 + "|" + udf5 + "||||||" + salt;
return sha512(hashString);
}
private static String sha512(String input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString().toLowerCase();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
// Example usage with parameters map
Map<String, String> params = new HashMap<>();
params.put("key", "yourKey");
params.put("txnid", "yourTxnId");
params.put("amount", "yourAmount");
params.put("productinfo", "yourProductInfo");
params.put("firstname", "yourFirstName");
params.put("email", "yourEmail");
params.put("udf1", "optional_value1");
// udf2, udf3, udf4, udf5 not provided - will be empty strings
String salt = "yourSalt";
String hash = generateHash(params, salt);
System.out.println("Generated Hash: " + hash);
}
}
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
public class ImprovedHashGenerator
{
public static string GenerateHash(Dictionary<string, string> parameters, string salt)
{
// Extract parameters or use empty string if not provided
string key = parameters["key"];
string txnid = parameters["txnid"];
string amount = parameters["amount"];
string productinfo = parameters["productinfo"];
string firstname = parameters["firstname"];
string email = parameters["email"];
// Get UDF values if present, otherwise use empty string
string udf1 = parameters.ContainsKey("udf1") ? parameters["udf1"] : "";
string udf2 = parameters.ContainsKey("udf2") ? parameters["udf2"] : "";
string udf3 = parameters.ContainsKey("udf3") ? parameters["udf3"] : "";
string udf4 = parameters.ContainsKey("udf4") ? parameters["udf4"] : "";
string udf5 = parameters.ContainsKey("udf5") ? parameters["udf5"] : "";
// Construct hash string with exact parameter sequence
string hashString = $"{key}|{txnid}|{amount}|{productinfo}|{firstname}|{email}|{udf1}|{udf2}|{udf3}|{udf4}|{udf5}||||||{salt}";
return Sha512(hashString);
}
private static string Sha512(string input)
{
using (SHA512 sha512 = SHA512.Create())
{
byte[] bytes = sha512.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString().ToLower();
}
}
public static void Main(string[] args)
{
// Example usage with parameters dictionary
Dictionary<string, string> parameters = new Dictionary<string, string>
{
["key"] = "yourKey",
["txnid"] = "yourTxnId",
["amount"] = "yourAmount",
["productinfo"] = "yourProductInfo",
["firstname"] = "yourFirstName",
["email"] = "yourEmail",
["udf1"] = "optional_value1"
// udf2, udf3, udf4, udf5 not provided - will be empty strings
};
string salt = "yourSalt";
string hash = GenerateHash(parameters, salt);
Console.WriteLine("Generated Hash: " + hash);
}
}import hashlib
def generate_hash(params, salt):
# Extract parameters or use empty string if not provided
key = params['key']
txnid = params['txnid']
amount = params['amount']
productinfo = params['productinfo']
firstname = params['firstname']
email = params['email']
udf1 = params.get('udf1', '')
udf2 = params.get('udf2', '')
udf3 = params.get('udf3', '')
udf4 = params.get('udf4', '')
udf5 = params.get('udf5', '')
# Construct hash string with exact parameter sequence
hash_string = f"{key}|{txnid}|{amount}|{productinfo}|{firstname}|{email}|{udf1}|{udf2}|{udf3}|{udf4}|{udf5}||||||{salt}"
# Generate SHA-512 hash
return hashlib.sha512(hash_string.encode('utf-8')).hexdigest()
# Example usage
params = {
'key': 'yourKey',
'txnid': 'yourTxnId',
'amount': 'yourAmount',
'productinfo': 'yourProductInfo',
'firstname': 'yourFirstName',
'email': 'yourEmail',
'udf1': 'optional_value1'
# udf2, udf3, udf4, udf5 not provided - will default to empty strings
}
salt = 'yourSalt'
hash_value = generate_hash(params, salt)
print("Generated Hash:", hash_value)
const crypto = require('crypto');
function generateHash(params, salt) {
// Extract parameters or use empty string if not provided
const key = params.key;
const txnid = params.txnid;
const amount = params.amount;
const productinfo = params.productinfo;
const firstname = params.firstname;
const email = params.email;
const udf1 = params.udf1 || '';
const udf2 = params.udf2 || '';
const udf3 = params.udf3 || '';
const udf4 = params.udf4 || '';
const udf5 = params.udf5 || '';
// Construct hash string with exact parameter sequence
const hashString = `${key}|${txnid}|${amount}|${productinfo}|${firstname}|${email}|${udf1}|${udf2}|${udf3}|${udf4}|${udf5}||||||${salt}`;
// Generate SHA-512 hash
return crypto.createHash('sha512').update(hashString).digest('hex');
}
// Example usage
const params = {
key: 'yourKey',
txnid: 'yourTxnId',
amount: 'yourAmount',
productinfo: 'yourProductInfo',
firstname: 'yourFirstName',
email: 'yourEmail',
udf1: 'optional_value1'
// udf2, udf3, udf4, udf5 not provided - will default to empty strings
};
const salt = 'yourSalt';
const hash = generateHash(params, salt);
console.log("Generated Hash:", hash);
Sample Request
curl -i 'https://test.payu.in/_payment' \
-H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \
-H 'content-type: application/x-www-form-urlencoded' \
--data-urlencode 'key=KOEfPI' \
--data-urlencode 'txnid=7f41f520f71b' \
--data-urlencode 'amount=50000' \
--data-urlencode 'productinfo=Mutual Fund' \
--data-urlencode 'firstname=John' \
--data-urlencode '[email protected]' \
--data-urlencode 'phone=9876543210' \
--data-urlencode 'pg=NB' \
--data-urlencode 'bankcode=AXIB' \
--data-urlencode 'surl=https://apiplayground-response.herokuapp.com/' \
--data-urlencode 'furl=https://apiplayground-response.herokuapp.com/' \
--data-urlencode 'api_version=21' \
--data-urlencode 'hash=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0' \
--data-urlencode 'more_info={"wtParams":[{"type":"mutual_fund","plan":"GD","amount":"50000","option":"G","scheme":"LT","receipt":"77407","mf_member_id":"123445","mf_user_id":"77407","mf_partner":"cams","mf_investment_type":"L","mf_amc_code":"UTB"}]}'import requests
# Define the URL and headers
url = "https://test.payu.in/_payment"
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type': 'application/x-www-form-urlencoded'
}
# Define the form data
form_data = {
'key': 'KOEfPI',
'txnid': '7f41f520f71b',
'amount': '50000',
'productinfo': 'Mutual Fund',
'firstname': 'John',
'email': '[email protected]',
'phone': '9876543210',
'pg': 'NB',
'bankcode': 'AXIB',
'surl': 'https://apiplayground-response.herokuapp.com/',
'furl': 'https://apiplayground-response.herokuapp.com/',
'api_version': '21',
'hash': 'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0',
'more_info': '{"wtParams":[{"type":"mutual_fund","plan":"GD","amount":"50000","option":"G","scheme":"LT","receipt":"77407","mf_member_id":"123445","mf_user_id":"77407","mf_partner":"cams","mf_investment_type":"L","mf_amc_code":"UTB"}]}'
}
try:
# Make the POST request
response = requests.post(url, headers=headers, data=form_data)
# Print response headers and content (equivalent to curl -i)
print("Response Headers:")
for header, value in response.headers.items():
print(f"{header}: {value}")
print("\nResponse Content:")
print(response.text)
print(f"\nStatus Code: {response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Error occurred: {e}")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)
{
try
{
await MakePayURequest();
}
catch (Exception ex)
{
Console.WriteLine($"Error occurred: {ex.Message}");
}
}
static async Task MakePayURequest()
{
var url = "https://test.payu.in/_payment";
// Set headers
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
// Prepare form data
var formParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("key", "KOEfPI"),
new KeyValuePair<string, string>("txnid", "7f41f520f71b"),
new KeyValuePair<string, string>("amount", "50000"),
new KeyValuePair<string, string>("productinfo", "Mutual Fund"),
new KeyValuePair<string, string>("firstname", "John"),
new KeyValuePair<string, string>("email", "[email protected]"),
new KeyValuePair<string, string>("phone", "9876543210"),
new KeyValuePair<string, string>("pg", "NB"),
new KeyValuePair<string, string>("bankcode", "AXIB"),
new KeyValuePair<string, string>("surl", "https://apiplayground-response.herokuapp.com/"),
new KeyValuePair<string, string>("furl", "https://apiplayground-response.herokuapp.com/"),
new KeyValuePair<string, string>("api_version", "21"),
new KeyValuePair<string, string>("hash", "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"),
new KeyValuePair<string, string>("more_info",
"{\"wtParams\":[{\"type\":\"mutual_fund\",\"plan\":\"GD\",\"amount\":\"50000\",\"option\":\"G\",\"scheme\":\"LT\",\"receipt\":\"77407\",\"mf_member_id\":\"123445\",\"mf_user_id\":\"77407\",\"mf_partner\":\"cams\",\"mf_investment_type\":\"L\",\"mf_amc_code\":\"UTB\"}]}")
};
var formContent = new FormUrlEncodedContent(formParams);
// Make the POST request
HttpResponseMessage response = await client.PostAsync(url, formContent);
// Print response headers
Console.WriteLine("Response Headers:");
foreach (var header in response.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
// Print response content
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("\nResponse Content:");
Console.WriteLine(responseBody);
Console.WriteLine($"\nStatus Code: {response.StatusCode}");
}
}async function makePayURequest() {
const url = 'https://test.payu.in/_payment';
// Prepare form data
const formData = new URLSearchParams({
'key': 'KOEfPI',
'txnid': '7f41f520f71b',
'amount': '50000',
'productinfo': 'Mutual Fund',
'firstname': 'John',
'email': '[email protected]',
'phone': '9876543210',
'pg': 'NB',
'bankcode': 'AXIB',
'surl': 'https://apiplayground-response.herokuapp.com/',
'furl': 'https://apiplayground-response.herokuapp.com/',
'api_version': '21',
'hash': 'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0',
'more_info': JSON.stringify({
"wtParams": [{
"type": "mutual_fund",
"plan": "GD",
"amount": "50000",
"option": "G",
"scheme": "LT",
"receipt": "77407",
"mf_member_id": "123445",
"mf_user_id": "77407",
"mf_partner": "cams",
"mf_investment_type": "L",
"mf_amc_code": "UTB"
}]
})
});
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData
};
try {
const response = await fetch(url, requestOptions);
// Print response headers
console.log('Response Headers:');
response.headers.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
// Get and print response content
const responseText = await response.text();
console.log('\nResponse Content:');
console.log(responseText);
console.log(`\nStatus Code: ${response.status}`);
return response;
} catch (error) {
console.error('Error occurred:', error);
throw error;
}
}
// Call the function
makePayURequest()
.then(response => {
console.log('Request completed successfully');
})
.catch(error => {
console.error('Request failed:', error);
});import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
public class PayURequest {
public static void main(String[] args) {
try {
makePayURequest();
} catch (Exception e) {
System.err.println("Error occurred: " + e.getMessage());
e.printStackTrace();
}
}
public static void makePayURequest() throws IOException, InterruptedException {
String url = "https://test.payu.in/_payment";
// Prepare form data
Map<String, String> formData = new HashMap<>();
formData.put("key", "KOEfPI");
formData.put("txnid", "7f41f520f71b");
formData.put("amount", "50000");
formData.put("productinfo", "Mutual Fund");
formData.put("firstname", "John");
formData.put("email", "[email protected]");
formData.put("phone", "9876543210");
formData.put("pg", "NB");
formData.put("bankcode", "AXIB");
formData.put("surl", "https://apiplayground-response.herokuapp.com/");
formData.put("furl", "https://apiplayground-response.herokuapp.com/");
formData.put("api_version", "21");
formData.put("hash", "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0");
formData.put("more_info",
"{\"wtParams\":[{\"type\":\"mutual_fund\",\"plan\":\"GD\",\"amount\":\"50000\",\"option\":\"G\",\"scheme\":\"LT\",\"receipt\":\"77407\",\"mf_member_id\":\"123445\",\"mf_user_id\":\"77407\",\"mf_partner\":\"cams\",\"mf_investment_type\":\"L\",\"mf_amc_code\":\"UTB\"}]}");
// Convert form data 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))
.reduce((p1, p2) -> p1 + "&" + p2)
.orElse("");
// Create HTTP client
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(20))
.build();
// Build the request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofMinutes(2))
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(formBody))
.build();
// Send the request
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Print response headers
System.out.println("Response Headers:");
response.headers().map().forEach((key, value) -> {
System.out.println(key + ": " + String.join(", ", value));
});
// Print response content
System.out.println("\nResponse Content:");
System.out.println(response.body());
System.out.println("\nStatus Code: " + response.statusCode());
}
}function makePayURequest() {
$url = 'https://test.payu.in/_payment';
// Prepare form data
$formData = array(
'key' => 'KOEfPI',
'txnid' => '7f41f520f71b',
'amount' => '50000',
'productinfo' => 'Mutual Fund',
'firstname' => 'John',
'email' => '[email protected]',
'phone' => '9876543210',
'pg' => 'NB',
'bankcode' => 'AXIB',
'surl' => 'https://apiplayground-response.herokuapp.com/',
'furl' => 'https://apiplayground-response.herokuapp.com/',
'api_version' => '21',
'hash' => 'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0',
'more_info' => '{"wtParams":[{"type":"mutual_fund","plan":"GD","amount":"50000","option":"G","scheme":"LT","receipt":"77407","mf_member_id":"123445","mf_user_id":"77407","mf_partner":"cams","mf_investment_type":"L","mf_amc_code":"UTB"}]}'
);
// Initialize cURL
$ch = curl_init();
// Set cURL options
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($formData),
CURLOPT_HEADER => true, // Include headers in output (equivalent to -i)
CURLOPT_HTTPHEADER => array(
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type: application/x-www-form-urlencoded'
),
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'PayU API Client'
));
// Execute the request
$response = curl_exec($ch);
// Check for cURL errors
if (curl_error($ch)) {
$error = curl_error($ch);
curl_close($ch);
throw new Exception('cURL error: ' . $error);
}
// Get response information
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
curl_close($ch);
// Separate headers and body
$headers = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
// Print response
echo "Response Headers:\n";
echo $headers . "\n";
echo "Response Content:\n";
echo $body . "\n";
echo "Status Code: " . $httpCode . "\n";
return array(
'headers' => $headers,
'body' => $body,
'status_code' => $httpCode
);
}
try {
$result = makePayURequest();
echo "Request completed successfully\n";
} catch (Exception $e) {
echo "Error occurred: " . $e->getMessage() . "\n";
}Step 2: Check Response from PayU
Success Response
{
"status": 1,
"message": "Transaction Processed successfully",
"details": {
"transactionid": "48101c0c-5265-4c2a-b6d0-e6e73d42809e",
"authpayuid": "999990000005920",
"amount": "50000.00",
"txnid": "7f41f520f71b",
"status": "success",
"firstname": "John",
"email": "[email protected]",
"phone": "9876543210",
"productinfo": "Mutual Fund",
"hash": "reverse_hash_value",
"key": "KOEfPI"
}
}Failure Response
{
"status": 0,
"message": "Invalid Parameter: mf_partner must be less than or equal to 4 characters."
}Response Parameters
| Parameter | Description |
|---|---|
| status | 1 for success, 0 for failure |
| message | Transaction status message |
| transactionid | PayU transaction ID |
| authpayuid | PayU authorization ID |
| amount | Transaction amount |
| txnid | Merchant transaction ID |
| hash | Response hash for verification |
Hash Verification
Verify response using reverse hash calculation:
sha512(SALT|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key)Step 3: Verify the Payment
Upon receiving the response, we recommend 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.
👉 For more details, refer to Webhooks for Payments.
Updated 6 days ago
