Earn Rewards Integration
Integrate RewardX to enable customers to redeem their loyalty points during checkout. Follow these sequential steps to implement a complete RewardX earn loyalty points.
Fetch the balance of all the loyalty points integrated.
Prepare PayU payment POST with SPLITPAY parameters and generate the required hash
Parse postback response and validate reverse hash from PayU
Perform final verification step to confirm transaction completion
Step 1: Fetch All Balance
Use the Fetch All Balance API to retrieve reward point balances from multiple specified loyalty providers and determine how much users can save using their points. Use the Fetch All Balance API to retrieve reward point balances from multiple specified loyalty providers and determine how much users can save using their points.
Request parameters
Loyalty API Parameters
| Parameter | Description | Example |
|---|---|---|
loyaltyProvidersmandatory | Array Array of loyalty provider names to fetch rewards from | ["TWID", "ZILLION"] |
mobileNumbermandatory | Number User's mobile number (masked for privacy) | 88001085** |
orderAmountmandatory | Number Order amount for which reward points are applicable | 1000 |
merchantTxnIdoptional | String Merchant-generated transaction reference identifier for tracking the balance lookup against the order. | 123merchantTxnId |
fetchRevisedEarnoptional | Boolean When set to true, the response includes the revised earn configuration (revisedEarnConfig) for each reward. | true |
Sample request for combined for both TWID & Zillion
curl -X POST "https://apitest.payu.in/loyalty-points/v1/balance/all" \
-H "Content-Type: application/json" \
-H "mid: YOUR_MERCHANT_ID" \
-d '{
"loyaltyProviders": ["TWID", "ZILLION"],
"merchantTxnId": "123merchantTxnId",
"mobileNumber": 8800108522,
"fetchRevisedEarn": true,
"orderAmount": 1000
}'import requests
import json
url = "https://apitest.payu.in/loyalty-points/v1/balance/all"
headers = {
"Content-Type": "application/json",
"mid": "YOUR_MERCHANT_ID"
}
payload = {
"loyaltyProviders": ["TWID", "ZILLION"],
"merchantTxnId": "123merchantTxnId",
"mobileNumber": 8800108522,
"fetchRevisedEarn": True,
"orderAmount": 1000
}
response = requests.post(url, headers=headers, json=payload)
print("Status Code:", response.status_code)
print("Response:", response.text)using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
var url = "https://apitest.payu.in/loyalty-points/v1/balance/all";
client.DefaultRequestHeaders.Add("Content-Type", "application/json");
client.DefaultRequestHeaders.Add("mid", "YOUR_MERCHANT_ID");
var json = new
{
loyaltyProviders = new[] { "TWID", "ZILLION" },
merchantTxnId = "123merchantTxnId",
mobileNumber = 8800108522L,
fetchRevisedEarn = true,
orderAmount = 1000
};
var jsonString = JsonSerializer.Serialize(json);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Status Code: {(int)response.StatusCode}");
Console.WriteLine($"Response: {responseBody}");
}
}const url = "https://apitest.payu.in/loyalty-points/v1/balance/all";
const headers = {
"Content-Type": "application/json",
"mid": "YOUR_MERCHANT_ID"
};
const payload = {
"loyaltyProviders": ["TWID", "ZILLION"],
"merchantTxnId": "123merchantTxnId",
"mobileNumber": 8800108522,
"fetchRevisedEarn": true,
"orderAmount": 1000
};
async function makeRequest() {
try {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
});
const data = await response.text();
console.log("Status Code:", response.status);
console.log("Response:", data);
} catch (error) {
console.error("Error:", error);
}
}
makeRequest();import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import com.google.gson.Gson;
import java.util.Arrays;
import java.util.List;
public class ApiRequest {
public static void main(String[] args) throws Exception {
URL url = new URL("https://apitest.payu.in/loyalty-points/v1/balance/all");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("mid", "YOUR_MERCHANT_ID");
Gson gson = new Gson();
String jsonInputString = "{\"loyaltyProviders\":[\"TWID\",\"ZILLION\"],\"merchantTxnId\":\"123merchantTxnId\",\"mobileNumber\":8800108522,\"fetchRevisedEarn\":true,\"orderAmount\":1000}";
try (OutputStream os = conn.getOutputStream()) {
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
int responseCode = conn.getResponseCode();
System.out.println("Status Code: " + responseCode);
try (BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println("Response: " + response.toString());
}
}
}<?php
$url = "https://apitest.payu.in/loyalty-points/v1/balance/all";
$headers = [
"Content-Type" => "application/json",
"mid" => "YOUR_MERCHANT_ID"
];
$payload = [
"loyaltyProviders" => ["TWID", "ZILLION"],
"merchantTxnId" => "123merchantTxnId",
"mobileNumber" => 8800108522,
"fetchRevisedEarn" => true,
"orderAmount" => 1000
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, array_map(function($key, $value) {
return "$key: $value";
}, array_keys($headers), $headers));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "Status Code: " . $httpCode . "\n";
echo "Response: " . $response . "\n";
?>Sample response for combined
{
"data": [
{
"loyaltyProvider": "TWID",
"usableAmount": 500.0,
"usablePoints": 500,
"userStatus": null,
"title": "Save Rs 500 using 500 twid Cash Points",
"availablePoints": null,
"earnConfig": {
"points": 0,
"amount": null,
"title": null
},
"revisedEarnConfig": null,
"rewardId": 270943,
"issuerDetailDTO": {
"brandName": "twid Cash",
"logo": "https://cdn.twidpay.com/co/brand_images/brand_image_14b20_1651155946.png",
"issuerType": "brand"
},
"holdApplicable": false,
"rewards": [
{
"loyaltyProvider": "TWID",
"usableAmount": 250.0,
"usablePoints": 1000,
"userStatus": null,
"title": "Save Rs 250 using 1000 Woodland Points",
"availablePoints": null,
"earnConfig": {
"points": 50,
"amount": null,
"title": "Earn 50 Woodland Points"
},
"revisedEarnConfig": null,
"rewardId": 270940,
"issuerDetailDTO": {
"brandName": "Woodland",
"logo": "https://cdn.twidpay.com/co/s2s_issuer_images/Woodland.jpg",
"issuerType": "brand"
},
"holdApplicable": false,
"rewards": null
},
{
"loyaltyProvider": "TWID",
"usableAmount": 125.0,
"usablePoints": 125,
"userStatus": null,
"title": "Save Rs 125 using 125 HDFC Bank Points",
"availablePoints": null,
"earnConfig": {
"points": 0,
"amount": null,
"title": null
},
"revisedEarnConfig": null,
"rewardId": 270942,
"issuerDetailDTO": {
"brandName": "HDFC Bank",
"logo": "https://cdn.twidpay.com/co/s2s_issuer_images/hdfc_square.svg",
"issuerType": "bank"
},
"holdApplicable": false,
"rewards": null,
"applicableBinList": [
"531849",
"536303",
"524167"
]
}
]
},
{
"customErrorMessage": "Unable to process request for provider",
"loyaltyProvider": "ZILLION",
"usableAmount": null,
"usablePoints": null,
"userStatus": null
}
]
}
Note:The
issuerDetailDTO.brandNamereturned in the Fetch Balance response (for example,"Woodland","HDFC Bank") is the value you must pass asrewardNamein thechildPaymentInstruments/earnPaymentInstrumentsarray of the_paymentrequest when the reward provider is TWID. TherewardNamefield is not applicable for Zillion.
Step 2: Initiate Payment with PayU
Request parameters
| Parameter | Description | Example | |
|---|---|---|---|
keymandatory | String Merchant key provided by PayU during onboarding. | ||
txnidmandatory | String The transaction ID is a reference number for a specific order that is generated by the merchant. | ||
amountmandatory | String The payment amount for the transaction. | ||
productinfomandatory | String A brief description of the product. | ||
firstnamemandatory | String The first name of the customer. | Ashish | |
emailmandatory | String The email address of the customer. | ||
phonemandatory | String The phone number of the customer. | ||
pgmandatory | String The pg parameter must contain SPLITPAY for Rewards transactions. | SPLITPAY | |
bankcodemandatory | String The bankcode parameter identifies the reward provider used at the parent transaction level. Use TWIDX for TWID Rewards or ZRD for Zillion Rewards. For more information, refer to Reward Provider Codes. | TWIDX | |
| splitInfo | JSON This parameter must contain the TWID split information. For more information, refer to splitInfo JSON Object Fields Description. The sample JSON for Spend/Burn or Earn Points with payment methods: -Cards -UPI | Refer to to splitInfo JSON Object Fields Description. | |
furlmandatory | String The success URL, which is the page PayU will redirect to if the transaction is successful. | ||
surlmandatory | String The Failure URL, which is the page PayU will redirect to if the transaction is failed. | ||
hashmandatory | String It is the hash calculated by the merchant. The hash calculation logic is: `sha512(key\|txnid\|amount\|productinfo\|firstname\|email\|udf1\|udf2\|udf3\|udf4\|udf5\|\|\|\|\| | SALT)` | |
address1optional | String The first line of the billing address. For Fraud Detection: This information is helpful when it comes to issues related to fraud detection and chargebacks. Hence, it is must to provide the correct information. | ||
address2optional | String The second line of the billing address. | ||
cityoptional | String The city where your customer resides as part of the billing address. | ||
stateoptional | String The state where your customer resides as part of the billing address. | ||
countryoptional | String The country where your customer resides. | ||
zipcodeoptional | String Billing address zip code is mandatory for the cardless EMI option. Character Limit-20 | ||
udf1optional | String User-defined fields (udf) are used to store any information corresponding to a particular transaction. You can use up to five udfs in the post designated as udf1, udf2, udf3, udf4, udf5. | ||
udf2optional | String User-defined fields (udf) are used to store any information corresponding to a particular transaction. You can use up to five udfs in the post designated as udf1, udf2, udf3, udf4, udf5. | ||
udf3optional | String User-defined fields (udf) are used to store any information corresponding to a particular transaction. | ||
udf4optional | String User-defined fields (udf) are used to store any information corresponding to a particular transaction. | ||
udf5optional | String User-defined fields (udf) are used to store any information corresponding to a particular transaction. |
Understanding Hashing and sample code
Hashing
You must hash the request parameters using the following hash logic:
sha512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||SALT)
For more information, refer to Generate Hash.
Hashing Sample Code
<?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);
Reward Provider Codes
Use the following bankcode values to identify the reward provider in both the top-level _payment request and inside the splitInfo.childPaymentInstruments / earnPaymentInstruments arrays:
| Reward Provider | Top-level bankcode (parent) | Reward instrument bankCode (child, RD) |
|---|---|---|
| TWID | TWIDX | TWIDLS |
| Zillion | ZRD | ZLS |
Note:The
bankcode(parent) signals the reward provider being used for the transaction, while thebankCodeinside theRDinstrument insidesplitInfois the child code that PayU uses to settle the reward leg of the split payment.
splitInfo JSON Object Fields Description
Important:A complete payment cannot be settled by Rewards (TWID or Zillion) alone — Rewards must always be combined with a Card or UPI instrument inside
childPaymentInstruments. The sum oftransactionAmountacross all child instruments must equal the orderamount.Earn is supported for both TWID and Zillion. Pass the reward instrument inside
earnPaymentInstruments(withtransactionAmount: "0") when the customer is paying via Card/UPI and accruing reward points on that transaction.
Field Descriptions in childPaymentInstruments
| Field | Description | Example |
|---|---|---|
| name | The name of the payment method. Use any of the following as required: CC for Cards RD for Rewards (TWID or Zillion) UPI for UPI | CC |
| bankCode | The bank code identifier for the payment instrument. Use CC for Cards, UPI for UPI, TWIDLS for TWID Rewards or ZLS for Zillion Rewards. | CC |
cardNumbermandatory for cards | The credit/debit card number for the transaction. | 5123456789012346 |
cvvmandatory for cards | The Card Verification Value (CVV) for card validation. | 345 |
validThroughmandatory for cards | The card expiry date in MM/YY format. | 07/25 |
| ownerName | The name of the card holder or account owner. | Payu |
vpamandatory for UPI | The Virtual Payment Address (VPA) used for the UPI transaction. | kk@okaxis |
rewardIdmandatory for TWID | The unique reward identifier returned in the rewardId field of the Fetch Balance response. | 271508 |
rewardNamemandatory for TWID | String Brand name of the reward program. Pass the value received as issuerDetailDTO.brandName in the Fetch Balance response (for example, Woodland, HDFC Bank). Mandatory for TWID, not applicable for Zillion. | Woodland |
cardBinmandatory for TWID | The TWID Rewards card BIN (first 6 digits of the underlying card). | 524216 |
cardLastFourmandatory for TWID | The last four digits of the TWID Rewards card. | 0009 |
| transactionAmount | The amount to be processed in the transaction for the given payment instrument. | 512 |
Field Descriptions in earnPaymentInstruments
Use the earnPaymentInstruments array when the customer is paying via Card or UPI and accruing reward points on the same transaction. Earn is supported for both TWID and Zillion.
| Field | Description | Example |
|---|---|---|
| name | The name of the payment instrument. Use RD for the reward instrument. | RD |
| bankCode | The bank code identifier for the reward instrument. Use TWIDLS for TWID Rewards or ZLS for Zillion Rewards. | TWIDLS |
| transactionAmount | The amount processed against the reward instrument. For Earn requests this is typically "0", since reward points are accrued (not redeemed). | 0 |
rewardIdmandatory for TWID | The unique reward identifier returned in the rewardId field of the Fetch Balance response. | 270940 |
rewardNamemandatory for TWID | String Brand name of the reward program. Pass the value received as issuerDetailDTO.brandName in the Fetch Balance response (for example, Woodland, HDFC Bank). Mandatory for TWID, not applicable for Zillion. | Woodland |
cardBinmandatory for TWID | The TWID Rewards card BIN (first 6 digits of the underlying card). | 524216 |
cardLastFourmandatory for TWID | The last four digits of the TWID Rewards card. | 0009 |
Cards
Sample request for Earn Points with Card (TWID)
curl -X POST "https://test.payu.in/_payment" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"key": "KOEfPI",
"txnid": "ram1234",
"productinfo": "Product Info",
"amount": "1000",
"email": "[email protected]",
"firstname": "Payu-Admin",
"lastname": "",
"phone": "9304204920",
"surl": "https://pp1admin.payu.in/test_response",
"furl": "https://pp1admin.payu.in/test_response",
"pg": "SPLITPAY",
"bankcode": "TWIDX",
"txn_s2s_flow": "4",
"splitInfo": {
"childPaymentInstruments": [
{
"bankCode": "CC",
"name": "CC",
"cardNumber": "5123456789012346",
"cvv": "345",
"validThrough": "12/26",
"ownerName": "Payu",
"transactionAmount": "1000.00"
}
],
"earnPaymentInstruments": [
{
"name": "RD",
"bankCode": "TWIDLS",
"transactionAmount": "0",
"rewardId": 270940,
"rewardName": "Woodland",
"cardBin": "524216",
"cardLastFour": "0009"
}
],
"totalAmount": "1000.00",
"consent": false
},
"hash": "e0241876845d20e42336426cf135651d5241503b51e525dffd17f88d1e694f7718a89e33cec6f21971097faad7dca5442910498c298de249b23ea3b12a75ed0c"
}'Sample request for Earn Points with Card (Zillion)
curl -X POST "https://test.payu.in/_payment" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"key": "KOEfPI",
"txnid": "ram1234",
"productinfo": "Product Info",
"amount": "1000",
"email": "[email protected]",
"firstname": "Payu-Admin",
"lastname": "",
"phone": "9304204920",
"surl": "https://pp1admin.payu.in/test_response",
"furl": "https://pp1admin.payu.in/test_response",
"pg": "SPLITPAY",
"bankcode": "ZRD",
"txn_s2s_flow": "4",
"splitInfo": {
"childPaymentInstruments": [
{
"bankCode": "CC",
"name": "CC",
"cardNumber": "5123456789012346",
"cvv": "345",
"validThrough": "12/26",
"ownerName": "Payu",
"transactionAmount": "1000.00"
}
],
"earnPaymentInstruments": [
{
"name": "RD",
"bankCode": "ZLS",
"transactionAmount": "0",
"rewardId": 270940
}
],
"totalAmount": "1000.00",
"consent": false
},
"hash": "e0241876845d20e42336426cf135651d5241503b51e525dffd17f88d1e694f7718a89e33cec6f21971097faad7dca5442910498c298de249b23ea3b12a75ed0c"
}'Sample JSON for Earn Points with Card
{
"childPaymentInstruments": [
{
"bankCode": "CC",
"name": "CC",
"cardNumber": "5123456789012346",
"cvv": "345",
"validThrough": "12/26",
"ownerName": "Payu",
"transactionAmount": "1000.00"
}
],
"earnPaymentInstruments": [
{
"name": "RD",
"bankCode": "TWIDLS",
"transactionAmount": "0",
"rewardId": 270940,
"rewardName": "Woodland",
"cardBin": "524216",
"cardLastFour": "0009"
}
],
"totalAmount": "1000.00",
"consent": false
}UPI
Sample request for Earn Points with UPI (TWID)
curl -X POST "https://test.payu.in/_payment" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"key": "KOEfPI",
"txnid": "ram1234",
"productinfo": "Product Info",
"amount": "1000",
"email": "[email protected]",
"firstname": "Payu-Admin",
"lastname": "",
"phone": "9304204920",
"surl": "https://pp1admin.payu.in/test_response",
"furl": "https://pp1admin.payu.in/test_response",
"pg": "SPLITPAY",
"bankcode": "TWIDX",
"txn_s2s_flow": "4",
"splitInfo": {
"childPaymentInstruments": [
{
"name": "UPI",
"bankCode": "UPI",
"vpa": "kk@okaxis",
"transactionAmount": "1000"
}
],
"earnPaymentInstruments": [
{
"name": "RD",
"bankCode": "TWIDLS",
"transactionAmount": "0",
"rewardId": 270940,
"rewardName": "Woodland"
}
],
"totalAmount": "1000.00",
"consent": false
},
"hash": "f158a418e38993aa4d1d72d056ebf08047d77a8a14f219ef619f6612e9a6ff8f6147ad035c97c012b74f15ebd08eaea423dd7438654f91d7aca1f10d4f406800"
}'Sample request for Earn Points with UPI (Zillion)
curl -X POST "https://test.payu.in/_payment" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"key": "KOEfPI",
"txnid": "ram1234",
"productinfo": "Product Info",
"amount": "1000",
"email": "[email protected]",
"firstname": "Payu-Admin",
"lastname": "",
"phone": "9304204920",
"surl": "https://pp1admin.payu.in/test_response",
"furl": "https://pp1admin.payu.in/test_response",
"pg": "SPLITPAY",
"bankcode": "ZRD",
"txn_s2s_flow": "4",
"splitInfo": {
"childPaymentInstruments": [
{
"name": "UPI",
"bankCode": "UPI",
"vpa": "kk@okaxis",
"transactionAmount": "1000"
}
],
"earnPaymentInstruments": [
{
"name": "RD",
"bankCode": "ZLS",
"transactionAmount": "0",
"rewardId": 270940
}
],
"totalAmount": "1000.00",
"consent": false
},
"hash": "f158a418e38993aa4d1d72d056ebf08047d77a8a14f219ef619f6612e9a6ff8f6147ad035c97c012b74f15ebd08eaea423dd7438654f91d7aca1f10d4f406800"
}'Sample JSON for Earn Points with UPI (Partly)
{
"childPaymentInstruments": [
{
"name": "UPI",
"bankCode": "UPI",
"vpa": "kk@okaxis",
"transactionAmount": "1000"
}
],
"earnPaymentInstruments": [
{
"name": "RD",
"bankCode": "TWIDLS",
"transactionAmount": "0",
"rewardId": 270940,
"rewardName": "Woodland"
}
],
"totalAmount": "1000.00",
"consent": false
}Step 3: Check response from PayU
Hash validation logic for payment response (Reverse Hashing)
While sending the response, PayU takes the exact same parameters that were sent in the request (in reverse order) to calculate the hash and returns it to you. You must verify the hash and then mark a transaction as a success or failure. This is to make sure the transaction has not tampered within the response.
The order of the parameters is similar to the following code block:
sha512(SALT|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key)Sample response (parsed)
- Success scenario (Zillion + UPI)
{
"mihpayid": "999091000010475",
"mode": "SPLITPAY",
"status": "success",
"unmappedstatus": "success",
"key": "KOEfPI",
"txnid": " ram12345",
"amount": "100",
"discount": "0.00",
"net_amount_debit": "100",
"addedon": "2025-01-10 14:56:13",
"productinfo": "Product Info",
"firstname": "Payu-Admin",
"lastname": "",
"address1": "",
"address2": "",
"city": "",
"state": "",
"country": "",
"zipcode": "",
"email": "[email protected]",
"phone": "8800**8522",
"udf1": "",
"udf2": "",
"udf3": "",
"udf4": "",
"udf5": "",
"udf6": "",
"udf7": "",
"udf8": "",
"udf9": "",
"udf10": "",
"hash": "29efcd4f7a8a9a60a61481d70e21baf5ba6e7a472716d9b99bd911ef5390240411107b959e5bc8cdabc31463d150d4e02578349afa20529b18e271f60dd6db59",
"field1": "",
"field2": "",
"field3": "",
"field4": "",
"field5": "",
"field6": "",
"field7": "",
"field8": "",
"field9": "",
"payment_source": "payuS2S",
"PG_TYPE": "SPLITPAY-PG",
"bank_ref_num": "1254",
"error": "E000",
"bankcode": "ZRD",
"error_Message": "No Error",
"splitPayInfo": {
"upi": {
"name": "UPI",
"bankCode": "UPI",
"vpa": "kk@okaxis",
"transactionAmount": "99"
},
"rd": {
"name": "RD",
"bankCode": "ZLS",
"transactionAmount": "1"
}
}
}- Success scenario (Zillion + Cards)
{
"mihpayid": "999091000010471",
"mode": "SPLITPAY",
"status": "success",
"unmappedstatus": "success",
"key": "KOEfPI",
"txnid": " ram1234",
"amount": "100",
"discount": "0.00",
"net_amount_debit": "100",
"addedon": "2025-01-10 14:54:13",
"productinfo": "Product Info",
"firstname": "Payu-Admin",
"lastname": "",
"address1": "",
"address2": "",
"city": "",
"state": "",
"country": "",
"zipcode": "",
"email": "[email protected]",
"phone": "8800108522",
"udf1": "",
"udf2": "",
"udf3": "",
"udf4": "",
"udf5": "",
"udf6": "",
"udf7": "",
"udf8": "",
"udf9": "",
"udf10": "",
"hash": "29efcd4f7a8a9a60a61481d70e21baf5ba6e7a472716d9b99bd911ef5390240411107b959e5bc8cdabc31463d150d4e02578349afa20529b18e271f60dd6db59",
"field1": "",
"field2": "",
"field3": "",
"field4": "",
"field5": "",
"field6": "",
"field7": "",
"field8": "",
"field9": "",
"payment_source": "payuS2S",
"PG_TYPE": "SPLITPAY-PG",
"bank_ref_num": "1254",
"error": "E000",
"bankcode": "ZRD",
"error_Message": "No Error",
"splitPayInfo": {
"cc": {
"name": "CC",
"bankCode": "CC",
"transactionAmount": "99"
},
"rd": {
"name": "RD",
"bankCode": "ZLS",
"transactionAmount": "1"
}
}
}- Success scenario (TWID + Cards)
{
"mihpayid": "999091000010480",
"mode": "SPLITPAY",
"status": "success",
"unmappedstatus": "success",
"key": "KOEfPI",
"txnid": "ram1234",
"amount": "512",
"discount": "0.00",
"net_amount_debit": "512",
"addedon": "2025-01-10 15:00:00",
"productinfo": "Product Info",
"firstname": "Payu-Admin",
"lastname": "",
"address1": "",
"address2": "",
"city": "",
"state": "",
"country": "",
"zipcode": "",
"email": "[email protected]",
"phone": "8800108522",
"udf1": "",
"udf2": "",
"udf3": "",
"udf4": "",
"udf5": "",
"udf6": "",
"udf7": "",
"udf8": "",
"udf9": "",
"udf10": "",
"hash": "29efcd4f7a8a9a60a61481d70e21baf5ba6e7a472716d9b99bd911ef5390240411107b959e5bc8cdabc31463d150d4e02578349afa20529b18e271f60dd6db59",
"field1": "",
"field2": "",
"field3": "",
"field4": "",
"field5": "",
"field6": "",
"field7": "",
"field8": "",
"field9": "",
"payment_source": "payuS2S",
"PG_TYPE": "SPLITPAY-PG",
"bank_ref_num": "1255",
"error": "E000",
"bankcode": "TWIDX",
"error_Message": "No Error",
"splitPayInfo": {
"cc": {
"name": "CC",
"bankCode": "CC",
"transactionAmount": "412"
},
"rd": {
"name": "RD",
"bankCode": "TWIDLS",
"transactionAmount": "100"
}
}
}- Success scenario (TWID + UPI)
{
"mihpayid": "999091000010482",
"mode": "SPLITPAY",
"status": "success",
"unmappedstatus": "success",
"key": "KOEfPI",
"txnid": "ram1234",
"amount": "512",
"discount": "0.00",
"net_amount_debit": "512",
"addedon": "2025-01-10 15:10:00",
"productinfo": "Product Info",
"firstname": "Payu-Admin",
"lastname": "",
"address1": "",
"address2": "",
"city": "",
"state": "",
"country": "",
"zipcode": "",
"email": "[email protected]",
"phone": "8800108522",
"udf1": "",
"udf2": "",
"udf3": "",
"udf4": "",
"udf5": "",
"udf6": "",
"udf7": "",
"udf8": "",
"udf9": "",
"udf10": "",
"hash": "29efcd4f7a8a9a60a61481d70e21baf5ba6e7a472716d9b99bd911ef5390240411107b959e5bc8cdabc31463d150d4e02578349afa20529b18e271f60dd6db59",
"field1": "",
"field2": "",
"field3": "",
"field4": "",
"field5": "",
"field6": "",
"field7": "",
"field8": "",
"field9": "",
"payment_source": "payuS2S",
"PG_TYPE": "SPLITPAY-PG",
"bank_ref_num": "1256",
"error": "E000",
"bankcode": "TWIDX",
"error_Message": "No Error",
"splitPayInfo": {
"upi": {
"name": "UPI",
"bankCode": "UPI",
"vpa": "kk@okaxis",
"transactionAmount": "412"
},
"rd": {
"name": "RD",
"bankCode": "TWIDLS",
"transactionAmount": "100"
}
}
}- Failure scenario
Array
(
[mihpayid] => 20869277619
[mode] => CC
[status] => failure
[unmappedstatus] => failed
[key] => L43t1c
[txnid] => 26ba7cd6a67b0a010542
[amount] => 1.00
[cardCategory] => domestic
[discount] => 0.00
[net_amount_debit] => 0.00
[addedon] => 2024-09-05 17:46:10
[productinfo] => Product Info
[firstname] => Payu-Admin
[lastname] =>
[address1] =>
[address2] =>
[city] =>
[state] =>
[country] =>
[zipcode] =>
[email] => [email protected]
[phone] => 1234567890
[udf1] =>
[udf2] =>
[udf3] =>
[udf4] =>
[udf5] =>
[udf6] =>
[udf7] =>
[udf8] =>
[udf9] =>
[udf10] =>
[hash] => ac7720e4bc33e5494bec6d37302e522171175a987f9d47286bfd29e8a7fc794f56433fcacf0bc120db781c4dc1d05a4857d71e83f00f6ed6aa9c97a1938b9467
[field1] =>
[field2] =>
[field3] =>
[field4] =>
[field5] => 05
[field6] =>
[field7] => AUTHNEGATIVE
[field8] =>
[field9] => Authorization failed at Bank
[payment_source] => payu
[pa_name] => PayU
[PG_TYPE] => CC-PG
[bank_ref_num] => 2409052690
[bankcode] => AMEX
[error] => E1903
[error_Message] => Authorization failed at Bank
[cardnum] => XXXXXXXXXXXX2003
[cardhash] => This field is no longer supported in postback params.
)Raw _payment API response (Card / UPI)
In the decoupled (txn_s2s_flow = 4) integration, the immediate response from the _payment endpoint is a JSON payload containing a referenceId, metaData, optional binData, and a base64-encoded result.acsTemplate. The merchant must base64-decode the acsTemplate to obtain an HTML form that auto-submits to the bank/UPI redirect page where the customer completes authentication. The parsed postback shown above is what PayU posts back to your surl / furl after the customer finishes the authentication step.
- Raw
_paymentresponse (Card)
{
"referenceId": "29b2d115825c53d10a56d64fd359c816",
"order": 1,
"metaData": {
"referenceId": "29b2d115825c53d10a56d64fd359c816",
"txnId": "6e5cc585-6d9f-47e5-909c-78268bafec7b",
"txnStatus": "Enrolled",
"unmappedStatus": "pending",
"type": "otp",
"expiryTimeout": 180,
"cancelUrl": "https://pp1api.payu.in/split-payment/transaction/v1/af6221f5e6baa4cae60c86eff057b234/cancel/29b2d115825c53d10a56d64fd359c816",
"isSplitTransaction": true
},
"binData": {
"pureS2SSupported": false,
"issuingBank": "ICICI",
"category": "creditcard",
"cardType": "VISA",
"isDomestic": true
},
"result": {
"otpPostUrl": "",
"acsTemplate": "PGh0bWw+PGJvZHk+PGZvcm0gbmFtZT0icGF5bWVudF9wb3N0IiBpZD0icGF5bWVudF9wb3N0IiBhY3Rpb249Imh0dHBzOi8vcHAxc2VjdXJlLnBheXUuaW4vLi4uLi9DcmVxIiBtZXRob2Q9InBvc3QiPjwvZm9ybT4="
},
"mode": "CC"
}- Raw
_paymentresponse (UPI)
{
"referenceId": "3d6cd50a233c2016644af4a0be40fa12",
"order": 1,
"metaData": {
"referenceId": "3d6cd50a233c2016644af4a0be40fa12",
"txnId": "6e557dba-955d-4ee9-b49e-7b5b186e71e5",
"txnStatus": "pending",
"unmappedStatus": "pending",
"type": "otp",
"expiryTimeout": 180,
"cancelUrl": "https://pp1api.payu.in/split-payment/transaction/v1/9c5c73a100f323c2c2b5a3568cd3176f/cancel/3d6cd50a233c2016644af4a0be40fa12",
"isSplitTransaction": true
},
"result": {
"acsTemplate": "PGh0bWw+PGJvZHk+PGZvcm0gbmFtZT0icGF5bWVudF9wb3N0IiBpZD0icGF5bWVudF9wb3N0IiBhY3Rpb249Imh0dHBzOi8vcHAxYXBpLnBheXUuaW4vcHVibGljLy8vM2Q2Y2Q1MGEyMzNjMjAxNjY0NGFmNGEwYmU0MGZhMTIvdXBpTG9hZGVyIiBtZXRob2Q9ImdldCI+PC9mb3JtPg=="
},
"mode": "UPI"
}Raw response field reference
| Field | Description | Example |
|---|---|---|
| referenceId | String Unique reference for this leg of the split transaction. | 29b2d115825c53d10a56d64fd359c816 |
| order | Number Sequence of the leg within the split transaction. | 1 |
| metaData.txnId | String PayU internal transaction id. | 6e5cc585-6d9f-47e5-909c-78268bafec7b |
| metaData.txnStatus | String Status of the leg (e.g. Enrolled, pending). | Enrolled |
| metaData.unmappedStatus | String Unmapped (raw) status of the leg. | pending |
| metaData.type | String Type of authentication challenge (e.g. otp). | otp |
| metaData.expiryTimeout | Number Expiry, in seconds, for the authentication step. | 180 |
| metaData.cancelUrl | String URL the merchant can call to cancel the split-payment leg before the customer completes authentication. | https://... |
| metaData.isSplitTransaction | Boolean Always true for SPLITPAY flows. | true |
| binData.issuingBank | String Issuing bank for the card (Card flow only). | ICICI |
| binData.category | String Card category (Card flow only). | creditcard |
| binData.cardType | String Card network (Card flow only). | VISA |
| binData.isDomestic | Boolean Whether the card is domestic (Card flow only). | true |
| result.acsTemplate | String (Base64) Base64-encoded HTML form. Decode and render in the browser to redirect the customer for authentication. | PGh0bWw+PGJvZHk+... |
| result.otpPostUrl | String URL to which the OTP must be POSTed (when applicable). | |
| mode | String Payment instrument used for this leg: CC for Card, UPI for UPI. | CC |
Step 4: Verify the Payment
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.
Updated about 1 hour ago
