Prerequisites🔗
- Create a Razorpay account, if you have not done already.
- Generate API keys required to authenticate API requests sent to Razorpay servers.
- Check the best practices.
Third Party Validation
Know how Razorpay performs Third-Party Validation (TPV) of your customers' bank accounts in real-time using Razorpay Standard Integration.
Third-Party Validation (TPV) of bank accounts is a mandatory requirement for merchants in the BFSI (Banking, Financial Services and Insurance) sector dealing with Securities, Broking and Mutual Funds. As per Securities and Exchange Board of India (SEBI) guidelines, transactions must be made by the customers only from those bank accounts which are provided when they registered with your business.
With Razorpay, you can comply with the SEBI guidelines for online payment collections by offering TPV integrations with major banks at the Checkout. Customers can make payments using netbanking or UPI. UPI supports both collect and intent flows.
Handy Tips
You can issue Payment Links to customers to accept online payments from them through specific bank accounts. You can perform this third-party validation using our Payment Links API.
Feature Request
This is an on-demand feature. Please raise a request with our Support team to get this feature activated on your Razorpay account.
In TPV integration flow, Razorpay maps the customers' bank accounts to ensure that the payment is processed only from their registered bank accounts.
Given below are the steps:
Collect the bank account details provided by the customer at the time of registration.
Pass the bank account details to the bank_account
array of the Orders API:
Given below is the sample code when method
is netbanking
.
Copycurl -u <YOUR_KEY_ID>:<YOUR_KEY_SECRET> \
-X POST https://api.razorpay.com/v1/orders \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"method": "netbanking",
"receipt": "BILL13375649",
"currency": "INR",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
}'
CopyRazorpayClient razorpay = new RazorpayClient("[YOUR_KEY_ID]", "[YOUR_KEY_SECRET]");
ArrayList Offer = new ArrayList<String>();
Offer.add("offer_JTUADI4ZWBGWur");
JSONObject orderRequest = new JSONObject();
orderRequest.put("amount", 1000); // amount in the smallest currency unit
orderRequest.put("currency", "INR");
orderRequest.put("receipt", "BILL13375649");
orderRequest.put("method", "netbanking");
JSONObject bank_account = new JSONObject();
bank_account.put("account_number", "765432123456789");
bank_account.put("name", "Gaurav Kumar");
bank_account.put("ifsc, "HDFC0000053");
orderRequest.put("bank_account", bank_account);
Order order = razorpayclient.orders.create(orderRequest);
System.out.print(order);
Copyimport razorpay
client = razorpay.Client(auth=("YOUR_ID", "YOUR_SECRET"))
client.order.create({
{
"amount": 500,
"method": "netbanking",
"receipt": "BILL13375649",
"currency": "INR",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
})
Copy$api = new Api($key_id, $secret);
$api->order->create(array('amount' => 100, 'currency' => 'INR', bank_account => array( 'account_number' => '765432123456789', 'name' => 'Gaurav Kumar', 'ifsc' => 'HDFC0000053')));
CopyRazorpayClient client = new RazorpayClient(your_key_id, your_secret);
Dictionary<string, object> options = new Dictionary<string,object>();
options.Add("amount", 50000); // amount in the smallest currency unit
options.Add("receipt", "receipt#1");
options.Add("currency", "INR");
bank_account.account_number="765432123456789";
bank_account.name="Gaurav Kumar";
bank_account.ifsc="HDFC0000053";
options.Add("bank_account", bank_account);
Order order = client.Order.Create(options);
Copyrequire "razorpay"
Razorpay.setup('YOUR_KEY_ID', 'YOUR_SECRET')
order = Razorpay::Order.create amount: 50000, currency: 'INR', receipt: 'receipt#1', bank_account: { account_number: '765432123456789', name: 'Gaurav Kumar', ifsc: 'HDFC0000053'}
Copyvar instance = new Razorpay({ key_id: 'YOUR_KEY_ID', key_secret: 'YOUR_SECRET' })
instance.orders.create({
amount: 50000,
currency: "INR",
receipt: "receipt#1",
bank_account: {
account_number: "765432123456789",
name: "Gaurav Kumar",
ifsc: "HDFC0000053"
}
})
Copyimport ( razorpay "github.com/razorpay/razorpay-go" )
client := razorpay.NewClient("YOUR_KEY_ID", "YOUR_SECRET")
data := map[string]interface{}{
"amount": 50000,
"currency": "INR",
"receipt": "receipt#1",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
}
body, err := client.Order.Create(data, nil)
Copy{
"id": "order_GAWN9beXgaqRyO",
"entity": "order",
"amount": 500,
"amount_paid": 0,
"amount_due": 500,
"currency": "INR",
"receipt": "BILL13375649",
"offer_id": null,
"status": "created",
"attempts": 0,
"notes": [],
"created_at": 1573044247
}
Given below is the sample code when method
is upi
.
Copycurl -u <YOUR_KEY_ID>:<YOUR_KEY_SECRET> \
-X POST https://api.razorpay.com/v1/orders \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"method": "upi",
"receipt": "BILL13375649",
"currency": "INR",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
}'
CopyRazorpayClient razorpay = new RazorpayClient("[YOUR_KEY_ID]", "[YOUR_KEY_SECRET]");
ArrayList Offer = new ArrayList<String>();
Offer.add("offer_JTUADI4ZWBGWur");
JSONObject orderRequest = new JSONObject();
orderRequest.put("amount", 1000); // amount in the smallest currency unit
orderRequest.put("currency", "INR");
orderRequest.put("receipt", "BILL13375649");
orderRequest.put("method", "upi");
JSONObject bank_account = new JSONObject();
bank_account.put("account_number", "765432123456789");
bank_account.put("name", "Gaurav Kumar");
bank_account.put("ifsc, "HDFC0000053");
orderRequest.put("bank_account", bank_account);
Order order = razorpayclient.orders.create(orderRequest);
System.out.print(order);
Copyimport razorpay
client = razorpay.Client(auth=("YOUR_ID", "YOUR_SECRET"))
client.order.create({
{
"amount": 500,
"method": "upi",
"receipt": "BILL13375649",
"currency": "INR",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
})
Copy$api = new Api($key_id, $secret);
$api->order->create(array('amount' => 100, 'method' => 'upi', 'currency' => 'INR', bank_account => array( 'account_number' => '765432123456789', 'name' => 'Gaurav Kumar', 'ifsc' => 'HDFC0000053')));
CopyRazorpayClient client = new RazorpayClient(your_key_id, your_secret);
Dictionary<string, object> options = new Dictionary<string,object>();
options.Add("amount", 50000); // amount in the smallest currency unit
options.Add("receipt", "receipt#1");
options.Add("currency", "INR");
options.Add("method", "upi");
bank_account.account_number="765432123456789";
bank_account.name="Gaurav Kumar";
bank_account.ifsc="HDFC0000053";
options.Add("bank_account", bank_account);
Order order = client.Order.Create(options);
Copyrequire "razorpay"
Razorpay.setup('YOUR_KEY_ID', 'YOUR_SECRET')
order = Razorpay::Order.create amount: 50000, currency: 'INR', receipt: 'receipt#1', method: 'upi', bank_account: { account_number: '765432123456789', name: 'Gaurav Kumar', ifsc: 'HDFC0000053'}
Copyvar instance = new Razorpay({ key_id: 'YOUR_KEY_ID', key_secret: 'YOUR_SECRET' })
instance.orders.create({
amount: 50000,
currency: "INR",
receipt: "receipt#1",
method: 'upi',
bank_account: {
account_number: "765432123456789",
name: "Gaurav Kumar",
ifsc: "HDFC0000053"
}
})
Copyimport ( razorpay "github.com/razorpay/razorpay-go" )
client := razorpay.NewClient("YOUR_KEY_ID", "YOUR_SECRET")
data := map[string]interface{}{
"amount": 50000,
"currency": "INR",
"receipt": "receipt#1",
"method": "upi",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
}
body, err := client.Order.Create(data)
Copy{
"id": "order_GAWRjlWkVcRh0V",
"entity": "order",
"amount": 500,
"amount_paid": 0,
"amount_due": 500,
"currency": "INR",
"receipt": "BILL13375649",
"offer_id": null,
"status": "created",
"attempts": 0,
"notes": [],
"created_at": 1573044206
}
Given below is the sample code when method
is not passed.
Copycurl -u <YOUR_KEY_ID>:<YOUR_KEY_SECRET> \
-X POST https://api.razorpay.com/v1/orders \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"receipt": "BILL13375649",
"currency": "INR",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
}'
CopyRazorpayClient razorpay = new RazorpayClient("[YOUR_KEY_ID]", "[YOUR_KEY_SECRET]");
ArrayList Offer = new ArrayList<String>();
Offer.add("offer_JTUADI4ZWBGWur");
JSONObject orderRequest = new JSONObject();
orderRequest.put("amount", 1000); // amount in the smallest currency unit
orderRequest.put("currency", "INR");
orderRequest.put("receipt", "BILL13375649");
JSONObject bank_account = new JSONObject();
bank_account.put("account_number", "765432123456789");
bank_account.put("name", "Gaurav Kumar");
bank_account.put("ifsc, "HDFC0000053");
orderRequest.put("bank_account", bank_account);
Order order = razorpayclient.orders.create(orderRequest);
System.out.print(order);
Copyimport razorpay
client = razorpay.Client(auth=("YOUR_ID", "YOUR_SECRET"))
client.order.create({
{
"amount": 500,
"receipt": "BILL13375649",
"currency": "INR",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
})
Copy$api = new Api($key_id, $secret);
$api->order->create(array('amount' => 100, 'currency' => 'INR', bank_account => array( 'account_number' => '765432123456789', 'name' => 'Gaurav Kumar', 'ifsc' => 'HDFC0000053')));
CopyRazorpayClient client = new RazorpayClient(your_key_id, your_secret);
Dictionary<string, object> options = new Dictionary<string,object>();
options.Add("amount", 50000); // amount in the smallest currency unit
options.Add("receipt", "receipt#1");
options.Add("currency", "INR");
bank_account.account_number="765432123456789";
bank_account.name="Gaurav Kumar";
bank_account.ifsc="HDFC0000053";
options.Add("bank_account", bank_account);
Order order = client.Order.Create(options);
Copyrequire "razorpay"
Razorpay.setup('YOUR_KEY_ID', 'YOUR_SECRET')
order = Razorpay::Order.create amount: 50000, currency: 'INR', receipt: 'receipt#1', bank_account: { account_number: '765432123456789', name: 'Gaurav Kumar', ifsc: 'HDFC0000053'}
Copyvar instance = new Razorpay({ key_id: 'YOUR_KEY_ID', key_secret: 'YOUR_SECRET' })
instance.orders.create({
amount: 50000,
currency: "INR",
receipt: "receipt#1",
bank_account: {
account_number: "765432123456789",
name: "Gaurav Kumar",
ifsc: "HDFC0000053"
}
})
Copyimport ( razorpay "github.com/razorpay/razorpay-go" )
client := razorpay.NewClient("YOUR_KEY_ID", "YOUR_SECRET")
data := map[string]interface{}{
"amount": 50000,
"currency": "INR",
"receipt": "receipt#1",
"bank_account": {
"account_number": "765432123456789",
"name": "Gaurav Kumar",
"ifsc": "HDFC0000053"
}
}
body, err := client.Order.Create(data)
Copy{
"id": "order_GAWRjlWkVcRh0V",
"entity": "order",
"amount": 500,
"amount_paid": 0,
"amount_due": 500,
"currency": "INR",
"receipt": "BILL13375649",
"offer_id": null,
"status": "created",
"attempts": 0,
"notes": [],
"created_at": 1573044206
}
Create a request payload using the following attributes:
amount
mandatoryinteger
The transaction amount expressed in paise (currency supported is INR). For example, for an actual amount of ₹1, the value of this field should be 100
.
currency
mandatorystring
The currency in which the transaction should be made. You can create Orders in INR only.
receipt
optionalstring
Receipt number that corresponds to this Order, set for your internal reference. Maximum length 40 characters.
notes
optionaljson object
Key-value pair that can be used to store additional information about the entity. Maximum 15 key-value pairs, 256 characters (maximum) each. For example, "note_key": "Beam me up Scotty”
.
method
optionalstring
The payment method used to make the payment. If this parameter is not passed, customers will be able to make payments using both netbanking and UPI payment methods. Possible values:
netbanking
: Customers can make payments only using netbanking.upi
: Customers can make payments only using UPI.bank_account
Details of the bank account that the customer has provided at the time of registration.
account_number
mandatorystring
The bank account number from which the customer should make the payment. For example, 765432123456789
. Payments will not be processed for an incorrect account number.name
optionalstring
The name linked to the bank account. For example, Gaurav Kumar
.ifsc
mandatorystring
The bank IFSC. For example, HDFC0000053
.Send the order_id
obtained in the response of the previous step along with the other Checkout attributes to trigger Razorpay Checkout.
Following are two sample codes for Checkout:
|
Copy-paste the form parameters as options
in your HTML code:
Copy<button id="rzp-button1">Pay</button>
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
var options = {
"key": "YOUR_KEY_ID", // Enter the Key ID generated from the Dashboard
"amount": "50000", // Amount is in currency subunits. Default currency is INR. Hence, 50000 refers to 50000 paise
"currency": "INR",
"name": "Acme Corp",
"description": "Test Transaction",
"image": "https://example.com/your_logo",
"order_id": "order_Dd3Wbag7QXDuuL", //This is a sample Order ID. Pass the `id` obtained in the response of Step 1
"handler": function (response){
alert(response.razorpay_payment_id);
alert(response.razorpay_order_id);
alert(response.razorpay_signature)
},
"prefill": {
"name": "Gaurav Kumar",
"email": "gaurav.kumar@example.com",
"contact": "9999999999"
},
"notes": {
"address": "Razorpay Corporate Office"
},
"theme": {
"color": "#3399cc"
}
};
var rzp1 = new Razorpay(options);
rzp1.on('payment.failed', function (response){
alert(response.error.code);
alert(response.error.description);
alert(response.error.source);
alert(response.error.step);
alert(response.error.reason);
alert(response.error.metadata.order_id);
alert(response.error.metadata.payment_id);
});
document.getElementById('rzp-button1').onclick = function(e){
rzp1.open();
e.preventDefault();
}
</script>
Copy<button id="rzp-button1">Pay</button>
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
var options = {
"key": "YOUR_KEY_ID", // Enter the Key ID generated from the Dashboard
"amount": "50000", // Amount is in currency subunits. Default currency is INR. Hence, 50000 refers to 50000 paise
"currency": "INR",
"name": "Acme Corp",
"description": "Test Transaction",
"image": "https://example.com/your_logo",
"order_id": "order_Dd3Wbag7QXDuuL", //This is a sample Order ID. Pass the `id` obtained in the response of Step 1
"callback_url": "https://eneqd3r9zrjok.x.pipedream.net/",
"prefill": {
"name": "Gaurav Kumar",
"email": "gaurav.kumar@example.com",
"contact": "9999999999"
},
"notes": {
"address": "Razorpay Corporate Office"
},
"theme": {
"color": "#3399cc"
}
};
var rzp1 = new Razorpay(options);
document.getElementById('rzp-button1').onclick = function(e){
rzp1.open();
e.preventDefault();
}
</script>
Know more about the Checkout Form Fields.
Handy Tips
rzp1.open()
) should be invoked by your site's JavaScript. This may or may not be a user-driven action such as a click.upi
in the Orders API.At the Checkout, customers complete the payment using the payment methods passed during the order creation.
The supported payment methods are netbanking
and upi
. Razorpay Checkout for each payment method is displayed as below:
The payment is marked as successful only when the bank account details entered in the order match those entered by the customer on the Checkout. If the customer tries to make payment with an account other than the registered account, Razorpay will fail the transaction.
The way you handle payment success and failure scenarios depends on the Checkout sample code you opted for in the previous step.
If you used Sample Code with Handler Function:
Customer sees your application web page, and the Checkout returns the response object of the successful payment (razorpay_payment_id
, razorpay_order_id
and razorpay_signature
). You need to collect these and send them to your server.
Copy "handler": function (response){
alert(response.razorpay_payment_id);
alert(response.razorpay_order_id);
alert(response.razorpay_signature)}
On payment failure, the customer is notified about the reason for failure and requested to retry the payment.
Copyrzp1.on('payment.failed', function (response){
alert(response.error.code);
alert(response.error.description);
alert(response.error.source);
alert(response.error.step);
alert(response.error.reason);
alert(response.error.metadata.order_id);
alert(response.error.metadata.payment_id);
}
Know more about the error parameters.
If you used the Sample Code with the Callback URL:
On Payment Success:
When you use a Callback URL, the response object of the successful payment (razorpay_payment_id
, razorpay_order_id
and razorpay_signature
) is submitted to the Callback URL. Only successful authorizations are auto-submitted.
On Payment Failure:
In case of failed payments, the Checkout Form is displayed again for payment retry.
A successful payment returns the following fields to the Checkout form.
You need to store these fields in your server.
You can confirm the authenticity of these details by verifying the signature in the next step.
Copy{
"razorpay_payment_id": "pay_29QQoUBi66xm2f",
"razorpay_order_id": "order_9A33XWu170gUtm",
"razorpay_signature": "9ef4dffbfd84f1318f6739a3ce19f9d85851857ae648f114332d8401e0949a3d"
}
razorpay_payment_id
string
Unique identifier for the payment returned by Checkout only for successful payments.razorpay_order_id
string
Unique identifier for the order returned by Checkout.razorpay_signature
string
Signature returned by the Checkout. This is used to verify the payment.This is a mandatory step to confirm the authenticity of the details returned to the Checkout form for successful payments.
To verify the razorpay_signature
returned to you by the Checkout form:
Create a signature in your server using the following attributes:
order_id
: Retrieve the order_id
from your server. Do not use the razorpay_order_id
returned by Checkout.razorpay_payment_id
: Returned by Checkout.key_secret
: Available in your server.key_secret
that was generated from the Razorpay Dashboard.Use the SHA256 algorithm, the razorpay_payment_id
and the order_id
to construct a HMAC hex digest as shown below:
Copygenerated_signature = hmac_sha256(order_id + "|" + razorpay_payment_id, secret); if (generated_signature == razorpay_signature) { payment is successful }
If the signature you generate on your server matches the razorpay_signature
returned to you by the Checkout form, the payment received is from an authentic source.
Given below are the sample codes for payment signature verification.
Copy/**
* This class defines common routines for generating
* authentication signatures for Razorpay Webhook requests.
*/
public class Signature
{
private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
/**
* Computes RFC 2104-compliant HMAC signature.
* * @param data
* The data to be signed.
* @param key
* The signing key.
* @return
* The Base64-encoded RFC 2104-compliant HMAC signature.
* @throws
* java.security.SignatureException when signature generation fails
*/
public static String calculateRFC2104HMAC(String data, String secret)
throws java.security.SignatureException
{
String result;
try {
// get an hmac_sha256 key from the raw secret bytes
SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), HMAC_SHA256_ALGORITHM);
// get an hmac_sha256 Mac instance and initialize with the signing key
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
mac.init(signingKey);
// compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(data.getBytes());
// base64-encode the hmac
result = DatatypeConverter.printHexBinary(rawHmac).toLowerCase();
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
return result;
}
}
Copyuse Razorpay\Api\Api;
$api = new Api($key_id, $key_secret);
$attributes = array('razorpay_signature' => '23233', 'razorpay_payment_id' => '332' , 'razorpay_order_id' => '12122');
$order = $api->utility->verifyPaymentSignature($attributes)
Copyrequire 'razorpay'
Razorpay.setup('key_id', 'key_secret')
payment_response = {
'razorpay_order_id': '12122',
'razorpay_payment_id': '332',
'razorpay_signature': '23233'
}
Razorpay::Utility.verify_payment_signature(payment_response)
Copyimport razorpay
client = razorpay.Client(auth=("YOUR_ID", "YOUR_SECRET"))
client.utility.verify_payment_signature({
'razorpay_order_id': razorpay_order_id,
'razorpay_payment_id': razorpay_payment_id,
'razorpay_signature': razorpay_signature
})
Copy Dictionary<string, string> attributes = new Dictionary<string, string>();
attributes.Add("razorpay_payment_id", paymentId);
attributes.Add("razorpay_order_id", Request.Form["razorpay_order_id"]);
attributes.Add("razorpay_signature", Request.Form["razorpay_signature"]);
Utils.verifyPaymentSignature(attributes);
Copyvar { validatePaymentVerification } = require('./dist/utils/razorpay-utils');
validatePaymentVerification({"order_id": razorpayOrderId, "payment_id": razorpayPaymentId }, signature, secret);
Copyimport (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"encoding/hex"
"fmt"
)
func main() {
signature := "477d1cdb3f8122a7b0963704b9bcbf294f65a03841a5f1d7a4f3ed8cd1810f9b"
secret := "qp3zKxwLZxbMORJgEVWi3Gou"
data := "order_J2AeF1ZpvfqRGH|pay_J2AfAxNHgqqBiI"
//fmt.Printf("Secret: %s Data: %s\n", secret, data)
// Create a new HMAC by defining the hash type and the key (as byte array)
h := hmac.New(sha256.New, []byte(secret))
// Write Data to it
_, err := h.Write([]byte(data))
if err != nil {
panic(err)
}
// Get result and encode as hexadecimal string
sha := hex.EncodeToString(h.Sum(nil))
fmt.Printf("Result: %s\n", sha)
if subtle.ConstantTimeCompare([]byte(sha), []byte(signature)) == 1 {
fmt.Println("Works")
}
}
After you have successfully completed the integration, you can set up webhooks, make test payments, replace test key with live key and integrate with other APIs.
After payment is authorized
, you need to capture it to settle the amount to your bank account as per the settlement schedule. Payments that are not captured are auto-refunded after a fixed time.
Know more about Capture Settings for payments.
The transaction timeout is applicable only when your customer attempts the payment.
The timeout is 3 to 15 minutes for an attempted payment. If there is a payment failure due to timeout, the customer is redirected to the Checkout page.
How Payment Gateway Works
Payment States
Settlements
Refunds
Accept UPI payments
ON THIS PAGE