Element Javascript SDK
The Element SDK allows you to build your own UI and accept payments through Cashfree.
Build your own UI (BYOU)
Element is our SDK solution for accepting payments when merchants want to display their own UI.
Element is our SDK solution for accepting payments when merchants want to display their own UI. Element works by binding itself to your UI elements. It can then process payments by using the values from those elements and initiating payment processing.
Resources
The SDK for sandbox and production are different. Both are listed below.
- Sandbox:
<script src="https://sdk.cashfree.com/js/core/1.0.26/bundle.sandbox.js"></script>
- Production:
<script src="https://sdk.cashfree.com/js/core/1.0.26/bundle.prod.js"></script>
Step 1: Initialize the Core SDK
Make sure you have included the Cashfree core SDK in your file.
const options = {}
const cfCheckout = Cashfree.initializeApp(options);
The orderToken
is the same which we generated in the previous step when creating an order.
The options
are handler methods which Cashfree SDK will invoke once the payment has completed.
name | type | required | description |
---|---|---|---|
onPaymentSuccess | Function (callback) | Yes | Handle payment success |
onPaymentFailure | Function (callback) | Yes | Handler for payment failure |
onError | Function (callback) | Yes | Handler when there in an error while processing payment |
Here is an example demonstrating how to initialise the options
.
const options = {
onPaymentSuccess: function(data) {
console.log("Success:", data);
/*
{
order:{
orderId: "some-orderid",
orderStatus: "PAID"
},
transaction:{
txStatus: "SUCCESS,
txMsg: "Transaction Message",
transactionId: 1232132,
transactionAmount: 1.00
}
}
*/
},
onPaymentFailure: function(data) {
console.log("Failure:", data);
/*
{
order:{
orderId: "some-orderid",
orderStatus: "ACTIVE"
},
transaction:{
txStatus: "FAILED,
txMsg: "Transaction Message",
transactionId: 1232132,
transactionAmount: 1.00
}
}
*/
},
onError: function(data) {
console.log("Error:", data);
/*
{
message: "Invalid card number"
paymentMode: "card"
type: "input_validation_error"
}
*/
},
};
Step 2: Introducing Elements
When you use the core SDK you will be rendering the payment UI by yourself. To help the SDK capture these details for payment processing, you have to tag these with specific elements which the SDK understands.
There are two ways you can configure elements in the SDK. You can either pass them individually for throw an array.
Passing a single element
const el = cfCheckout.element({
pay: document.getElementById('pay-card'),
type: 'card',
});
el.on('change', function(data){
console.log(data)
});
Passing an array
cfCheckout.elements([
{
pay: document.getElementById('pay-card'),
type: 'card',
onChange: cardEventHandler
},
{
pay: document.getElementById('pay-intent'),
type: 'upi-intent',
onChange: upiIntentHandler
}
])
The sdk will emit the change
event which will help you ensure that the input provided is valid. For example - if the card number passes basic checks like Luhn check etc. In the next step, we will show you how to accept payments for different payment instruments.
Step 3: Building components
Card
To accept card payments, you must ask the customer for their card details - card number, expiry month, expiry year, cvv and cardholder name. Prepare your html as below.
<div id="pay-card">
<table>
<tr><td>Card number</td><td><input type="text" value="" data-card-number> </td></tr>
<tr><td>card expiry MM</td><td><input type="text" value="" data-card-expiry-mm> </td></tr>
<tr><td>card expiry YY</td><td><input type="text" value="" data-card-expiry-yy> </td></tr>
<tr><td>card cvv</td><td><input type="password" value="" data-card-cvv></td></tr>
<tr><td>Card holder</td><td><input type="text" value="" data-card-holder></td></tr>
</table>
<button id="pay-card-btn">Pay</button>
</div>
As you can see here the element created is pay-card
. This element is a collection of HTML form inputs with each having a custom attribute. These input HTML elements capture the payment information.
attribute | description |
---|---|
data-card-number | Holds card number |
data-card-expiry-mm | Holds card expiry month in MM. Example 01 for January and 12 for December. Has to be of length == 2. |
data-card-expiry-yy | Holds card expiry year in YY format. Example 21 for 2021, 22 for 2022 etc. Has to be of length == 2. |
data-card-cvv | Holds card cvv. Recommended to use it as type="password" |
data-card-holder | Holds card holder name |
Once you have the html form ready, here is a sample javascript to verify details and initiate payment.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<title>Cashfree Sample</title>
</head>
<body class="container">
<h1>Test Order Elemental</h1>
<div class="row">
<div class="d-flex flex-column">
<p>Order Amount: 1</p>
<div id="pay-card">
<div class="form-group">
<label for="my-input">Holder Name</label>
<input class="form-control" type="text" data-card-holder value="John Doe">
</div>
<div class="form-group">
<label for="my-input">Card Number</label>
<input class="form-control" type="text" data-card-number value="4111111111111111">
</div>
<div class="form-group">
<label for="my-input">Expiry MM</label>
<input class="form-control" type="text" data-card-expiry-mm value="12">
</div>
<div class="form-group">
<label for="my-input">Holder Name</label>
<input class="form-control" type="text" data-card-expiry-yy value="24">
</div>
<div class="form-group">
<label for="my-input">CVV</label>
<input class="form-control" type="password" data-card-cvv value="123">
</div>
<hr>
<button class="btn btn-primary" id="pay-btn">Pay</button>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://sdk.cashfree.com/js/core/1.0.26/bundle.sandbox.js"></script>
<script src="main.js"></script>
</body>
</html>
$(document).ready(function (e) {
let isCardReadyToPay = true;
const config = {
onPaymentSuccess: function (data) {
if (data.order.status == "PAID") {
$.ajax({
url: "checkstatus.php?order_id=" + data.order.orderId,
success: function (result) {
if (result.order_status == "PAID") {
alert("Order PAID");
}
},
});
}
},
onPaymentFailure: function (data) {
alert(data.transaction.txMsg);
},
onError: function (err) {
alert(err.message);
},
};
const cfCheckout = Cashfree.initializeApp(config);
cfCheckout.elements([
{
pay: document.getElementById("pay-card"),
type: "card",
onChange: cardEventHandler,
},
]);
function cardEventHandler(data) {
isCardReadyToPay = data.isReadyToPay;
}
let order_token = "";
$("#pay-btn").click(async function () {
if (isCardReadyToPay)
if (order_token == "") {
$.ajax({
url: "fetchtoken.php",
success: async function (result) {
order_token = result["order_token"];
await cfCheckout.pay(order_token, "card");
},
});
} else {
await cfCheckout.pay(order_token, "card");
}
});
});
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.cashfree.com/pg/orders",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"customer_details\":{\"customer_id\":\"12345\",\"customer_email\":\"[email protected]\",\"customer_phone\":\"1299087801\"},\"order_amount\":1,\"order_currency\":\"INR\",\"order_note\":\"test order\"}",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json",
"x-api-version: 2022-01-01",
"x-client-id: TEST_CLIENT_ID",
"x-client-secret: TEST_CLIENT_SECRET"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(array("error" => 1));
echo "cURL Error #:" . $err;
die();
} else {
$result = json_decode($response, true);
header('Content-Type: application/json; charset=utf-8');
$output = array("order_token" => $result["order_token"]);
echo json_encode($output);
die();
}
?>
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.cashfree.com/pg/orders/" . $_GET["order_id"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json",
"x-api-version: 2021-05-21",
"x-client-id: TEST_CLIENT_ID",
"x-client-secret: TEST_CLIENT_SECRET"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(array("error" => 1));
echo "cURL Error #:" . $err;
die();
} else {
$result = json_decode($response, true);
header('Content-Type: application/json; charset=utf-8');
$output = array("order_status" => $result["order_status"]);
echo json_encode($output);
die();
}
?>
UPI Intent
The SDK allows you to capture UPI payments through different methods - intent, a collect request or by creating a QR code. To build an intent workflow, you need to tell the SDK which app is calling the intent.
<div id="pay-intent">
UPI App <select data-upi-provider>
<option value="">select</option>
<option value="gpay">gpay</option>
<option value="phonepe">phonepe</option>
<option value="paytm">paytm</option>
<option value="bhim">bhim</option>
</select>
<button id="pay-intent-btn">Pay</button>
</div>
To setup api-intent we will just add the same javascript code which helps the SDK identify the html element for intent.
const config = {
onPaymentSuccess: function(data) {},
onPaymentFailure: function(data) {},
onError: function(err) {},
};
const cfCheckout = Cashfree.initializeApp(config);
let isUPIIntentReady = false;
let order_token = ""; //order_token is received after create order api is called
cfCheckout.elements([
{
pay: document.getElementById('pay-intent'),
type: 'upi-intent',
onChange: upiIntentHandler
}
])
function upiIntentHandler(data){
console.log("UPI intent --> ", data)
isUPIIntentReady = data.isReadyToPay
}
$("#pay-intent-btn").click(async function() {
if(!isUPIIntentReady) {
alert("UPI Intent not ready to pay!")
return
}
await cfCheckout.pay(order_token, 'upi-intent');
});
The only attribute we need for upi intent is data-upi-provider.
attribute | description |
---|---|
data-upi-provider | Hold the identifier for the mobile app. Values can be gpay , phonepe , paytm and bhim |
UPI Collect
UPI collect based payments refer to customers entering the UPI ID (8987123112@ybl or rohit@okhdfc). We will then send a notification to the customer on their UPI application to approve this payment. Once the customer approves the payment in the upi mobile application, and has enough funds the payment will be completed.
Here is a simple html to render this payment form.
<div id="pay-collect">
UPI Collect <input type="text" value="testsuccess@gocash" data-upi-id>
<button id="pay-collect-btn">Pay</button>
</div>
To process payment here is the sample javascript code.
let isUPICollectReady = false;
let order_token = ""; //order_token is received after create order api is called
cfCheckout.elements([
{
pay: document.getElementById('pay-collect'),
type: 'upi-collect',
onChange: upiCollectHandler
}
]);
function upiCollectHandler(data){
console.log("UPI collect --> ", data)
isUPICollectReady = data.isReadyToPay
}
$("#pay-collect-btn").click(async function() {
if(!isUPICollectReady) {
alert("UPI collect not ready to pay!")
return
}
await cfCheckout.pay(order_token, 'upi-collect')
});
There is only element attribute required for UPI checkout flow - the UPI id.
attribute | description |
---|---|
data-upi-id | Holds the upi id of the customer |
UPI QR Code
You can also choose to display a QR code which can be scanned by any UPI app to complete the payment. We do not require any input attributes to build the QR code.
<button id="pay-qr-btn">Pay</button>
<script>
document.getElementById('pay-qr-btn').addEventListener('click', async () => {
await cfCheckout.pay(orderToken, 'upi-qrcode');
});
</script>
Mobile applications/Wallets
The SDK allows you to pay using different wallets and mobile applications, for instance - Amazon Pay, Google Pay, PhonePe, Jio money, Paytm, Airtel money, Freecharge, etc.
There are two attributes which we need to complete payments for these wallets - the wallet name and customers phone number.
attribute | description |
---|---|
data-app-name | Holds the app name. Values can be gpay phonepe paytm amazon airtel freecharge mobikwik jio ola |
data-app-phone | Phone number of the customer |
Below is a sample payment form to collect app details. We need basically need the two attributes - data-app-name
and data-app-phone
.
<div id="pay-app">
<select data-app-name>
<option value="">select</option>
<option value="gpay">gpay</option>
<option value="phonepe">phonepe</option>
<option value="paytm">paytm</option>
<option value="amazon">amazon</option>
<option value="airtel">airtel</option>
<option value="freecharge">freecharge</option>
<option value="mobikwik">mobikwik</option>
<option value="jio">jio</option>
<option value="ola">ola</option>
</select>
<input type="text" data-app-phone />
<button id="pay-app-btn">Pay</button>
</div>
The javascript code is similar to the previous flows.
let isAppReady = false;
let order_token = "";
cfCheckout.elements([
{
pay: document.getElementById('pay-app'),
type: 'app',
onChange: appEventHandler
},
]);
function appEventHandler(data){
console.log("App --> ", data)
isAppReady = data.isReadyToPay
}
$("#pay-app-btn").click(async function() {
if(!isAppReady) {
alert("App not ready to pay!")
return
}
await cfCheckout.pay(order_token, 'app')
});
BNPL
The SDK allows you to pay using different paylater applications, for instance - Lazypay, ZestMoney, Flexipay, Kotak, OlaPostpaid, etc.
There are two attributes that we need to complete payments for these wallets - the provider name and customers phone number.
attribute | description |
---|---|
data-provider | Holds the app name. Values can be lazypay zestmoney olapostpaid kotak flexipay simpl |
data-paylater-phone | Phone number of the customer |
Below is a sample payment form to collect paylater details. We need basically need the two attributes - data-provider
and data-paylater-phone
.
<div id="pay-later">
<select data-provider>
<option value="">select</option>
<option value="lazypay">Lazy Pay</option>
<option value="olapostpaid">OlaMoney Post Paid</option>
<option value="flexipay">Hdfc Paylater</option>
<option value="kotak">Kotak Paylater</option>
<option value="zestmoney">Zestmoney pay later</option>
<option value="simpl">Simpl</option>
</select>
<input type="text" data-paylater-phone />
<button id="pay-later-btn">Pay</button>
</div>
The javascript code is similar to the previous flows.
let isProviderReady = false;
let order_token = "";
cfCheckout.elements([
{
pay: document.getElementById('pay-later'),
type: 'paylater',
onChange: paylaterEventHandler
},
]);
function paylaterEventHandler(data){
console.log("App --> ", data)
isProviderReady = data.isReadyToPay
}
$("#pay-later-btn").click(async function() {
if(!isProviderReady) {
alert("App not ready to pay!")
return
}
await cfCheckout.pay(order_token, 'paylater')
});
Credit Card EMI
To accept credit card EMI payments, you must ask the customer for the following details - card number, card expiry month, card expiry year, card CVV, bank name, and tenure.
attribute | description |
---|---|
data-emi-number | Holds card number |
data-emi-expiry-mm | Holds card expiry month in MM. Example 01 for January and 12 for December. Has to be of length == 2. |
data-emi-expiry-yy | Holds card expiry year in YY format. Example 21 for 2021, 22 for 2022, etc. Has to be of length == 2. |
data-emi-cvv | Holds card CVV. Recommended to use it as type="password" |
data-emi-bank | Holds Bank Name for the corresponding card.Values can be HDFC ICICI Kotak RBL BOB Standard Chartered |
data-emi-tenure | Holds Tenure for the EMI payment. Values are: HDFC : 3 6 9 12 ICICI : 3 6 9 12 Kotak : 3 6 9 12 18 20 24 30 36 RBL : 3 6 9 12 18 24 BOB : 3 6 9 12 18 24 36 Standard Chartered : 3 6 9 12 INDUS : 3 6 9 12 AU : 3 6 9 12 18 24 HSBC : 3 6 9 12 YES : 3 6 9 12 18 24 CITI : 3 6 9 12 SBI : 3 6 9 12 FED : 3 6 9 12 Axis : 3 6 9 12 18 24 |
<div id="pay-ccemi">
<table>
<tr><td>Card number</td><td><input type="text" value="" data-emi-number> </td></tr>
<tr><td>card expiry MM</td><td><input type="text" value="" data-emi-expiry-mm> </td></tr>
<tr><td>card expiry YY</td><td><input type="text" value="" data-emi-expiry-yy> </td></tr>
<tr><td>card cvv</td><td><input type="password" value="" data-emi-cvv></td></tr>
<tr><td>Bank Name</td><td><input type="text" value="" data-emi-bank></td></tr>
<tr><td>Tenure</td><td><input type="text" value="" data-emi-tenure></td></tr>
</table>
<button id="pay-ccemi-btn">Pay</button>
</div>
The javascript code is similar to the previous flows.
let isProviderReady = false;
let order_token = ""; //order_token is received after create order api is called
cfCheckout.elements([
{
pay: document.getElementById('pay-ccemi'),
type: 'emi',
onChange: ccemiEventHandler
},
]);
function ccemiEventHandler(data){
console.log("CCEMI --> ", data)
isProviderReady = data.isReadyToPay
}
$("#pay-ccemi-btn").click(async function() {
if(!isProviderReady) {
alert("CC EMI not ready to pay!")
return
}
await cfCheckout.pay(order_token, 'emi')
});
Cardless EMI
The SDK allows you to pay using different cardless applications. For example - Zestmoney, Flexmoney.
There are two attributes that we need to complete payments for cardless EMI - the provider name and customers phone number.
attribute | description |
---|---|
data-cardless-provider | Holds the app name. Values can be flexmoney zestmoney . |
data-cardless-phone | Phone number of the customer |
Below is a sample payment form to collect cardless EMI details. We need basically need the two attributes - data-cardless-provider
and data-cardless-phone
.
<div id="cardless-emi">
<select data-cardless-provider>
<option value="">select</option>
<option value="flexmoney">FlexMoney</option>
<option value="zestmoney">ZestMoney</option>
</select>
<input type="text" data-cardless-phone />
<button id="cardless-emi-btn">Pay</button>
</div>
The javascript code is similar to the previous flows.
let isProviderReady = false;
let order_token = "";
cfCheckout.elements([
{
pay: document.getElementById('cardless-emi'),
type: 'cardlessemi',
onChange: cardlessEventHandler
},
]);
function cardlessEventHandler(data){
console.log("App --> ", data)
isProviderReady = data.isReadyToPay
}
$("#cardless-emi-btn").click(async function() {
if(!isProviderReady) {
alert("App not ready to pay!")
return
}
await cfCheckout.pay(order_token, 'cardlessemi')
});
Net Banking
If you want to accept payment using net banking, you will have to build out elements for net banking. There is only attribute for net banking that we receive - the bank code.
attribute | description |
---|---|
data-netbanking-code | Holds the bank code. The bank code is given by Cashfree’s for different banks. It ranges from 3001 to 3999. For example HDFC has a code of 3021 See here for more details. |
The javascript code to process net banking payments is again similar to previous flows.
<div id="pay-nb">
<input type="text" value="" data-netbanking-code>
</div>
<button id="pay-nb-btn">Pay</button>
Here we are showing you another way to initiate a Cashfree element.
const el = cfCheckout.element({
pay: document.getElementById('pay-nb'),
type: 'netbanking',
});
el.on('change', function(data){
console.log(data);
document.getElementById("onChangeNB").innerHTML = JSON.stringify(data)
});
document.getElementById('pay-nb-btn').addEventListener('click', async () => {
await cfCheckout.pay(orderToken, 'netbanking');
});
Confirm payment
Once you received a response on either onPaymentSuccess
or onPaymentFailure
you should make an api call to your backend server to confirm the status of the payment. We will see that in the next step.
NPM
npm i cashfree-elementjs
For further instructions please visit the official npm page
Updated 11 months ago