Pay using iFrame

Use this mode of integration, if you wish to embed the payment form as part of your checkout page.

Create Order

To collect payment from a customer, you first need to create an order with Juspay. Order encapsulates all the information that is required for payment.

Embedding the iFrame

The iframe URL is available as part of the POST /order/create API.

Example

{
  "order_id": "1478851764",
  "id": "ord_e294a26e66ad4336a992ceab81ad704c",
  "status": "CREATED",
  "status_id": 1,
  "payment_links": {
    "web": "https://api.juspay.in/merchant/pay/ord_e294a26e66ad4336a992ceab81ad704c",
    "mobile": "https://api.juspay.in/merchant/pay/ord_e294a26e66ad4336a992ceab81ad704c?mobile=true",
    "iframe": "https://api.juspay.in/merchant/ipay/ord_e294a26e66ad4336a992ceab81ad704c"
  }
}

payment_links attribute will be present in both /order/create API and /order/status API. We have provided three variants to make it easy for your customers. As the name implies, these are best suited for the respective channels.

VariantDescription
webRenders a desktop-optimized version of the checkout page
mobileRenders a mobile-optimized version of the checkout page
iframeProvides an iFrame that you can embed as part of your checkout page
<iframe src="https://api.juspay.in/merchant/ipay/ord_e294a26e66ad4336a992ceab81ad704c"
width="630" height="400"
style="border: 1px solid #CCC;padding: 20px;height: auto;min-height: 300px;">
</iframe>

Mobile optimized form

The mobile variant url is available in payment_links attribute will be present in both /order/create API and /order/status API. Please see the code below:

<iframe src="https://api.juspay.in/merchant/pay/ord_e294a26e66ad4336a992ceab81ad704c?mobile=true"
width="630" height="400"
style="border: 1px solid #CCC;padding: 20px;height: auto;min-height: 300px;">
</iframe>

This will render a mobile responsive form with all the functionalities included.

Note: The mobile-optimized checkout experience will use the redirect mode to do the authentication.

Using EMI

To support EMI the iFrame payment URL has been enhanced to take additional parameters:

  • is_emi: Indicates if EMI is applicable for this transaction. Valid values are true and false.
  • emi_bank: Issuing bank of the card
  • emi_tenure: Tenure of EMI in months

Note: It is an error to pass is_emi and not pass emi_bank and emi_tenure.

Sample code for creating an iFrame with EMI support:

<iframe src="https://api.juspay.in/merchant/ipay/ord_e294a26e66ad4336a992ceab81ad704c?is_emi=true&emi_tenure=6&emi_bank=HDFC"
width="630" height="400"
style="border: 1px solid #CCC;padding: 20px;height: auto;min-height: 300px;">
</iframe>

Currently supported combinations of emi_bank and emi_tenure are:

EMI BankEMI TenureSupported Gateways
HDFC3,6,9,12,18,24PAYU, HDFC, RAZORPAY
CITI3,6,9,12,18,24PAYU
ICICI3,6,9,12,18,24PAYU, ICICI, CCAVENUE, RAZORPAY
SBI3,6,9,12PAYU, CCAVENUE, RAZORPAY
AXIS3,6,9,12PAYU, ICICI, CCAVENUE, RAZORPAY
SCB3,6,9,12,18,24ICICI, PAYU, RAZORPAY
KOTAK3,6,9,12ICICI, CCAVENUE, PAYU, RAZORPAY
HSBC3,6,9,12ICICI, CCAVENUE, PAYU
AMEX3,6,9,12PAYU, CCAVENUE, RAZORPAY
INDUSIND3,6,9,12,18,24PAYU, CCAVENUE, RAZORPAY
RBL3,6,9,12,18,24RAZORPAY, PAYU
YES3,6,9,12,18,24PAYU, RAZORPAY
ICICIDC3,6,9,12PAYU
AXISDC3,6,9,12PAYU
HDFCDC3,6,9,12,18PAYU, BILLDESK

Payment Method Customization

By default, cards are enabled. To enable only required payment methods to pass an extra parameter to the payment URL

To enable only Netbanking, pass the following parameter: payment_options=nb. To enable only Wallets, pass the following parameter: payment_options=wallet. To enable Netbanking and Wallets together, pass the following parameter: payment_options=nb|wallet.

Sample code for creating an iFrame with EMI support:

<iframe src="https://api.juspay.in/merchant/ipay/ord_e294a26e66ad4336a992ceab81ad704c?payment_options=nb"
width="630" height="400"
style="border: 1px solid #CCC;padding: 20px;height: auto;min-height: 300px;">
</iframe>

PCI Compliance

iFrame based integration offers the easiest path to PCI Compliance. Since iFrame is as good as a separate browser window, your website is completely shielded away from getting any sensitive card information. You can become PCI Compliant by simply filling up the PCI DSS SAQ-A questionnaire.

Javascript Integration

Pay-V3.js

Checkout using Javascript

This mode of integration is an alternative to iFrame based integration. While the iFrame based integration lets you easily get to the market, javascript based integration gives you the ultimate flexibility to define the checkout experience for your customer.

Create order

Order creation has already been explained previously. Follow the same steps mentioned here.

pay-v3.js

pay-v3.js is the recommended mode of checkout. This latest version uses iFrame elements to take the card input from the user, and a hidden iFrame to send the card information to JusPay servers. This offers better security and reduces the compliance level for you.

<script type="text/javascript"
        src="https://api.juspay.in/pay-v3.js"></script>

Implementing Checkout

Before we get to the details, let's take a quick look at a typical payment form. This is the part you can build with your web framework, or by hand in HTML - whatever way you're used to building forms on the web.

For Cards

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order"/>
    <div class="card_number_div"></div>
    <div class="name_on_card_div"></div>
    <div class="card_exp_month_div"></div> - <div class="card_exp_year_div"></div>
    <div class="security_code_div"></div>
    <input type="checkbox"  class="juspay_locker_save"> Save card information
    <input type="hidden" class="redirect" value="true"/>
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with Secure Password
    <input type="radio" class="auth_type" value="ATMPIN" name="auth_type"> Verify with ATM PIN
    <button type="submit" id="common_pay_btn">Make Payment</button>
</form>

In the above form, you need to write the <div> elements for card_number, name_on_card, card_exp_month, card_exp_year and security_code fields. There is no need to write input elements here, since we will be inserting our iframe elements inside this div which will have the input element. You need to assign a unique class name for each div as given in above example.

Include the auth_type field only if your account supports ATM PIN transactions. Display the auth_type option to users only if the card entered supports ATM PIN transactions. To know how to check the atm pin support for a card, please refer to our API documentation.

For Saved Card

<form class="juspay_inline_form" id="payment_form1">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="hidden" class="card_token"/>
    <input type="hidden" class="card_isin"/>
    <div class="security_code_div"></div>
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with Secure Password
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with ATM PIN
    <input type="hidden" class="redirect" value="true"/>
