Native OTP

Integrate the Razorpay Native OTP feature with Custom Checkout to combat customer payment issues such as payment failures due to low internet speeds and bank page redirects.


Native OTP helps generate and verify OTP on the customers’ browser without redirecting them to their bank's ACS page for authentication. Since there will be no redirection using the customers’ browser, it will reduce the dependency on the customers’ browser network, reduce the drop-off rates, and give a seamless consumer experience for card transactions.

  • Increase success rates by up to 4%.
  • Reduce payment failures due to low internet speeds.
  • Avoid failures due to redirects to bank pages.
  • Offer a consistent experience on mobile and web checkout.

Follow the integration steps given below:

1.1

.

1.2

.

1.3

.

1.4

.

1.5

.

1.6

.

Order is an important step in the payment process.

  • An order should be created for every payment.
  • You can create an order using the . It is a server-side API call. Know how to Orders API.
  • The order_id received in the response should be passed to the checkout. This ties the Order with the payment and secures the request from being tampered.

The following is a sample API request and response for creating an order:

curl -X POST https://api.razorpay.com/v1/orders
-u [YOUR_KEY_ID]:[YOUR_KEY_SECRET]
-H 'content-type:application/json'
-d '{
"amount": 50000,
"currency": "INR",
"receipt": "rcptid_11",
"partial_payment": true,
"first_payment_min_amount": 23000
}'

Here is the list of parameters and their description for creating an order:

amount

mandatory

integer The transaction amount, expressed in the currency subunit. For example, for an actual amount of ₹299.35, the value of this field should be 29935.

currency

mandatory

string The currency in which the transaction should be made. See the

. Length must be 3 characters.

receipt

optional

string Your receipt id for this order should be passed here. Maximum length is 40 characters.

notes

optional

json 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”.

partial_payment

optional

boolean Indicates whether the customer can make a partial payment. Possible values:

  • true: The customer can make partial payments.
  • false (default): The customer cannot make partial payments.

id

mandatory

string Unique identifier of the customer. For example, cust_1Aa00000000004.

Know more about

.

The error response parameters are available in the

.

Validating the authentication type is critical. This will help you set the value of auth_type during

.

Watch Out!

If the value of auth_type is sent as an OTP for a BIN that is not validated successfully, the transaction will fail.

Use the getCardFlows method given below to check for the available flows on a given card number:

razorpay.getCardFlows('411111', (flows) => {
console.log(flows.otp);
});

Use the getCardFeatures method given below to get the card features:

{
"flows": {
"otp": true,
"recurring": false,
"iframe": false,
"emi": true
},
"type": "credit",
"issuer": "HDFC",
"network": "Diners Club",
"cobranding_partner": null,
"country": "IN",
"http_status_code": 200
}

While initiating payment for the card payment method, you must pass an additional parameter within the create payment function if the card flow function response is otp = true.

function createRazorpayPayment (data) {
rzp.createPayment(data, {
nativeotp: true
});
}

Use the sample code given below to display OTP UI to your customers:

rzp.on('payment.otp.required', function (data) {
// Show OTP UI
// data = {
// "metadata": {
// "issuer": "HDFC",
// "network": "MC",
// "last4": "9275",
// "iin": "512967"
// },
// "next": [
// "otp_submit",
// "otp_resend"
// ],
// "redirect": "https://api.razorpay.com/v1/payments/pay_E1xQsBuIZ02..."
// }
});

Handy Tips

  • If you want to redirect the user to the bank ACS page, you should use the URL present in the response for creating a payment.
  • To get post-transaction feedback from the bank page to your website, the callback URL needs to be defined while creating a payment. Razorpay will send the response to the defined callback URL after payment success or failure.

After entering the OTP, the customer can perform either:

OTP submission is a part of the payment authentication process where the customer submits the OTP received through your application's frontend.

The customer receives the OTP for card payments via their preferred notification medium - SMS or email.

Handy Tips

Do not perform any validation on the length of the OTP since this can vary across banks. The OTP, however, should not be blank.

Use the following function to enable customers to submit OTP

function submitRazorpayOTP (otp) {
rzp.submitOTP(otp);
}

There can be situations when customers must re-enter the OTP sent to them. The issuing bank determines the number of retries that the user is allowed. Given below is the sample code of the OTP Resend function:

function resendRazorpayOTP () {
rzp.resendOTP();
}

Customers can cancel the payment based on their requirements. Given below is the sample code of the OTP Cancel function:

function cancelRazorpayPayment () {
rzp.emit('payment.cancel');
}

Once the payment process is completed, Razorpay will make a POST request to the callback_url on whether the payment was a success or a failure.

You can easily verify the payment signature using our SDKs:

String secret = "<YOUR_KEY_SECRET>";
JSONObject options = new JSONObject();
options.put("razorpay_order_id", "order_IEIaMR65cu6nz3");
options.put("razorpay_payment_id", "pay_IH4NVgf4Dreq1l");
options.put("razorpay_signature", "0d4e745a1838664ad6c9c9902212a32d627d68e917290b0ad5f08ff4561bc50f");
boolean status = Utils.verifyPaymentSignature(options, secret);

If razorpay_payment_id is returned, the payment is successfully created and verified.

Handy Tips

A successful transaction results in creating the razorpay_order_id in your database. You can mark the corresponding transaction at your end as paid and notify the customer of the same.

You can use the sample code given below:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script
type="text/javascript"
src="https://checkout.razorpay.com/v1/razorpay.js"
></script>
</head>
<body>
<p>Pay Rs. 5000</p>
<h2>Payment Method</h2>
<p id="method"></p>
<button id="rzp-button1">Pay</button>
<button id="rzp-button2">pop-up top</button>
</body>
<script>
var razorpay = new Razorpay({
key: 'YOUR_KEY_ID',
image:
'https://www.carlogos.org/car-logos/lamborghini-logo-1000x1100-show.png',
callback_url: 'https://www.google.com/',
redirect: true,
});
razorpay.once('ready', function (response) {
// console.log(response.methods);
// document.getElementById("method").innerHTML = JSON.stringify(response.methods);
});
razorpay.getCardFlows('411111', (flows) => {
console.log(flows.otp);
});
var data = {
amount: 100,
email: 'gaurav.kumar@example.com',
contact: '9000090000',
//"order_id": "order_JyhxBsMXOOfJ4c",
method: 'card',
'card[name]': 'Gaurav Kumar',
'card[number]': '4111111111111111',
'card[cvv]': '566',
'card[expiry_month]': '10',
'card[expiry_year]': '26',
};
var btn = document.querySelector('#rzp-button1');
btn.addEventListener('click', function () {
razorpay.createPayment(data, {
nativeotp: true,
});
razorpay.on('payment.otp.required', function (data) {
// Show OTP UI
console.log(data);
});
// razorpay.submitOTP('1234');
//razorpay.resendOTP();
//razorpay.emit('payment.cancel');
});
var btn1 = document.querySelector('#rzp-button2');
btn1.addEventListener('click', function () {
razorpay.focus(); // will bring popup to top
});
</script>
</html>

Is this integration guide useful?