Pay-V3 Integration

Checkout using Javascript Integration

Javascript based integration helps merchants overcome the PCI compliance overheads while it gives them the ultimate flexibility to define the checkout experience for the customer.

In this mode of integration, Juspay provides a card form that merchants can embed in their page. Doing so ensures that the card details are effectively collected on Juspay's page.

🚧

PCI Compliance Guidelines

As per PCI DSS guidelines, non compliant merchants cannot store users' card number on their server. The Pay-V3.js implementation on web platform is alternative provided by Juspay through which your website is completely shielded away from getting any sensitive card information.

Create Order

Order creation must be done with Juspay via a backend server to server call. For the API reference, please refer 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 overheads for you.

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

Implementing Checkout Payment Form

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 in HTML - whichever way you are used to building forms on web platform.

For New 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="checkbox" class="tokenize"> Merchant hosted consent screen
    <input type="hidden" class="redirect" value="true"/>
    <input type="radio" class="auth_type" value="" name="auth_type"> Verify with Secure Password
    <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, card_exp_month, card_exp_year, security_code and name_on_card (optional) fields. You need to assign a unique class name for each div as given in above example.

The key tokenize should be passed only when tokenization consent screen is hosted by merchant. The value should be passed as true, only if customer has given consent for tokenization.

For Saved Cards

<form class="juspay_inline_form" id="payment_form1">
    <input type="hidden" class="merchant_id" value="guest"/>
    <input type="hidden" class="order_id" value="guest_order1"/>
    <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="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_order2"/>
    <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="hidden" class="redirect" value="true"/>
    <button type="submit" class="make_payment">Pay</button>
</form>

In the above case, all the forms will have the same class name for common styling and different ids for identification. In the above form, you need to write the <div> element for security_code fields. All the saved card forms should have the same class name for security_code divs.

📘

Pay-V3 Note

There is no need to write input elements here, since Juspay will be inserting their iframe elements inside the div, which will have the input element.

For Other Payment Methods

<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>
<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>
<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 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 field represents the merchant_id of your account. This will be provided by the Juspay team.
  • payment_method_type field identifies the category of the payment instrument being used. It can be one of CARD, NB, WALLET, etc.
  • payment_method field identifies the actual payment instrument being used. (Sample list of payment methods for NetBanking is shown in the form above)
  • juspay_locker_save field indicates to Juspay 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 securely to process it for payment. It 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.

Sample Code Snippet for New Cards

<script type="text/javascript">
      var juspay_form = 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: 6,
       
        /* Fingerprint will work only if customer_id and client_auth_token are present in set-up as shown below */
        customer: {
          customer_id: "cst_mfdepvmfhs3j1mcq",
          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 (recommended but optional). 
         * It will have the following order:`card_exp_month` -> `card_exp_year` ->`security_code`. */
        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 after card_number (recommended but optional).
         * Note 1: Please set `auto_tab_enabled` to `true` as shown above to enable this functionality. */
        auto_tab_from_card_number : "card_exp_month",

       /* Set `tokenize_support` flag to true if you want to check tokenize support response of a particular card bin. */
       tokenize_support : true,

        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 event information will be available in the event object */
            console.log(event);
            switch (event.target_element) {
              case "card_number":
                if (event.empty) {
                  frm.find(".card_number_div").addClass("invalid");
                } else if (event.valid) {
                  juspay_form.get_card_fingerprint({ /* This function will give card fingerprint in Pay-v3 callback once complete card number has been entered */
                    success_handler: function (response) {
                      console.log("got success_handler response", response);
                    },
                    error_handler: function (response) {
                      console.log("got error_handler response", response);
                    },
                  });

                  frm.find(".card_number_div").removeClass("invalid");
                } else if (event.partially_valid) {
                  frm.find(".card_number_div").removeClass("invalid");
                } else {
                  frm.find(".card_number_div").addClass("invalid");
                }
                break;
          },
        },
    })
</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>

The key "tokenize" should be passed when tokenization consent screen is hosted by Merchant. Value should be true if customer has given consent for tokenization.

Sample Code Snippet for Saved Cards

<script type="text/javascript">
     var juspay_form = 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: "xxx"
                }
            }
        },
        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 event information will be available in the event object 
             
             *  1. event.target_element - (security_code) 
             *  2. event.valid - (true/false) 
             *  3. event.empty - (true/false) 
             *  4. event.card_brand  */
        }
    })
</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.

Card Form Validation

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

Event

Possible Values

Description

event.target_element

card_number/ name_on_card/ card_exp_month/ card_exp_year/ security_code

Name of the field which generated this event

event.type

focus/ blur/ keyup/ change

This field explains the event type which triggered the event callback

event.valid

true/ false

This field explains whether the value inside the input field of target_element is valid or not

event.empty

true/ false

This field explains whether the input field of target_element is empty or not

event.card_isin

Card bin value of the card number
(Available only when target_element is card_number)

event.card_brand

MASTERCARD/ VISA/ MAESTRO/ AMEX/ DINERS/ DISCOVER/ JCB/ RUPAY

Card brand value of the card number
(Available only when target_element is card_number)

event.card_type

DEBIT/ CREDIT

Card type identifier of the card number
(Available only when target_element is card_number)

event.card_sub_type

(Only available for >= 9 digit card bin requests)

event.partially_valid

This field explains whether the user is typing the card number correctly
(Available only when target_element is card_number)

event.expiry_valid

This field 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)

event.mandate_support

true/ false

This field explains whether the card number entered is eligible for the mandate transaction

event.bank

(Only available for >= 9 digit card bin requests)

event.tokenize_support

true/ false

This field provides tokenize support response for a particular card bin

For Encoding the Card Details

<script type="text/javascript">
    var juspay_form = 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>

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

For Netbanking, Wallets and UPI

<script type="text/javascript">
    var juspay_form = 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>

Using EMI

To support EMI the pay-v3.js 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>