</form>
<form class="juspay_inline_form" id="payment_form2">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="hidden" class="card_token"/>
    <input type="hidden" class="card_isin"/>
    <div class="security_code_div"></div>
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with Secure Password
    <input type="radio" class="auth_type" value="ATMPIN" name="auth_type"> Verify with ATM PIN
    <input type="hidden" class="redirect" value="true"/>
    <button type="submit" class="make_payment">Pay</button>
</form>

All these forms will have the same class name for common styling and different id's for identification. In the above form, you need to write the <div> element for security_code fields. There is no need to write input element here, since we will be inserting our iframe elements inside this div which will have the input element. All the saved card forms should have the same class name for security_code divs.

Include the auth_type field only if your account supports ATM PIN transactions. Display the auth_type options to the user only if the card entered supports ATM PIN transactions. To know how to check the atm pin support for a stored card, please refer to our API documentation

For Netbanking

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="NB"/>
    <select class="payment_method">
        <option value="NB_ALLB" label="Allahabad Bank">Allahabad Bank</option>
        <option value="NB_ANDHRA" label="Andhra Bank">Andhra Bank</option>
        <option>...</option>
        <!-- More banks -->
        <option value="NB_YESB" label="YES Bank">YES Bank</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

For Wallets

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="WALLET"/>
    <select class="payment_method">
        <option value="FREECHARGE" label="Freecharge Wallet">Freecharge Wallet</option>
        <option>...</option>
        <!-- More wallets -->
        <option value="SBIBUDDY" label="SBI Buddy">SBI Buddy</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

For UPI Collect transactions

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="text" class="upi_vpa" value=""/>
    <input type="hidden" class="payment_method_type" value="UPI"/>
    <input type="hidden" class="payment_method" value="UPI"/>
    <input type="hidden" class="txn_type" value="UPI_COLLECT"/>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

For ATM PIN Redirection transactions

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="CARD"/>
    <input type="hidden" class="auth_type" value="ATMPIN"/>
    <select class="payment_method">
        <option value="ATM_CARD_BOB" label="Bank of Baroda">Bank of Baroda</option>
        <option value="ATM_CARD_IOB" label="Indian Overseas Bank">Indian Overseas Bank</option>
        <option>...</option>
        <!-- More banks -->
        <option value="ATM_CARD_UBI" label="Union Bank of India">Union Bank of India</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

Besides the usual fields, there are some Juspay specific fields which will enable us to process the payment when the form is submitted.

  • order_id field represents the order_id of the order object that you have just created.
  • merchant_id helps us identify you. Changing this would mean that we credit the payment to someone else's account. So, please be careful with this field!
  • payment_method_type identifies the category of the payment instrument being used. It can be one of CARD, NB, WALLET.
  • payment_method identifies the actual payment instrument being used. List of payment methods for NetBanking is shown in the form above.
  • juspay_locker_save tells us whether we need to store this card after the payment is successful.
  • If redirect is true, then we will choose the redirection flow for authentication. Otherwise, a popup window will be used for authentication. By default, popup window will be chosen for authentication.

pay-v3.js listens to the form submit event and transports the card information safely to process it for payment. pay-v3.js also supports card tokenization which will tokenize the card information and provide a short-lived token. This token can then be used to initiate the transaction. This is accomplished by the following snippet.

For Cards

