UPI Intent OTM - Merchant Hosted
The merchant initiates a call to PayU with the SI details, pg., bankcode, and pre-authorization amount. This amount is considered the Block Amount. Using these details, PayU will then relay the callback with the current status to the merchant.
The pre_authorize parameter is used for pre-authorize payments using the seamless integration with the _payment API.
Experience the end-to-end Merchant Hosted Checkout> UPI flow and instantly generate the complete code for seamless, zero-coding integration into your website.
Steps to integrate
Submit the pre-authorization transaction request to PayU for payment hold
Handle and process the response received from PayU after pre-auth request submission
Complete the payment capture process for the pre-authorized transaction
Verify the current status of the transaction and confirm payment completion
Step 1: Post the Pre-Auth transaction request
Post the additional parameters for with the Pre-Authorization using the Merchant Hosted Checkout.
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.
Environment
| Test Environment | <https://test.payu.in/_payment> |
| Production Environment | <https://secure.payu.in/_payment> |
The pre_authorize parameter as specified is used to pre-authorize payments using the Merchant Hosted Checkout integration with the _payment API.
Mandatory Parameters
| Parameter | Description | Example | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
key mandatory | varchar This parameter is the unique Merchant Key provided by PayU for your merchant account. | Your Test Key | ||||||||||||||||
txnid mandatory | varchar This parameter is known as Transaction ID (or Order ID). It is the order reference number generated at your (Merchant's) end. It is an identifier that 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 the same Transaction ID again would fail. Hence, you must post us a unique transaction ID for every new transaction. Character limit: 25 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.' | fd3e847h2 | ||||||||||||||||
amount mandatory | float This parameter should contain the payment amount of the particular transaction. Note: Type-cast the amount to float type | 1000 | ||||||||||||||||
productinfo mandatory | varchar This parameter should contain a brief product description. It should be a string describing the product. Character limit: 100 | Time Magazine Subscription | ||||||||||||||||
firstname mandatory | varchar Must contain the first name of the customer. Character limit: 60 | Ashish | ||||||||||||||||
email mandatory | varchar Must contain the email of the customer. This information is helpful when it comes to issues related to fraud detection and chargebacks. Hence, it is a must to provide the correct information. Also, MIS reporting is shared with few issuing banks where email and mobile number is used to keep track of users using SI transactions. Character limit: 50 | [email protected] | ||||||||||||||||
phone mandatory | varchar Must contain the phone number of the customer. This information is helpful when it comes to issues related to fraud detection and chargebacks. Hence, it is required to provide the correct information. Character limit: 50 | 9876543210 | ||||||||||||||||
surl mandatory | surL is the acronym for Success URL. This parameter must contain the URL on which PayU will redirect the final response if the transaction is successful. | |||||||||||||||||
furl mandatory | furl is the acronym for Failure URL. This parameter must contain the URL on which PayU will redirect the final response if the transaction is failed. | |||||||||||||||||
pg mandatory | It defines the payment category for which you wish to perform UPI One-Time Mandate integration. For UPI, pg = UPI | UPI | ||||||||||||||||
bankcode mandatory | It defines the bank with which you wish to perform UPI Intent One-Time Mandate integration using the bank code. For UPI Intent, use INTENT. | UPI | ||||||||||||||||
txn_s2s_flow mandatory | This parameter must be passed with the values as 4 for UPI Intent. | |||||||||||||||||
pre_authorize mandatory for Pre-Auth | This parameter is set to 1 to Pre-authorization payment. | 1 | ||||||||||||||||
hash mandatory | Hash is a crucial parameter used to ensure that any data is not tampered while redirecting customer from the merchant website to PayU's payment interface while registration transactions. It is SHA-512 hash generated by encrypting values of merchant key, txnid, amount, productinfo, firstname, email, udf and si_details by merchant Salt. In the case of registration transaction, the formula used to calculate this hash is similar to the following: HASH = SHA512(sha512(key | txnid | amount | productinfo | firstname | udf1 | udf2 | udf3 | udf4 | udf5 | SALT)) |
Optional Parameters
| Parameter | Description | Example |
|---|---|---|
| si_details | This parameter contains the following information in JSON format: paymentStartDate, paymentEndDate. Example: {"paymentStartDate":"2024-07-24","paymentEndDate":"2024-07-28"} | {"paymentStartDate":"2024-07-24","paymentEndDate":"2024-07-28"} |
curl --request POST \
--url https://test.payu.in/_payment \
--header 'accept: text/plain' \
--header 'content-type: application/x-www-form-urlencoded' \
--data key=JPM7Fg \
--data pg=UPI \
--data bankcode=INTENT \
--data txn_s2s_flow=4 \
--data txnid=aso6787 \
--data siDetails='{"paymentStartDate": "2019-09-01","paymentEndDate": "2019-12-01"}' \
--data pre_authorize=1 \
--data amount=100.00 \
--data productinfo=iPhone \
--data firstname=Ashish \
--data [email protected] \
--data phone=9876543210 \
--data surl=https://apiplayground-response.herokuapp.com/ \
--data furl=https://apiplayground-response.herokuapp.com/ \
--data hash=8e8de8a3cf2ba999e16c0ffdb63a645074af4ad1aa0a8d66d81555a119c004e1791173fe6199084f256623664b250d3aeb50fc2c4cfc155e729d8811a157c98bimport requests
url = "https://test.payu.in/_payment"
headers = {"accept": "text/plain", "content-type": "application/x-www-form-urlencoded"}
data = {
"key": "JPM7Fg", "pg": "UPI", "bankcode": "INTENT", "txn_s2s_flow": "4", "txnid": "aso6787",
"siDetails": '{"paymentStartDate": "2019-09-01","paymentEndDate": "2019-12-01"}',
"pre_authorize": "1", "amount": "100.00", "productinfo": "iPhone",
"firstname": "Ashish", "email": "[email protected]", "phone": "9876543210",
"surl": "https://apiplayground-response.herokuapp.com/",
"furl": "https://apiplayground-response.herokuapp.com/",
"hash": "8e8de8a3cf2ba999e16c0ffdb63a645074af4ad1aa0a8d66d81555a119c004e1791173fe6199084f256623664b250d3aeb50fc2c4cfc155e729d8811a157c98b"
}
response = requests.post(url, headers=headers, data=data)
print(response.status_code)
print(response.text)const params = new URLSearchParams({
key: "JPM7Fg", pg: "UPI", bankcode: "UPI", vpa: "anything@payu",
txn_s2s_flow: "4", txnid: "aso6787",
siDetails: '{"paymentStartDate": "2019-09-01","paymentEndDate": "2019-12-01"}',
pre_authorize: "1", amount: "100.00", productinfo: "iPhone",
firstname: "Ashish", email: "[email protected]", phone: "9876543210",
surl: "https://apiplayground-response.herokuapp.com/",
furl: "https://apiplayground-response.herokuapp.com/",
hash: "8e8de8a3cf2ba999e16c0ffdb63a645074af4ad1aa0a8d66d81555a119c004e1791173fe6199084f256623664b250d3aeb50fc2c4cfc155e729d8811a157c98b"
});
const response = await fetch("https://test.payu.in/_payment", {
method: "POST",
headers: {"accept": "text/plain", "content-type": "application/x-www-form-urlencoded"},
body: params.toString()
});
console.log(response.status);
console.log(await response.text());<?php
$data = http_build_query(["key" => "JPM7Fg", "pg" => "UPI", "bankcode" => "INTENT",
"vpa" => "anything@payu", "txn_s2s_flow" => "4", "txnid" => "aso6787",
"siDetails" => '{"paymentStartDate": "2019-09-01","paymentEndDate": "2019-12-01"}',
"pre_authorize" => "1", "amount" => "100.00", "productinfo" => "iPhone",
"firstname" => "Ashish", "email" => "[email protected]", "phone" => "9876543210",
"surl" => "https://apiplayground-response.herokuapp.com/",
"furl" => "https://apiplayground-response.herokuapp.com/",
"hash" => "8e8de8a3cf2ba999e16c0ffdb63a645074af4ad1aa0a8d66d81555a119c004e1791173fe6199084f256623664b250d3aeb50fc2c4cfc155e729d8811a157c98b"]);
$ch = curl_init();
curl_setopt_array($ch, [CURLOPT_URL => "https://test.payu.in/_payment", CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["accept: text/plain","content-type: application/x-www-form-urlencoded"]]);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n"; echo curl_exec($ch); curl_close($ch);
?>import java.net.URI; import java.net.http.*;
public class IntentStep1 {
public static void main(String[] args) throws Exception {
String f = "key=JPM7Fg&pg=UPI&bankcode=INTENT&txn_s2s_flow=4&txnid=aso6787"
+ "&siDetails=%7B%22paymentStartDate%22%3A%222019-09-01%22%7D&pre_authorize=1"
+ "&amount=100.00&productinfo=iPhone&firstname=Ashish&email=ashish%40abc.com&phone=9876543210"
+ "&surl=https%3A%2F%2Fapiplayground-response.herokuapp.com%2F"
+ "&furl=https%3A%2F%2Fapiplayground-response.herokuapp.com%2F"
+ "&hash=8e8de8a3cf2ba999e16c0ffdb63a645074af4ad1aa0a8d66d81555a119c004e1791173fe6199084f256623664b250d3aeb50fc2c4cfc155e729d8811a157c98b";
var req = HttpRequest.newBuilder().uri(URI.create("https://test.payu.in/_payment"))
.header("accept","text/plain").header("content-type","application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(f)).build();
var res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode()); System.out.println(res.body());
}
}using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks;
class IntentStep1 {
static async Task Main() {
var c = new HttpClient(); c.DefaultRequestHeaders.Add("accept","text/plain");
var f = new FormUrlEncodedContent(new Dictionary<string,string>{
{"key","JPM7Fg"},{"pg","UPI"},{"bankcode","INTENT"},{ {"txn_s2s_flow","4"},{"txnid","aso6787"},
{"siDetails","{\"paymentStartDate\":\"2019-09-01\",\"paymentEndDate\":\"2019-12-01\"}"},
{"pre_authorize","1"},{"amount","100.00"},{"productinfo","iPhone"},
{"firstname","Ashish"},{"email","[email protected]"},{"phone","9876543210"},
{"surl","https://apiplayground-response.herokuapp.com/"},
{"furl","https://apiplayground-response.herokuapp.com/"},
{"hash","8e8de8a3cf2ba999e16c0ffdb63a645074af4ad1aa0a8d66d81555a119c004e1791173fe6199084f256623664b250d3aeb50fc2c4cfc155e729d8811a157c98b"}});
var r = await c.PostAsync("https://test.payu.in/_payment",f);
System.Console.WriteLine((int)r.StatusCode); System.Console.WriteLine(await r.Content.ReadAsStringAsync());
}
}Step 2: Check the response from PayU
Success scenario
For Intent, as part of response, Intent URL is returned. Now, merchant needs to use data received in intentURIData parameter, JSON decode the response and use URL to invoke intent at their end
{
"metaData": {
"message": null,
"referenceId": "test123",
"statusCode": null,
"txnId": "test989",
"txnStatus": "pending",
"unmappedStatus": "pending"
},
"result": {
"paymentId": "99999999",
"merchantName": "abc",
"merchantVpa": "abc@sbi",
"amount": "166.00",
"intentURIData": "upi://mandate?pa=abc@upi&pn=abc&mn=ONETIME&tid=test123&validitystart=02102024&validityend=15112024&am=166.00&amrule=MAX&recur=ONETIME&tr=test989&cu=INR&mc=6300&tn=UPIIntent&mode=13&purpose=01&orgid=400011&rev=N&block=Y&txnType=CREATE",
"acsTemplate": "PGh0bWw+PGJvZH... (truncated for brevity)",
"otpPostUrl": "https://pp78secure.payu.in/ResponseHandler.php"
}
}Failure scenarios
After the transaction is authorised by the customer, PayU will receive confirmation. PAyU will pass the confirmation to the merchant as webhook.
{
"metaData": {
"message": "Transaction failed due to invalid params shared by the merchant",
"referenceId": "dde7096af9db932a9fd09b9b4383d8be",
"statusCode": "E1101",
"txnId": "0c4931ddee7a4f69227f",
"txnStatus": "failed",
"unmappedStatus": "failure"
},
"result": {}
}Step 3: Capture a pre-authorized payment
To capture a pre-authorized payment, use the following command. After the API command is successful, the transaction would be captured and settled to you.
Mandatory Parameters
| Parameter | Description | |||
|---|---|---|---|---|
key mandatory | This parameter is the unique Merchant Key provided by PayU for your merchant account. The Merchant Key acts as the unique identifier (primary key) to identify a Merchant Account in our database. Sample value - YbfVda | |||
command mandatory | For initiating a capture transaction, the value of the parameter will be passed as - capture_transaction | |||
hash mandatory | This parameter must contain the hash value to be calculated at merchant end. Hash logic for this API is: sha512(key | command | var1 | Salt) |
var1 mandatory | This parameter must contain the payuId that was generated by PayU as part of Pre-authorization operation. | |||
var2 mandatory | This parameter contains the token, that is, merchant unique reference number. | |||
var3 mandatory | This parameter must contain the amount to be captured. |
curl --location --request POST 'https://info.payu.in/merchant/postservice.php?form=2' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--form 'key="JF***g"' \
--form 'command="capture_transaction"' \
--form 'hash="67411736ab98c59522492a12751a6015c41b87764019f9dc14052690c2c7af9095d31002fc109dcf3596c2f38792d56db6f6207b1989010f2adf51c144fa3019"' \
--form 'var1="15246574846"' \
--form 'var2="authorizeTransaction123"' \
--form 'var3="1"'import requests
url = "https://info.payu.in/merchant/postservice.php?form=2"
files = {"key": (None,"JF***g"), "command": (None,"capture_transaction"),
"hash": (None,"67411736ab98c59522492a12751a6015c41b87764019f9dc14052690c2c7af9095d31002fc109dcf3596c2f38792d56db6f6207b1989010f2adf51c144fa3019"),
"var1": (None,"15246574846"), "var2": (None,"authorizeTransaction123"), "var3": (None,"1")}
response = requests.post(url, files=files)
print(response.status_code)
print(response.text)const formData = new FormData();
formData.append("key","JF***g"); formData.append("command","capture_transaction");
formData.append("hash","67411736ab98c59522492a12751a6015c41b87764019f9dc14052690c2c7af9095d31002fc109dcf3596c2f38792d56db6f6207b1989010f2adf51c144fa3019");
formData.append("var1","15246574846"); formData.append("var2","authorizeTransaction123"); formData.append("var3","1");
const response = await fetch("https://info.payu.in/merchant/postservice.php?form=2",{method:"POST",body:formData});
console.log(response.status); console.log(await response.text());<?php
$ch = curl_init();
curl_setopt_array($ch, [CURLOPT_URL => "https://info.payu.in/merchant/postservice.php?form=2",
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => ["key"=>"JF***g","command"=>"capture_transaction",
"hash"=>"67411736ab98c59522492a12751a6015c41b87764019f9dc14052690c2c7af9095d31002fc109dcf3596c2f38792d56db6f6207b1989010f2adf51c144fa3019",
"var1"=>"15246574846","var2"=>"authorizeTransaction123","var3"=>"1"]]);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE)."\n"; echo curl_exec($ch); curl_close($ch);
?>import java.net.URI; import java.net.http.*; import java.nio.charset.StandardCharsets; import java.util.UUID;
public class CaptureStep3 {
public static void main(String[] args) throws Exception {
String b = UUID.randomUUID().toString();
String body = "--"+b+"\r\nContent-Disposition: form-data; name=\"key\"\r\n\r\nJF***g\r\n"
+"--"+b+"\r\nContent-Disposition: form-data; name=\"command\"\r\n\r\ncapture_transaction\r\n"
+"--"+b+"\r\nContent-Disposition: form-data; name=\"hash\"\r\n\r\n67411736ab98c59522492a12751a6015c41b87764019f9dc14052690c2c7af9095d31002fc109dcf3596c2f38792d56db6f6207b1989010f2adf51c144fa3019\r\n"
+"--"+b+"\r\nContent-Disposition: form-data; name=\"var1\"\r\n\r\n15246574846\r\n"
+"--"+b+"\r\nContent-Disposition: form-data; name=\"var2\"\r\n\r\nauthorizeTransaction123\r\n"
+"--"+b+"\r\nContent-Disposition: form-data; name=\"var3\"\r\n\r\n1\r\n--"+b+"--";
var req = HttpRequest.newBuilder().uri(URI.create("https://info.payu.in/merchant/postservice.php?form=2"))
.header("Content-Type","multipart/form-data; boundary="+b)
.POST(HttpRequest.BodyPublishers.ofString(body,StandardCharsets.UTF_8)).build();
var res = HttpClient.newHttpClient().send(req,HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode()); System.out.println(res.body());
}
}using System.Net.Http; using System.Threading.Tasks;
class CaptureStep3 {
static async Task Main() {
var c = new HttpClient();
var f = new MultipartFormDataContent();
f.Add(new StringContent("JF***g"),"key"); f.Add(new StringContent("capture_transaction"),"command");
f.Add(new StringContent("67411736ab98c59522492a12751a6015c41b87764019f9dc14052690c2c7af9095d31002fc109dcf3596c2f38792d56db6f6207b1989010f2adf51c144fa3019"),"hash");
f.Add(new StringContent("15246574846"),"var1"); f.Add(new StringContent("authorizeTransaction123"),"var2"); f.Add(new StringContent("1"),"var3");
var r = await c.PostAsync("https://info.payu.in/merchant/postservice.php?form=2",f);
System.Console.WriteLine((int)r.StatusCode); System.Console.WriteLine(await r.Content.ReadAsStringAsync());
}
}Sample response
{
"status": 1,
"msg": "Capture Request Queued",
"request_id": "Request ID",
"bank_ref_num": "Bank Reference Number"
}Step 4: Check Transaction Status
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.
Reference: For cancelling pre-auth payments, refer to Cancel a Pre-Authorized Transaction API.
Updated 2 days ago
