TAP JavaScript library can be used for building payment flows. With it you can collect sensitive Card information from the user in your web pages and create representative Tokens for safely sending that data to your servers.
Card Element
TAP JS library’s card element is a prebuilt UI component. It collects card details from customers and tokenizes the sensitive information with in the element without ever touching your server. Card element includes feature like
- Automatically format card information as it’s entered
- Currency validation for payment options
- Input validation and error response
- Real time BIN response (The leading six digits of the card number is the "bank identification number or BIN", sometimes referred to as the "issuer identification number or IIN")
- Responsive design to fit the width of your customer’s screen or mobile device
- Customizable styling to match the look and feel of your checkout flow
- Customizable styling to match the look and feel of your checkout flow
- Result
- HTML
- CSS
- Javascript
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js"></script>
<script src="https://secure.gosell.io/js/sdk/tap.min.js"></script>
<form id="form-container" method="post" action="/charge">
<!-- Tap element will be here -->
<div id="element-container"></div>
<div id="error-handler" role="alert"></div>
<div id="success" style=" display: none;;position: relative;float: left;">
Success! Your token is <span id="token"></span>
</div>
<!-- Tap pay button -->
<button id="tap-btn">Submit</button>
</form>
.form-row {
width: 70%;
float: left;
background-color: #ededed;
}
#card-element {
background-color: transparent;
height: 40px;
border-radius: 4px;
border: 1px solid transparent;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
#card-element--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
#card-element--invalid {
border-color: #fa755a;
}
#card-element--webkit-autofill {
background-color: #fefde5 !important;
}
#submitbutton,#tap-btn{
align-items:flex-start;
background-attachment:scroll;background-clip:border-box;
background-color:rgb(50, 50, 93);background-image:none;
background-origin:padding-box;
background-position-x:0%;
background-position-y:0%;
background-size:auto;
border-bottom-color:rgb(255, 255, 255);
border-bottom-left-radius:4px;
border-bottom-right-radius:4px;border-bottom-style:none;
border-bottom-width:0px;border-image-outset:0px;
border-image-repeat:stretch;border-image-slice:100%;
border-image-source:none;border-image-width:1;
border-left-color:rgb(255, 255, 255);
border-left-style:none;
border-left-width:0px;
border-right-color:rgb(255, 255, 255);
border-right-style:none;
border-right-width:0px;
border-top-color:rgb(255, 255, 255);
border-top-left-radius:4px;
border-top-right-radius:4px;
border-top-style:none;
border-top-width:0px;
box-shadow:rgba(50, 50, 93, 0.11) 0px 4px 6px 0px, rgba(0, 0, 0, 0.08) 0px 1px 3px 0px;
box-sizing:border-box;color:rgb(255, 255, 255);
cursor:pointer;
display:block;
float:left;
font-family:"Helvetica Neue", Helvetica, sans-serif;
font-size:15px;
font-stretch:100%;
font-style:normal;
font-variant-caps:normal;
font-variant-east-asian:normal;
font-variant-ligatures:normal;
font-variant-numeric:normal;
font-weight:600;
height:35px;
letter-spacing:0.375px;
line-height:35px;
margin-bottom:0px;
margin-left:12px;
margin-right:0px;
margin-top:28px;
outline-color:rgb(255, 255, 255);
outline-style:none;
outline-width:0px;
overflow-x:visible;
overflow-y:visible;
padding-bottom:0px;
padding-left:14px;
padding-right:14px;
padding-top:0px;
text-align:center;
text-decoration-color:rgb(255, 255, 255);
text-decoration-line:none;
text-decoration-style:solid;
text-indent:0px;
text-rendering:auto;
text-shadow:none;
text-size-adjust:100%;
text-transform:none;
transition-delay:0s;
transition-duration:0.15s;
transition-property:all;
transition-timing-function:ease;
white-space:nowrap;
width:150.781px;
word-spacing:0px;
writing-mode:horizontal-tb;
-webkit-appearance:none;
-webkit-font-smoothing:antialiased;
-webkit-tap-highlight-color:rgba(0, 0, 0, 0);
-webkit-border-image:none;
}
//pass your public key from tap's dashboard
var tap = Tapjsli('pk_test_EtHFV4BuPQokJT6jiROls87Y');
var elements = tap.elements({});
var style = {
base: {
color: '#535353',
lineHeight: '18px',
fontFamily: 'sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: 'rgba(0, 0, 0, 0.26)',
fontSize:'15px'
}
},
invalid: {
color: 'red'
}
};
// input labels/placeholders
var labels = {
cardNumber:"Card Number",
expirationDate:"MM/YY",
cvv:"CVV",
cardHolder:"Card Holder Name"
};
//payment options
var paymentOptions = {
currencyCode:["KWD","USD","SAR"],
labels : labels,
TextDirection:'ltr'
}
//create element, pass style and payment options
var card = elements.create('card', {style: style},paymentOptions);
//mount element
card.mount('#element-container');
//card change event listener
card.addEventListener('change', function(event) {
if(event.BIN){
console.log(event.BIN)
}
if(event.loaded){
console.log("UI loaded :"+event.loaded);
console.log("current currency is :"+card.getCurrency())
}
var displayError = document.getElementById('error-handler');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission
var form = document.getElementById('form-container');
form.addEventListener('submit', function(event) {
event.preventDefault();
tap.createToken(card).then(function(result) {
console.log(result);
if (result.error) {
// Inform the user if there was an error
var errorElement = document.getElementById('error-handler');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server
var errorElement = document.getElementById('success');
errorElement.style.display = "block";
var tokenElement = document.getElementById('token');
tokenElement.textContent = result.id;
console.log(result.id);
}
});
});
HTTPS requirements
All submissions of payment info using Elements are made via a secure HTTPS connection. However, to protect yourself from certain forms of man-in-the-middle attacks, and to prevent your customers from seeing Mixed Content warnings in modern browsers, you must serve the page containing the payment form over HTTPS as well. In short, the address of the page containing Elements must start with https:// rather than just http://. If you are not familiar with the process of buying SSL certificates and integrating them with your server to enable a secure HTTPS connection, Please ask a server administrator to set it up.
Step 1: Set up TAP JS Elements
Elements is available as part of TAP JS library. To get started, include this script on your pages—it should always be loaded directly from https://secure.gosell.io/js/sdk/tap.min.js: In the header of your html web page.
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js"></script>
<script src="https://secure.gosell.io/js/sdk/tap.min.js"></script>
Responsive Dimension Optional
To make JS element scale to dimensions of the device, You should include the following meta tag in your html header.
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Step 2: Create your payment form
To securely collect card details from your customers, Elements creates UI components for you that are hosted by Tap payments. They are then placed into your payment form, rather than you creating them directly.
To determine where to insert these components, create empty DOM elements (containers) with unique IDs within your payment form.
For example:
<form id="form-container" method="post" action="/charge">
<!-- Tap element will be here -->
<div id="element-container"></div>
<div id="error-handler" role="alert"></div>
<div id="success" style=" display: none;;position: relative;float: left;">
Success! Your token is <span id="token"></span>
</div>
<!-- Tap pay button -->
<button id="tap-btn">Submit</button>
</form>
When the form above has loaded, in javascript create an instance of an Element and mount it to the Element container created above. Tap provides a public key to access js library and initialized to your TAP account. This public key should be passed as parameter to Tapjsli().
Javascript
//pass your public key from tap's dashboard
var tap = Tapjsli('pk_test_EtHFV4BuPQokJT6jiROls87Y');
var elements = tap.elements({});
var style = {
base: {
color: '#535353',
lineHeight: '18px',
fontFamily: 'sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: 'rgba(0, 0, 0, 0.26)',
fontSize:'15px'
}
},
invalid: {
color: 'red'
}
};
// input labels/placeholders
var labels = {
cardNumber:"Card Number",
expirationDate:"MM/YY",
cvv:"CVV",
cardHolder:"Card Holder Name"
};
//payment options
var paymentOptions = {
currencyCode:["KWD","USD","SAR"],
labels : labels,
TextDirection:'ltr'
}
//create element, pass style and payment options
var card = elements.create('card', {style: style},paymentOptions);
//mount element
card.mount('#element-container');
//card change event listener
card.addEventListener('change', function(event) {
if(event.loaded){
console.log("UI loaded :"+event.loaded);
console.log("current currency is :"+card.getCurrency())
}
var displayError = document.getElementById('error-handler');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
Step 3: Create a token to securely transmit card information
The payment details collected using Elements can then be converted into a token. Create an event handler that handles the submit event on the form. The handler sends the fields to TAP for tokenization and prevents the form’s submission (the form is submitted by JavaScript in the next step).
Javascript
// Handle form submission
var form = document.getElementById('form-container');
form.addEventListener('submit', function(event) {
event.preventDefault();
tap.createToken(card).then(function(result) {
console.log(result);
if (result.error) {
// Inform the user if there was an error
var errorElement = document.getElementById('error-handler');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server
var errorElement = document.getElementById('success');
errorElement.style.display = "block";
var tokenElement = document.getElementById('token');
tokenElement.textContent = result.id;
tapTokenHandler(token)
}
});
});
tap.createToken returns a Promise which resolves with a result object. This object has either:
- result.id: a Token was created successfully.
- result.error: there was an error. This includes client-side validation errors.
Step 4: Submit the token and the rest of your form to your server
The last step is to submit the token, along with any additional information that has been collected, to your server.
Javascript
function tapTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'tapToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
Get Card Details
The leading six digits of the card number is the "bank identification number (BIN)", sometimes referred to as the "issuer identification number (IIN)".
TAP JS Card element also returns BIN details in real time.
Check the highlighted part of the script below if you want to use the BIN in your application(s).
Javascript
card.addEventListener('change', function(event) {
if(event.BIN){
console.log(event.BIN)
}
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
BIN response sample
{
"bin":"424242",
"bank":"",
"card_brand":"VISA",
"card_type":"CREDIT",
"card_category":"",
"card_scheme":"VISA",
"country_name":"UNITED KINGDOM",
"country":"GB",
"website":"",
"phone":"",
"address_required":false,
"api_version":"V2"
}
Possible utilities of BIN
- Card origin identification
- Targeted campaigns for card origins
- Currency identification
- Shipping feasibility
Element Options
Option | Description | Target |
---|---|---|
style.base.color | Text Color | Input |
style.base.lineHeight | Line height | Input |
style.base.fontFamily | Font Family | Input |
style.base.fontSmoothing | Font Smoothing | Input |
style.base.fontSize | Font Size | Input |
style.base['::placeholder'].color | Color | Input |
style.base['::placeholder'].fontSize | Font Size | Input |
style.invalid.color | Color of text when input is invalid | Input |
paymentOptions.labels.cardNumber | Place holder for credit card | Input |
paymentOptions.labels.expirationDate | Place holder for expiry date | Input |
paymentOptions.labels.cvv | Place holder for CVV | Input |
paymentOptions.labels.cardHolder | Place holder for Card Owner Name | Input |
paymentOptions.currencyCode | array of three-letter alphabetic ISO currency codes | Currency support |
paymentOptions.paymentAllowed | array of payment method to be allowed, options ['VISA', 'MASTERCARD', 'AMEX', 'MADA'], default string 'all' | Payment Methods support |
paymentOptions.TextDirection | sets the direction of text, table columns, and horizontal overflow, only two values valid (rtl, ltr) | Input |
Library methods
Method | Description |
---|---|
Tapjsli('PUBLIC API') | Authenticates and validates public key access |
Tapjsli('PUBLIC API','MERCHANT ID') | (optional) Authenticates public key and merchant id access |
tap.elements({}) | Initiates Element |
elements.create('card', {style: style},paymentOptions) | Creates Card Element with given options |
card.mount('#element-container') | mounts/loads UI into html container |
card.addEventListener('change', function(event) {}); | Adds change event listener to card element |
event.loaded | If ‘true’, js library is loaded |
card.currency(‘SAR’) | Changes currency in real time, supplied value must be valid three-letter alphabetic ISO currency code |
card.clearForm() | Clears the form inputs and errors |