<script type="text/javascript">
    Juspay.Setup({
        payment_form: "#payment_form",
        success_handler: function(status) {},
        error_handler: function(error_code, error_message, bank_error_code, bank_error_message, gateway_id) {},
        card_bin_digit_count: 9,
        customer: {
          customer_id: "test",
          client_auth_token: "tkn_91b9b3cbab9542bf9367ef6d6350b7e4",
        },
        iframe_elements: {
            card_number: {
                /* Class name of the <div> which will hold the iframe element for card number. */
                container: ".card_number_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "4111 1111 1111 1111"
                }
            },
            name_on_card: {
                /* Class name of the <div> which will hold the iframe element for card holder name. */
                container: ".name_on_card_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "Cardholder Name"
                }
            },
            card_exp_month: {
                /* Class name of the <div> which will hold the iframe element for card expiry month. */
                container: ".card_exp_month_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "MM"
                }
            },
            card_exp_year: {
                /* Class name of the <div> which will hold the iframe element for card expiry year. */
                container: ".card_exp_year_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "YY"
                }
            },
            security_code: {
                /* Class name of the <div> which will hold the iframe element for card security code. */
                container: ".security_code_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "123"
                }
            }
        },
        /* Set `auto_tab_enabled` flag to true if you want to enable auto-switching between fields when the user types the valid data,
         * which will have the following order:
         * `card_exp_month` -> `card_exp_year` -> `security_code`.
         * Note: You can ignore the `auto_tab_enabled` field if auto-switching between fields isn't required.
         */
        auto_tab_enabled : true,
        /* Set `auto_tab_from_card_number` to either `card_exp_month` or `name_on_card` based on which field is rendered next after card_number.
         * Note 1: Please set `auto_tab_enabled` to `true` as shown above to enable this functionality.
         * Note 2: You can ignore the `auto_tab_from_card_number` field if this functionality isn't required.
         */
        auto_tab_from_card_number : "card_exp_month",
        styles: {
            /* Add common styling for all input fields here */
            "input": {
            },
            /* Add the styling for card number input field here */
            ".card_number": {
                "line-height": "10px",
                "font-size": "16px"
            },
            /* Add the styling for card holder name input field here */
            ".name_on_card": {
                "line-height": "20px",
                "font-size": "16px",
            },
            /* Add the styling for card expiry month input field here */
            ".card_exp_month": {
                "line-height": "30px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling for card expiry year input field here */
            ".card_exp_year": {
                "line-height": "40px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling for card security code input field here */
            ".security_code": {
                "line-height": "50px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling to be added to input fields in focus state */
            ":focus": {
            }
        },
        /* 
         * This function will be called with an event object as a parameter in two cases:
         * 1. When some event occurs on the input field inside the iframe element.
         * 2. The user clicks on the submit button and the values in some of the input fields are invalid. (In the second case, we will send the event object with the state of the first invalid field in the checkout form.)
         *
         * This event object will contain the state of the input field. You should use this event object to show validation messages in your checkout form.
         *
         */
        iframe_element_callback: function(event) {
            /*
             *  The following information will be available in the event object:
             *  1. event.target_element - (card_number/name_on_card/card_exp_month/card_exp_year/security_code) Name of the field field which generated this event.
             *
             *  2. event.type - (focus/blur/keyup/change) This field explains the event type which triggered the event callback.
             *
             *  3. event.valid - (true/false) This explains whether the value inside the input field of target_element is valid or not.
             *
             *  4. event.empty - (true/false) This explains whether the input field of target_element is empty or not.
             *
             *  5. event.card_isin - ISIN value of the card number (Available only when target_element is card_number)
             *
             *  6. event.card_brand - MASTERCARD/VISA/MAESTRO/AMEX/DINERS/DISCOVER/JCB/RUPAY (Available only when target_element is card_number)
             *      
             *  7. event.card_type - (DEBIT/CREDIT) (Available only when target_element is card_number)
             *      
             *  8. event.card_sub_type - (only available for >= 9 digit card bin requests)
             *      
             *  9. event.partially_valid - This explains whether the user is typing the card number correctly. (Available only when target_element is card_number)
             *      
             *  10. event.expiry_valid - This explains whether the combination of month or year is valid or not. There may be a case when the input year is the current year and the input month is any month before the current month, then you will get valid=true for both month and year separately, but together they are not valid. To keep such cases in mind, you need to validate whether expiry_valid is true or not. (Available only when target_element is either card_exp_month or card_exp_year)
             *
             * 11. event.atm_pin_auth_support - This explains whether the card number entered is valid for ATM PIN transactions. Please note that this field will be set only if your merchant account supports ATM PIN transactions.
             *
             * 12. event.mandate_support - (true/false) This explains whether the card number entered is eligible for the mandate transactions
             *
             * 12. event.bank - Name of bank (only available for >= 9 digit card bin requests)
             */
        }
    })
</script>

<script type="text/javascript">
    juspay_form.tokenize({
      /* juspay_form is the reference of the object returned from Juspay.Setup() */
      success_handler : function(response) {
        /*
         * response.token contains the card token
         * response.start_payment() will start the transaction
         */
      },
      error_handler : function(response) {

      }
    })
</script>

For Saved Cards

<script type="text/javascript">
    Juspay.Setup({
        payment_form: "#payment_form",
        success_handler: function(status) {},
        error_handler: function(error_code, error_message, bank_error_code, bank_error_message, gateway_id) {}
        iframe_elements: {
            security_code: {
                /* Class name of the <div> which will hold the iframe element for card security code. */
                container: ".security_code_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "123"
                }
            }
        },
        styles: {
            /* Add the styling for card security code input field here */
            ".security_code": {
                "line-height": "50px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling to be added to input fields in focus state */
            ":focus": {
            }
        },
        /* 
         * This function will be called with an event object as parameter in two cases:
         * 1. When some event occurs on the security_code field inside iframe element.
         * 2. The user clicks on the submit button and the values in some of the input fields are invalid. (In second case, we will send the event object with state of the first invalid field in checkout form, which is security_code here.)
         *
         * This event object will contain the state of the input field. You should use this event object to show validation messages in your checkout form.
         *
         */
        iframe_element_callback: function(event) {
            /*
             *  The following information will be available in the event object:
             *  1. event.target_element - (security_code) Name of the field field which generated this event.
             *      
             *  2. event.valid - (true/false) This explains whether the value inside the input field of target_element is valid or not. 
             *
             *  3. event.empty - (true/false) This explains whether the input field of target_element is empty or not.
             *
             *  4. event.card_brand - MASTERCARD/VISA/MAESTRO/AMEX/DINERS/DISCOVER/JCB/RUPAY
             *      
             */
        }
    })
</script>

<script type="text/javascript">
    juspay_form.tokenize({
      /* juspay_form is the reference of the object returned from Juspay.Setup() */
      success_handler : function(response) {
        /*
         * response.token contains the card token
         * response.start_payment() will start the transaction
         */
      },
      error_handler : function(response) {

      }
    })
</script>

Note:The parameter "name_on_card" is mandatory for calling tokenize function. If not passed you might encounter CORS issue.

For Netbanking, Wallets and UPICurrently supported combinations of emi_bank and emi_tenure are:

EMI BankEMI TenureSupported Gateways
HDFC3,6,9,12,18,24PAYU, HDFC, RAZORPAY
CITI3,6,9,12,18,24PAYU
ICICI3,6,9,12,18,24PAYU, ICICI, CCAVENUE, RAZORPAY
SBI3,6,9,12PAYU, CCAVENUE, RAZORPAY
AXIS3,6,9,12PAYU, ICICI, CCAVENUE, RAZORPAY
SCB3,6,9,12,18,24ICICI, PAYU, RAZORPAY
KOTAK3,6,9,12ICICI, CCAVENUE, PAYU, RAZORPAY
HSBC3,6,9,12ICICI, CCAVENUE, PAYU
AMEX3,6,9,12PAYU, CCAVENUE, RAZORPAY
INDUSIND3,6,9,12,18,24PAYU, CCAVENUE, RAZORPAY
RBL3,6,9,12,18,24RAZORPAY, PAYU
YES3,6,9,12,18,24PAYU, RAZORPAY
ICICIDC3,6,9,12PAYU
AXISDC3,6,9,12PAYU
HDFCDC3,6,9,12,18PAYU, BILLDESK

Payment Method Customization

By default, cards are enabled. To enable only required payment methods to pass an extra parameter to the payment URL

To enable only Netbanking, pass the following parameter: payment_options=nb. To enable only Wallets, pass the following parameter: payment_options=wallet. To enable Netbanking and Wallets together, pass the following parameter: payment_options=nb|wallet.

Sample code for creating an iFrame with EMI support:

<iframe src="https://api.juspay.in/merchant/ipay/ord_e294a26e66ad4336a992ceab81ad704c?payment_options=nb"
width="630" height="400"
style="border: 1px solid #CCC;padding: 20px;height: auto;min-height: 300px;">
</iframe>

PCI Compliance

iFrame based integration offers the easiest path to PCI Compliance. Since iFrame is as good as a separate browser window, your website is completely shielded away from getting any sensitive card information. You can become PCI Compliant by simply filling up the PCI DSS SAQ-A questionnaire.

Javascript Integration

Pay-V3.js

Checkout using Javascript

This mode of integration is an alternative to iFrame based integration. While the iFrame based integration lets you easily get to the market, javascript based integration gives you the ultimate flexibility to define the checkout experience for your customer.

Create order

Order creation has already been explained previously. Follow the same steps mentioned here.

pay-v3.js

pay-v3.js is the recommended mode of checkout. This latest version uses iFrame elements to take the card input from the user, and a hidden iFrame to send the card information to JusPay servers. This offers better security and reduces the compliance level for you.

<script type="text/javascript"
        src="https://api.juspay.in/pay-v3.js"></script>

Implementing Checkout

Before we get to the details, let's take a quick look at a typical payment form. This is the part you can build with your web framework, or by hand in HTML - whatever way you're used to building forms on the web.

For Cards

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order"/>
    <div class="card_number_div"></div>
    <div class="name_on_card_div"></div>
    <div class="card_exp_month_div"></div> - <div class="card_exp_year_div"></div>
    <div class="security_code_div"></div>
    <input type="checkbox"  class="juspay_locker_save"> Save card information
    <input type="hidden" class="redirect" value="true"/>
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with Secure Password
    <input type="radio" class="auth_type" value="ATMPIN" name="auth_type"> Verify with ATM PIN
    <button type="submit" id="common_pay_btn">Make Payment</button>
</form>

In the above form, you need to write the <div> elements for card_number, name_on_card, card_exp_month, card_exp_year and security_code fields. There is no need to write input elements here, since we will be inserting our iframe elements inside this div which will have the input element. You need to assign a unique class name for each div as given in above example.

Include the auth_type field only if your account supports ATM PIN transactions. Display the auth_type option to users only if the card entered supports ATM PIN transactions. To know how to check the atm pin support for a card, please refer to our API documentation.

For Saved Card

<form class="juspay_inline_form" id="payment_form1">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="hidden" class="card_token"/>
    <input type="hidden" class="card_isin"/>
    <div class="security_code_div"></div>
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with Secure Password
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with ATM PIN
    <input type="hidden" class="redirect" value="true"/>
</form>
<form class="juspay_inline_form" id="payment_form2">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="hidden" class="card_token"/>
    <input type="hidden" class="card_isin"/>
    <div class="security_code_div"></div>
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with Secure Password
    <input type="radio" class="auth_type" value="ATMPIN" name="auth_type"> Verify with ATM PIN
    <input type="hidden" class="redirect" value="true"/>
    <button type="submit" class="make_payment">Pay</button>
</form>

All these forms will have the same class name for common styling and different id's for identification. In the above form, you need to write the <div> element for security_code fields. There is no need to write input element here, since we will be inserting our iframe elements inside this div which will have the input element. All the saved card forms should have the same class name for security_code divs.

Include the auth_type field only if your account supports ATM PIN transactions. Display the auth_type options to the user only if the card entered supports ATM PIN transactions. To know how to check the atm pin support for a stored card, please refer to our API documentation

For Netbanking

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="NB"/>
    <select class="payment_method">
        <option value="NB_ALLB" label="Allahabad Bank">Allahabad Bank</option>
        <option value="NB_ANDHRA" label="Andhra Bank">Andhra Bank</option>
        <option>...</option>
        <!-- More banks -->
        <option value="NB_YESB" label="YES Bank">YES Bank</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

For Wallets

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="WALLET"/>
    <select class="payment_method">
        <option value="FREECHARGE" label="Freecharge Wallet">Freecharge Wallet</option>
        <option>...</option>
        <!-- More wallets -->
        <option value="SBIBUDDY" label="SBI Buddy">SBI Buddy</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

For UPI Collect transactions

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="text" class="upi_vpa" value=""/>
    <input type="hidden" class="payment_method_type" value="UPI"/>
    <input type="hidden" class="payment_method" value="UPI"/>
    <input type="hidden" class="txn_type" value="UPI_COLLECT"/>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

For ATM PIN Redirection transactions

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="CARD"/>
    <input type="hidden" class="auth_type" value="ATMPIN"/>
    <select class="payment_method">
        <option value="ATM_CARD_BOB" label="Bank of Baroda">Bank of Baroda</option>
        <option value="ATM_CARD_IOB" label="Indian Overseas Bank">Indian Overseas Bank</option>
        <option>...</option>
        <!-- More banks -->
        <option value="ATM_CARD_UBI" label="Union Bank of India">Union Bank of India</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true"/>
</form>

Besides the usual fields, there are some Juspay specific fields which will enable us to process the payment when the form is submitted.

  • order_id field represents the order_id of the order object that you have just created.
  • merchant_id helps us identify you. Changing this would mean that we credit the payment to someone else's account. So, please be careful with this field!
  • payment_method_type identifies the category of the payment instrument being used. It can be one of CARD, NB, WALLET.
  • payment_method identifies the actual payment instrument being used. List of payment methods for NetBanking is shown in the form above.
  • juspay_locker_save tells us whether we need to store this card after the payment is successful.
  • If redirect is true, then we will choose the redirection flow for authentication. Otherwise, a popup window will be used for authentication. By default, popup window will be chosen for authentication.

pay-v3.js listens to the form submit event and transports the card information safely to process it for payment. pay-v3.js also supports card tokenization which will tokenize the card information and provide a short-lived token. This token can then be used to initiate the transaction. This is accomplished by the following snippet.

For Cards

<script type="text/javascript">
    Juspay.Setup({
        payment_form: "#payment_form",
        success_handler: function(status) {},
        error_handler: function(error_code, error_message, bank_error_code, bank_error_message, gateway_id) {},
        card_bin_digit_count: 9,
        customer: {
          customer_id: "test",
          client_auth_token: "tkn_91b9b3cbab9542bf9367ef6d6350b7e4",
        },
        iframe_elements: {
            card_number: {
                /* Class name of the <div> which will hold the iframe element for card number. */
                container: ".card_number_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "4111 1111 1111 1111"
                }
            },
            name_on_card: {
                /* Class name of the <div> which will hold the iframe element for card holder name. */
                container: ".name_on_card_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "Cardholder Name"
                }
            },
            card_exp_month: {
                /* Class name of the <div> which will hold the iframe element for card expiry month. */
                container: ".card_exp_month_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "MM"
                }
            },
            card_exp_year: {
                /* Class name of the <div> which will hold the iframe element for card expiry year. */
                container: ".card_exp_year_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "YY"
                }
            },
            security_code: {
                /* Class name of the <div> which will hold the iframe element for card security code. */
                container: ".security_code_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "123"
                }
            }
        },
        /* Set `auto_tab_enabled` flag to true if you want to enable auto-switching between fields when the user types the valid data,
         * which will have the following order:
         * `card_exp_month` -> `card_exp_year` -> `security_code`.
         * Note: You can ignore the `auto_tab_enabled` field if auto-switching between fields isn't required.
         */
        auto_tab_enabled : true,
        /* Set `auto_tab_from_card_number` to either `card_exp_month` or `name_on_card` based on which field is rendered next after card_number.
         * Note 1: Please set `auto_tab_enabled` to `true` as shown above to enable this functionality.
         * Note 2: You can ignore the `auto_tab_from_card_number` field if this functionality isn't required.
         */
        auto_tab_from_card_number : "card_exp_month",
        styles: {
            /* Add common styling for all input fields here */
            "input": {
            },
            /* Add the styling for card number input field here */
            ".card_number": {
                "line-height": "10px",
                "font-size": "16px"
            },
            /* Add the styling for card holder name input field here */
            ".name_on_card": {
                "line-height": "20px",
                "font-size": "16px",
            },
            /* Add the styling for card expiry month input field here */
            ".card_exp_month": {
                "line-height": "30px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling for card expiry year input field here */
            ".card_exp_year": {
                "line-height": "40px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling for card security code input field here */
            ".security_code": {
                "line-height": "50px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling to be added to input fields in focus state */
            ":focus": {
            }
        },
        /* 
         * This function will be called with an event object as a parameter in two cases:
         * 1. When some event occurs on the input field inside the iframe element.
         * 2. The user clicks on the submit button and the values in some of the input fields are invalid. (In the second case, we will send the event object with the state of the first invalid field in the checkout form.)
         *
         * This event object will contain the state of the input field. You should use this event object to show validation messages in your checkout form.
         *
         */
        iframe_element_callback: function(event) {
            /*
             *  The following information will be available in the event object:
             *  1. event.target_element - (card_number/name_on_card/card_exp_month/card_exp_year/security_code) Name of the field field which generated this event.
             *
             *  2. event.type - (focus/blur/keyup/change) This field explains the event type which triggered the event callback.
             *
             *  3. event.valid - (true/false) This explains whether the value inside the input field of target_element is valid or not.
             *
             *  4. event.empty - (true/false) This explains whether the input field of target_element is empty or not.
             *
             *  5. event.card_isin - ISIN value of the card number (Available only when target_element is card_number)
             *
             *  6. event.card_brand - MASTERCARD/VISA/MAESTRO/AMEX/DINERS/DISCOVER/JCB/RUPAY (Available only when target_element is card_number)
             *      
             *  7. event.card_type - (DEBIT/CREDIT) (Available only when target_element is card_number)
             *      
             *  8. event.card_sub_type - 
             *      
             *  9. event.partially_valid - This explains whether the user is typing the card number correctly. (Available only when target_element is card_number)
             *      
             *  10. event.expiry_valid - This explains whether the combination of month or year is valid or not. There may be a case when the input year is the current year and the input month is any month before the current month, then you will get valid=true for both month and year separately, but together they are not valid. To keep such cases in mind, you need to validate whether expiry_valid is true or not. (Available only when target_element is either card_exp_month or card_exp_year)
             *
             * 11. event.atm_pin_auth_support - This explains whether the card number entered is valid for ATM PIN transactions. Please note that this field will be set only if your merchant account supports ATM PIN transactions.
             *
             * 12. event.mandate_support - (true/false) This explains whether the card number entered is eligible for the mandate transactions
             */
        }
    })
</script>

<script type="text/javascript">
    juspay_form.tokenize({
      /* juspay_form is the reference of the object returned from Juspay.Setup() */
      success_handler : function(response) {
        /*
         * response.token contains the card token
         * response.start_payment() will start the transaction
         */
      },
      error_handler : function(response) {

      }
    })
</script>

For Saved Cards

<script type="text/javascript">
    Juspay.Setup({
        payment_form: "#payment_form",
        success_handler: function(status) {},
        error_handler: function(error_code, error_message, bank_error_code, bank_error_message, gateway_id) {}
        iframe_elements: {
            security_code: {
                /* Class name of the <div> which will hold the iframe element for card security code. */
                container: ".security_code_div",
                attributes: {
                    /* Field Attributes, which you want to set for the <input> field inside the iframe element. */
                    placeholder: "123"
                }
            }
        },
        styles: {
            /* Add the styling for card security code input field here */
            ".security_code": {
                "line-height": "50px",
                "font-size": "16px",
                "width": "60px"
            },
            /* Add the styling to be added to input fields in focus state */
            ":focus": {
            }
        },
        /* 
         * This function will be called with an event object as parameter in two cases:
         * 1. When some event occurs on the security_code field inside iframe element.
         * 2. The user clicks on the submit button and the values in some of the input fields are invalid. (In second case, we will send the event object with state of the first invalid field in checkout form, which is security_code here.)
         *
         * This event object will contain the state of the input field. You should use this event object to show validation messages in your checkout form.
         *
         */
        iframe_element_callback: function(event) {
            /*
             *  The following information will be available in the event object:
             *  1. event.target_element - (security_code) Name of the field field which generated this event.
             *      
             *  2. event.valid - (true/false) This explains whether the value inside the input field of target_element is valid or not. 
             *
             *  3. event.empty - (true/false) This explains whether the input field of target_element is empty or not.
             *
             *  4. event.card_brand - MASTERCARD/VISA/MAESTRO/AMEX/DINERS/DISCOVER/JCB/RUPAY
             *      
             */
        }
    })
</script>

<script type="text/javascript">
    juspay_form.tokenize({
      /* juspay_form is the reference of the object returned from Juspay.Setup() */
      success_handler : function(response) {
        /*
         * response.token contains the card token
         * response.start_payment() will start the transaction
         */
      },
      error_handler : function(response) {

      }
    })
</script>

Note:The parameter "name_on_card" is mandatory for calling tokenize function. If not passed you might encounter CORS issue.

For Netbanking, Wallets and UPI

<script type="text/javascript">
    Juspay.Setup({
        payment_form: "#payment_form",
        success_handler: function(status) {},
        error_handler: function(error_code, error_message, bank_error_code, bank_error_message, gateway_id) {},
    })
 </script>

For Encoding the Card Details

<script type="text/javascript">
Juspay.Setup({
    payment_form: "#payment_form",
    success_handler: function(status) {},
    error_handler: function(error_code, error_message, bank_error_code,
        bank_error_message, gateway_id) {},
    card_encoding_key: ":card_encoding_key",
    card_encoding_version: "YYYY-MM-DD"
})
</script>

The card_encoding_key can be found on juspay's dashboard under the Settings--> Security.
And the card_encoding_version is 2017-04-26.

Card Form Validation

Juspay JS will validate the card elements. You are only expected to handle the validation events.

Using EMI

To support EMI the iFrame payment URL has been enhanced to take additional parameters:

  • is_emi: Indicates if EMI is applicable for this transaction. Valid values are true and false.
  • emi_bank: Issuing bank of the card
  • emi_tenure: Tenure of EMI in months
  • emi_type: Type of EMI ie STANDARD_EMI or NO_COST_EMI

Note: It is an error to pass is_emi and not pass emi_bank and emi_tenure.

Sample form with EMI support:

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="hidden" class="is_emi" value="true" />
    <input type="hidden" class="emi_bank" value="HDFC" />
    <input type="hidden" class="emi_tenure" value="6" />
    <input type="hidden" class="emi_type" value="STANDARD_EMI" />
    <div class="card_number_div"></div>
    <div class="name_on_card_div"></div>
    <div class="card_exp_month_div"></div> - <div class="card_exp_year_div"></div>
    <div class="security_code_div"></div>
    <input type="checkbox"  class="juspay_locker_save"> Save card information
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="false">
</form>

Currently supported combinations of emi_bank and emi_tenure are:

EMI BankEMI TenureSupported Gateways
HDFC3,6,9,12,18,24PAYU, HDFC, RAZORPAY
CITI3,6,9,12,18,24PAYU
ICICI3,6,9,12,18,24PAYU, ICICI, CCAVENUE, RAZORPAY
SBI3,6,9,12PAYU, CCAVENUE
AXIS3,6,9,12PAYU, ICICI, CCAVENUE, RAZORPAY
SCB3,6,9,12,18,24ICICI, PAYU
KOTAK3,6,9,12ICICI, CCAVENUE, PAYU, RAZORPAY
HSBC3,6,9,12ICICI, CCAVENUE, PAYU
AMEX3,6,9,12PAYU, CCAVENUE, RAZORPAY
INDUSIND3,6,9,12,18,24PAYU, CCAVENUE, RAZORPAY
RBL3,6,9,12,18,24RAZORPAY, PAYU
BOB3,6,9,12RAZORPAY
YES3,6,9,12,18,24PAYU
ICICIDC3,6,9,12PAYU
AXISDC3,6,9,12PAYU
HDFCDC3,6,9,12,18PAYU, BILLDESK

PCI Compliance

All Juspay clients must be PCI DSS Compliant at all times. When using pay-v3.js, you can achieve compliance with the most minimal requirement of completing the Self Assessment Questionnaire A (SAQ A). Since all the card elements are captured in Juspay's iFrame, the simplest level of PCI validation is sufficient for your website.

JS VersionSAQ Requirement
pay-v3.jsSAQ A
pay-v2.js (deprecated)SAQ A-EP

Pay-V2.js

Deprecated (please use pay-v3.js)
This mode of integration is an alternative to iFrame based integration. While the iFrame based integration lets you easily get to the market, javascript based integration gives you the ultimate flexibility to define the checkout experience for your customer.

Create order

Order creation has already been explained previously. Follow the same steps mentioned here.

pay-v2.js (deprecated)

pay-v2.js has been deprecated. Migrate to pay-v3.js for better security and reduced compliances. For pay-v3.js integration document, please check this link. If you are looking for pay-v2.js integration document, please continue.

<script type="text/javascript"
        src="https://api.juspay.in/pay-v2.js"></script>

Implementing Checkout

Before we get to the details, let's take a quick look at a typical payment form. This is the part you can build with your web framework, or by hand in HTML - whichever way you are used to building forms on the web.

For Cards

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="text" class="card_number" placeholder="Card number">
    <input type="text" class="name_on_card" placeholder="Cardholder name">
    <input type="text" class="card_exp_month" placeholder="MM"> - <input type="text" class="card_exp_year" placeholder="YYYY">
    <input type="text" class="security_code" placeholder="CVV" >
    <input type="checkbox"  class="juspay_locker_save"> Save card information
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true">
</form>

For Saved Card

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="hidden" class="card_token" >
    <input type="text" class="security_code" placeholder="CVV" >
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true">
</form>

For Netbanking

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="NB"/>
    <select class="payment_method">
        <option value="NB_ALLB" label="Allahabad Bank">Allahabad Bank</option>
        <option value="NB_ANDHRA" label="Andhra Bank">Andhra Bank</option>
        <option value="NB_AXIS" label="Axis Bank">Axis Bank</option>
        <option value="NB_BBKM" label="Bank of Bahrain and Kuwait">Bank of Bahrain and Kuwait</option>
        <option value="NB_BHARAT" label="Bharat Bank">Bharat Bank</option>
        <option value="NB_BOB" label="Bank of Baroda">Bank of Baroda</option>
        <option value="NB_BOBCORP" label="Bank of Baroda Corporate">Bank of Baroda Corporate</option>
        <option value="NB_BOI" label="Bank of India">Bank of India</option>
        <option value="NB_BOM" label="Bank of Maharashtra">Bank of Maharashtra</option>
        <option value="NB_CANR" label="Canara Bank">Canara Bank</option>
        <option value="NB_CBI" label="Central Bank Of India">Central Bank Of India</option>
        <option value="NB_CITI" label="Citi Bank NetBanking">Citi Bank NetBanking</option>
        <option value="NB_CORP" label="Corporation Bank">Corporation Bank</option>
        <option value="NB_COSMOS" label="COSMOS Bank">COSMOS Bank</option>
        <option value="NB_CSB" label="Catholic Syrian Bank">Catholic Syrian Bank</option>
        <option value="NB_CUB" label="CityUnion">CityUnion</option> 
        <option value="NB_DBS" label="DBS Bank">DBS Bank</option>
        <option value="NB_DCB" label="Development Credit Bank">Development Credit Bank</option>
        <option value="NB_DCBB" label="Development Credit Bank Business">Development Credit Bank Business</option>
        <option value="NB_DENA" label="DENA Bank">DENA Bank</option>
        <option value="NB_DEUT" label="Deutsche Bank">Deutsche Bank</option>
        <option value="NB_DLS" label="Dhanalaxmi Bank">Dhanalaxmi Bank</option>
        <option value="NB_FED" label="Federal Bank">Federal Bank</option>
        <option value="NB_HDFC" label="HDFC Bank">HDFC Bank</option>
        <option value="NB_ICICI" label="ICICI Netbanking">ICICI Netbanking</option>
        <option value="NB_IDBI" label="Industrial Development Bank of India">Industrial Development Bank of India</option>
        <option value="NB_IDFC" label="IDFC Bank">IDFC Bank</option>
        <option value="NB_INDB" label="Indian Bank">Indian Bank</option> 
        <option value="NB_INDUS" label="IndusInd Bank">IndusInd Bank</option>
        <option value="NB_ING" label="ING Vysya Bank">ING Vysya Bank</option>
        <option value="NB_IOB" label="Indian Overseas Bank">Indian Overseas Bank</option>
        <option value="NB_JNK" label="Jammu and Kashmir Bank">Jammu and Kashmir Bank</option>
        <option value="NB_JSB" label="Janata Sahakari Bank">Janata Sahakari Bank</option>
        <option value="NB_KARN" label="Karnataka Bank">Karnataka Bank</option>
        <option value="NB_KOTAK" label="Kotak Bank">Kotak Bank</option>
        <option value="NB_KVB" label="Karur Vysya">Karur Vysya</option>
        <option value="NB_KVBCORP" label="Karur Vysya Corporate Banking">Karur Vysya Corporate Banking</option>
        <option value="NB_LVB" label="Lakshmi Vilas Bank Retail">Lakshmi Vilas Bank Retail</option>
        <option value="NB_LVBCORP" label="Lakshmi Vilas Bank Corporate">Lakshmi Vilas Bank Corporate</option>
        <option value="NB_NAIB" label="The Nainital Bank">The Nainital Bank</option>
        <option value="NB_NKGSB" label="North Kanara GSB">North Kanara GSB</option>   
        <option value="NB_OBC" label="Oriental Bank Of Commerce">Oriental Bank Of Commerce</option>
        <option value="NB_PMCB" label="Punjab and Maharashtra Coop Bank">Punjab and Maharashtra Coop Bank</option>
        <option value="NB_PNB" label="Punjab National Bank">Punjab National Bank</option>
        <option value="NB_PNBCORP" label="Punjab National Bank CORPORATE">Punjab National Bank CORPORATE</option>
        <option value="NB_PNJSB" label="Punjab and Sind Bank">Punjab and Sind Bank</option>
        <option value="NB_RATN" label="Ratnakar Bank">Ratnakar Bank</option>
        <option value="NB_RBS" label="Royal Bank of Scotland">Royal Bank of Scotland</option>
        <option value="NB_SARASB" label="Saraswat Bank">Saraswat Bank</option>
        <option value="NB_SBBJ" label="State Bank of Bikaner and Jaipur">State Bank of Bikaner and Jaipur</option>
        <option value="NB_SBH" label="State Bank of Hyderabad">State Bank of Hyderabad</option>
        <option value="NB_SBI" label="State Bank of India">State Bank of India</option>
        <option value="NB_SBM" label="State Bank of Mysore">State Bank of Mysore</option>
        <option value="NB_SBP" label="State Bank of Patiala">State Bank of Patiala</option>
        <option value="NB_SBT" label="State Bank of Travancore">State Bank of Travancore</option>
        <option value="NB_SCB" label="Standard Chartered Bank">Standard Chartered Bank</option>
        <option value="NB_SOIB" label="South Indian Bank">South Indian Bank</option>
        <option value="NB_SVC" label="SVC Co operative Bank">SVC Cooperative Bank</option>
        <option value="NB_SVCB" label="Shamrao Vithal Cooperative Bank">Shamrao Vithal Cooperative Bank</option>
        <option value="NB_SYNB" label="Syndicate Bank">Syndicate Bank</option>
        <option value="NB_TMB" label="Tamilnadu Mercantile Bank">Tamilnadu Mercantile Bank</option>
        <option value="NB_TNSC" label="Tamilnadu State Apex Coop Bank">Tamilnadu State Apex Coop Bank</option>
        <option value="NB_UBI" label="Union Bank of India">Union Bank of India</option>
        <option value="NB_UBICORP" label="Union Bank Corporate Banking">Union Bank Corporate Banking</option>
        <option value="NB_UCOB" label="UCO Bank">UCO Bank</option>
        <option value="NB_UNIB" label="United Bank of India">United Bank of India</option>
        <option value="NB_VJYB" label="Vijaya Bank">Vijaya Bank</option>
        <option value="NB_YESB" label="YES Bank">YES Bank</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true">
</form>

For Wallets

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="hidden" class="payment_method_type" value="WALLET"/>
    <select class="payment_method">
        <option value="FREECHARGE" label="Freecharge Wallet">Freecharge Wallet</option>
        <option value="JANACASH" label="Jana Cash">Jana Cash</option>
        <option value="JIOMONEY" label="JioMoney">JioMoney</option>
        <option value="MOBIKWIK" label="Mobikwik Wallet">Mobikwik Wallet</option>
        <option value="OLAMONEY" label="Olamoney Wallet">Olamoney Wallet</option>
        <option value="PAYZAPP" label="PAYZAPP">PAYZAPP</option>
        <option value="PAYTM" label="PayTM Wallet">PayTM Wallet</option>
        <option value="PAYUMONEY" label="PayU Money Wallet">PayU Money Wallet</option>
        <option value="SBIBUDDY" label="SBI Buddy">SBI Buddy</option>
    </select>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true">
</form>

For UPI Collect

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order_101"/>
    <input type="text" class="upi_vpa" value""/>
    <input type="hidden" class="payment_method_type" value="UPI"/>
    <input type="hidden" class="payment_method" value="UPI"/>
    <input type="hidden" class="txn_type" value="UPI_COLLECT"/>
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="true">
</form>

Besides the usual fields, there are some Juspay specific fields that will enable us to process the payment when the form is submitted.

  • order_id field represents the order_id of the order object that you have just created.
  • merchant_id helps us identify you. Changing this would mean that we credit the payment to someone else's account. So, please be careful with this field!
  • payment_method_type identifies the category of the payment instrument being used. It can be one of CARD, NB, WALLET.
  • payment_method identifies the actual payment instrument being used. List of payment methods for NetBanking is shown in the form above.
  • juspay_locker_save tells us whether we need to store this card after the payment is successful.
  • If redirect is true, then we will choose the redirection flow for authentication. Otherwise, a popup window will be used for authentication. By default, popup window will be chosen for authentication.

pay-v2.js listens to the form submit event and transports the card information safely to process it for payment. This is accomplished by the following snippet.

<script type="text/javascript">
Juspay.Setup({
    payment_form: "#payment_form",
    success_handler: function(status) {},
    error_handler: function(error_code, error_message, bank_error_code,
        bank_error_message, gateway_id) {},
    card_encoding_key: ":card_encoding_key",
    card_encoding_version: "YYYY-MM-DD"
})
</script>

Redirect or Popup?

Authentication can be performed either via a popup or using the traditional redirection based flow. In the former, a separate window opens up to conduct the authentication. This popup is closed as soon as the payment is complete. You can control this choice by passing the appropriate value in <span style="color:#f48fb1"redirect element.

In the code snippet above showing Juspay.Setup, there are two handlers success_handler and error_handler. If the payment is successful, then success_handler is invoked. If the payment failed, then <span style="color:#f48fb1"error_handler will be invoked.

Redirect Flow

For mobile, redirection flow is chosen by default. You cannot change this. So, you must always ensure that you have coded the case to handle the redirection flow as well.

Card Form Validation

Validation must be implemented by you. Please ensure the following:

  • Card Number must be validated using Luhn Algorithm
  • Expiry date must be in future
  • CVV (security_code) must be 3 digits for Visa/Mastercard/Rupay and 4 digits for American Express
  • Cardholder name must be alphabets & space only
  • Expiry & CVV must be made optional for Maestro cards for better coverage

Stored cards

To checkout using the stored card, the form must contain the card_token element and the security_code element. Please see the sample code below.

<form class="juspay_express_form" id="payment_form">
    <input type="hidden" class="card_token" value="54eb18a0-c7ca-46a3-b122-448d93a3698a"/>
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order"/>
    <label>
        <p>5264-XXXXXXXX-3394</p>
        <p>Expires: 10/24</p>
    </label>
    <input type="text" class="security_code" placeholder="CVV" >
    <button type="submit" class="make_payment">Pay</button>
</form>

Binding to Juspay.Setup is same as above. To handle multiple stored cards, you can create separate forms with different identifiers and bind them individually. It is also possible to handle using a single form.

Using EMI

To support EMI the iFrame payment URL has been enhanced to take additional parameters:

  • is_emi: Indicates if EMI is applicable for this transaction. Valid values are true and false.
  • emi_bank: Issuing bank of the card
  • emi_tenure: Tenure of EMI in months

Note: It is an error to pass is_emi and not pass emi_bank and emi_tenure.

Sample form with EMI support:

<form class="juspay_inline_form" id="payment_form">
    <input type="hidden" class="merchant_id" value="guest">
    <input type="hidden" class="order_id" value="guest_order"/>
    <input type="hidden" class="is_emi" value="true" />
    <input type="hidden" class="emi_bank" value="HDFC" />
    <input type="hidden" class="emi_tenure" value="6" />
    <input type="text" class="card_number" placeholder="Card number">
    <input type="text" class="name_on_card" placeholder="Cardholder name">
    <input type="text" class="card_exp_month" placeholder="MM"> - <input type="text" class="card_exp_year" placeholder="YYYY">
    <input type="text" class="security_code" placeholder="CVV" >
    <input type="checkbox"  class="juspay_locker_save"> Save card information
    <button type="submit" class="make_payment">Pay</button>
    <input type="hidden" class="redirect" value="false">
</form>

Currently supported combinations of emi_bank and emi_tenure are:

EMI BankEMI TenureSupported Gateways
HDFC3,6,9,12,18,24PAYU, HDFC, RAZORPAY
CITI3,6,9,12,18,24PAYU
ICICI3,6,9,12,18,24PAYU, ICICI, CCAVENUE, RAZORPAY
SBI3,6,9,12PAYU, CCAVENUE
AXIS3,6,9,12PAYU, ICICI, CCAVENUE, RAZORPAY
SCB3,6,9,12,18,24ICICI, PAYU
KOTAK3,6,9,12ICICI, CCAVENUE, PAYU, RAZORPAY
HSBC3,6,9,12ICICI, CCAVENUE, PAYU
AMEX3,6,9,12PAYU, CCAVENUE, RAZORPAY
INDUSIND3,6,9,12,18,24PAYU, CCAVENUE, RAZORPAY
RBL3,6,9,12,18,24RAZORPAY, PAYU
BOB3,6,9,12RAZORPAY
YES3,6,9,12,18,24PAYU
ICICIDC3,6,9,12PAYU
AXISDC3,6,9,12PAYU
HDFCDC3,6,9,12,18PAYU, BILLDESK

PCI Compliance

All Juspay clients must be PCI DSS Compliant at all times. When using pay-v2.js, the card information is captured by HTML form which is controlled by your website. This puts your website & domain within the PCI scope. You can achieve compliance by completing the Self Assessment Questionnaire A-EP (SAQ A-EP).

We strongly advise you to upgrade to pay-v3.js.

JS VersionSAQ Requirement
pay.js (legacy)SAQ A-EP
pay-v2.jsSAQ A-EP

iFrame vs Javascript

iFrame vs Javascript

When is iFrame better than Javascript?

  • Complete the integration in 2 days flat
  • Checkout form is always improving and heavily optimized
  • Mobile web experience in Android/iOS suffices

When is Javascript better than iFrame?

  • You wish to completely customize the checkout form (development time is higher)
  • Give native experience to your customers in Android/iOS
iFrameJavascript
Development Time2 days2 weeks
Form factors supportedDesktop & MobileRequires coding
Ability to customize the checkout formMedium (styles only)Very high (you own the form)
Form validationBuilt-inRequires coding
Intelligent Maestro handling 19 digit & 16 digitsBuilt-inRequires coding
Switch between stored cards & new cardBuilt-inRequires coding
Android & iOS experienceMobile WebNative
Promotions: Card based Cash backRule based supportYes (build your own)
Promotions: Card based DiscountsNo supportYes (build your own)
PCI ComplianceSAQ-ASAQ-A EP (for pay.js) SAQ-A (for pay-v2.js)

Switching from iFrame to Javascript

If you get started with iFrame and sometime in the future, would like to transition to Javascript based integration, it is completely feasible to do so.

Payment Links

Payment Links

Now you can send or message payment links to your customers. This will be very convenient for a variety of use cases including Pay on Delivery (an alternative for Cash on Delivery). These links are available as part of the POST /order/create API.

Example

{
  "order_id": "1478851764",
  "id": "ord_e294a26e66ad4336a992ceab81ad704c",
  "status": "CREATED",
  "status_id": 1,
  "payment_links": {
    "web": "https://api.juspay.in/merchant/pay/ord_e294a26e66ad4336a992ceab81ad704c",
    "mobile": "https://api.juspay.in/merchant/pay/ord_e294a26e66ad4336a992ceab81ad704c?mobile=true",
    "iframe": "https://api.juspay.in/merchant/ipay/ord_e294a26e66ad4336a992ceab81ad704c"
  }
}

payment_links attribute will be present in both /order/create API and /order/status API. We have provided three variants to make it easy for your customers. As the name implies, these are best suited for the respective channels.

VariantDescription
webRenders a desktop optimized version of the checkout page
mobileRenders a mobile optimized version of the checkout page
iframeProvides an iFrame that you can embed as part of your checkout page

Payment methods

All the payment methods enabled in your account will be displayed to the user. This is to ensure maximum acceptance which improves your success rate significantly.

Expiry

Links become invalid as soon as the order expires. The default expiry is 15 minutes from the time of creation. This value is customizable via our dashboard. Please follow this link to customize it to your need.

The maximum expiry time is 24 hours. This limit is set due to security restrictions. If you wish to extend the expiry period, then please reach out to us. Your chances of convincing us will improve significantly if you use a good random generator for Order ID attribute.

Pay on Delivery

The link can be directly shared with your customers at the time of product delivery. All the payment options are available to the customer (including stored cards). This makes it very convenient for the customer to pay using their favorite payment option.

The image you see above is a simple depiction of an experience that can be built using our API.

The image you see above is a simple depiction of an experience that can be built using our API.

  1. As your Delivery executive is preparing to deliver an order, they can initiate payment for that order.
  2. Your server sends a notification to your customer via email or SMS or push notification.
  3. The customer sees the checkout page with all the payment options. Proceeds to make payment and completes successfully. You can make it a 1-click experience if you use our Mobile SDK and open the URL there.
  4. Your Delivery executive can refresh the screen and check the payment status, once payment is confirmed can deliver the order.

Security

Anyone involved with the processing, transmission, or storage of credit card data must comply with the Payment Card Industry Data Security Standards (PCI DSS). Juspay makes this easy for you to do, and you can set up a fully PCI-compliant integration by taking the following steps:

  • Serve your payment pages securely using Transport Layer Security (TLS) so that they make use of HTTPS
  • Use Juspay's pay-v3.js to render card elements from Juspay iFrame. This ensures that the cardholder data is accepted and transmitted from Juspay's iFrame to Juspay's servers directly.

TLS

Transport Layer Security (TLS) and its predecessor, Secure Sockets Layer (SSL), both frequently referred to as "SSL", are cryptographic protocols that provide communications security over a network. When secured by TLS, connections between a client (e.g., a web browser) and a server (e.g., wikipedia.org) have one or more of the following properties:

  • Privacy - connection through encryption
  • Identity authentication - identification through certificates, and
  • Reliability - dependable maintenance of a secure connection through message integrity checking.

TLS is designed to prevent eavesdropping and tampering. We currently support TLS v1.2

A digital certificate - a file issued by a certification authority (CA) - is needed in order to use TLS. When installed, this certificate assures the client that it's really communicating with the server it expects to be talking to, not an impostor. Additionally, your customers are more comfortable sharing sensitive information on pages visibly served over HTTPS, which can help increase your customer conversion rate.

PCI DSS guidelines

So long as you ensure that the cardholder data doesn't come in direct contact with your website or servers, your compliance level can remain the easiest - SAQ A. Any deviation can significantly increase the compliance requirements. We have summarized below various scenarios for your quick reference:

MechanismCard entry environmentCompliance Requirement
Redirection to hosted pageUser is redirected from your website. The user enters complete card data is in payment page rendered from Juspay's domainSAQ - A
Embedded iFrameYou embed Juspay's iFrame in your checkout page. The user enters complete card data in iFrame served from Juspay's domainSAQ - A
Pay-v2.jsCardholder data is captured on your website but transmitted using Juspay's iFrameSAQ - A EP
Pay-v3.jsJuspay renders card input elements as iFrame from Juspay's domain. User data is captured directly in Juspay's iFrame and transmitted using Juspay's iFrame.SAQ - A
Direct Card APIYou use Juspay's API to send cardholder dataSAQ - D

For any queries relating to security, you may write to [email protected]


Did this page help you?