Pay-V3.js

Checkout using Javascript

This mode of integration is 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"/>
    <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"/>
    <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"/>
</form>
<button type="button" class="make_payment">Pay</button>

For saved cards, you need to create a separate form for each saved card and a common submit button which will submit the saved card form selected by the user. All these forms will have 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 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 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. 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) {}
        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 user types the valid data,
         * which will have the following order:
         * `card_exp_month` -> `card_exp_year` -> `security_code`.
         * Note: You can ignore `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 `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 parameter in two cases:
         * 1. When some event occurs on the input 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.)
         *
         * 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 valud 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.partially_valid - This explains whether the user is typing the card number correctly. (Available only when target_element is card_number)
             *      
             *  9. 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 current year and the input month is any month before 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 validaate whether expiry_valid is true or not. (Available only when target_element is either card_exp_month or card_exp_year)
             *
             * 10. 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.
             */
        }
    })
</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>

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>

Card Form Validation

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

Using EMI

To support EMI include the following parameters while creating the payment form:

  • 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" />
    <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 Bank EMI Tenure Supported Gateways
HDFC 3,6,9,12,18,24 PAYU, HDFC, RAZORPAY
CITI 3,6,9,12,18,24 PAYU
ICICI 3,6,9,12,18,24 PAYU, ICICI, CCAVENUE, RAZORPAY
SBI 3,6,9,12 PAYU, CCAVENUE
AXIS 3,6,9,12 PAYU, ICICI, CCAVENUE, RAZORPAY
SCB 3,6,9,12,18,24 ICICI, PAYU, RAZORPAY
KOTAK 3,6,9,12 ICICI, CCAVENUE, PAYU, RAZORPAY
HSBC 3,6,9,12 ICICI, CCAVENUE, PAYU
AMEX 3,6,9,12 PAYU, CCAVENUE, RAZORPAY
INDUSIND 3,6,9,12,18,24 PAYU, CCAVENUE, RAZORPAY
RBL 3,6,9,12,18,24 RAZORPAY, PAYU
YES 3,6,9,12,18,24 PAYU
ICICIDC 3,6,9,12 PAYU
AXISDC 3,6,9,12 PAYU

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 Version SAQ Requirement
pay-v3.js SAQ A
pay-v2.js (deprecated) SAQ A-EP