Runner.js is a browser-side JavaScript library used to tokenize and send sensitive payment information directly from a user’s browser, keeping your customer’s data secure and your software fully PCI-compliant. A single integration to Runner.js will provide your tokenization needs for your integration regardless of the end payment processor for your merchant accounts.
<aside> ✅ If you’d like to tokenize a payment account without integrating to Runner.js, log on to the Run Merchant portal and navigate to the Developer menu where you will find a card tokenizer for your merchant account. Please reach out to your Integration Delivery lead if you do not see this menu in your account.
</aside>
<script src=”https://javelin.runpayments.io/javascripts/runner.js”></script>
var runner = new Runner();
runner.init({
element: '#run-form',
publicKey: <YOUR KEY>,
css: 'input%7Bwidth%3A200px%3B%7D',
useExpiry: true,
useCvv: true,
cardLabel: 'test label',
cvvLabel: 'test cvv label',
expiryLabel: 'test expiry label',
tokenizeAutomatically: true,
inactivityto: 200
});
runner.onLoaded(function() {
console.log('loaded');
});
Call the “tokenize
” method to make an API call to Run Payments’ backend. (Note: This action can be completed during form submission.) The resulting value may then be passed to the Payment API to enact payment processing activities.
Call the Payments API. Using the resulting token from step 4, you can pass the stored credit card or bank data, along with supplemental order information, to the Payments API to complete a transaction.
runner.tokenize((res) => {
// let’s make an API call to the backend
var xhr = new XMLHttpRequest();
xhr.open(”POST”, “<https://example.com/charge”>, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onerror = function (err) {
// handle error here…
errorElement.textContent = typeof err === 'object' ? (err && err.error) || Object.keys(err).map((k) => err[k].join(' ')).join(' ') : JSON.stringify(err);
errorElement.classList.add('visible');
loaderElement.classList.remove('visible');
};
// other params from your payment form
var extraDetails = {
amount: 10000,
name: “John Doe:,
email: '[email protected]',
phone: “1231231231”,
address1: '100 New York, 5th ',
address2: '',
address_city: 'Orlando',
address_state: 'FL',
account_zip: '32811',
address_country: 'USA',
capture: 'Y', // Y - auth and charge ‘N’ - just auth
vault: 'Y', // Y - return vault_id in successful response - stores customer and card info in a vault object; N - does not store card/customer data
}
var params = JSON.stringify({
...extraDetails,
account_token: res.account_token, // card number tokenized
expiration: res.expiry, // expiration
});
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var resp = JSON.parse(xhr.responseText);
if (resp['trans_id']) { // successful resp returns trans_id identifier
successElement.querySelector('.token').textContent = resp['trans_id'];
} else {
// handle error here…
}
}
}
xhr.send(params);
})};
Attribute | Description | Required |
---|---|---|
element |
ID (with #) of the element where to load the card number/CVV fields (iframe) or the account/routing number in case of ACH | Yes |
publicKey |
Your Public key linked to your account | Yes |
css |
Styling that will get applied to the iframe (account number/cvv) fields in case of card entry. For ACH it is ignored since account/routing fields are not part of the iframe. | |
Please send URL encoded values. | No | |
useExpiry |
If true, it will render expiry month/year fields | No |
useCvv |
If true it will render the cvv field | No |
cardLabel |
Set your own label for the card number input field | No |
cvvLabel |
Set your own label for cvv field | No |
expiryLabel |
Set your own label for expiry field | No |
tokenizeAutomatically |
If you want Runner.js to call tokenize after user stops typing instead of using onBlur event. Default false | No |
inactivityto |
How long to wait (in ms) for tokenize to be called. Works only if tokenizeAutomatically is set to true. Default 300 | not required |
Passing Merchant ID while using the same Public Key to render the correct version of the iFrame
var runner = new Runner();
runner.init({
element: '#run-form',
publicKey: 'N1uWuiv8KneR8Rppnnt5fw2n',
mid: '800000001780',
If on your form there is a div like this:
<div id="cvvId"></div>
Then in the init function, you should have cvvFieldSelector: '#cvvId',
Example:
runner.init({
element: '#run-form',
publicKey: 'TQhD2CRs9hedqYkozkdM4GnW',
useCvv: true,
cybersourceCvvField: '#cvvId',
cvvLabel: 'test cvv label',
cardLabel: 'test card label',
css: {
formContainer: {
'input': {
'font-size': '26px',
'color': 'red'
},
},
cardNumber: {
'input': {
'font-size': '16px',
'color': 'green'
},
},
}
});
HTML:
<div class="group">
<label id="cardNumber-label">Card Number</label>
<div id="cardNumber-container"></div>
</div>
<div class="group" >
<label id="securityCode-label">Cvv</label>
<div id="cvvId"></div>
</div>
<div class="group" >
<label id="exp-label">Exp month</label>
<input name="expmonth" class="field input-box" placeholder="" />
<label id="exp-label">Exp year</label>
<input name="expyear" class="field input-box" placeholder="" />
</div>
Full HTML example:
<div id="pay-example">
<form id="my-sample-form" onsubmit="return false;">
<div id="run-form"></div>
<div class="group">
<label>
<span>First Name</span>
<input
name="cardholder-first-name" class="field input-box" placeholder="Jane" />
</label>
<label>
<span>Last Name</span>
<input name="cardholder-last-name" class="field input-box" placeholder="Doe" />
</label>
<label>
<span>Phone</span>
<input name="phone" class="field input-box" placeholder="+1000000000000" />
</label>
<label>
<span>Vault ID</span>
<input name="vault_id" class="field input-box" placeholder="" />
</label>
</div>
<div class="group">
<label id="cardNumber-label">Card Number</label>
<div id="cardNumber-container"></div>
</div>
<div class="group" >
<label id="securityCode-label">Cvv</label>
<div id="cvvId"></div>
<%# <input name="cvv" id="cvvId" class="field input-box" /> %>
</div>
<div class="group" >
<label id="exp-label">Exp month</label>
<input name="expmonth" class="field input-box" placeholder="" />
<label id="exp-label">Exp year</label>
<input name="expyear" class="field input-box" placeholder="" />
</div>
<div class="group">
<label id="exp-label">Transaction ID to capture:</label>
<input name="capture_id" />
</div>
<div class="group">
<label id="exp-label">Transaction ID to void:</label>
<input name="void_id" />
</div>
<div class="group">
<label id="exp-label">Transaction ID to refund:</label>
<input name="refund_id" />
</div>
<button id="pay-button">Pay $100</button>
</form>
</div>
Javascript:
<script>
(function() {
var runner = new Runner();
runner.init({
element: '#run-form',
publicKey: '<your key here>',
useCvv: true,
cvvFieldSelector: '#cvvId',
cardNumberFieldSelector: "#cardNumber-container",
cvvLabel: 'test cvv label',
cardLabel: 'test card label',
css: {
formContainer: {
'input': {
'font-size': '26px',
'color': 'red'
},
},
cardNumber: {
'input': {
'font-size': '16px',
'color': 'green'
},
},
}
});
document.querySelector('#pay-button').onclick = () => {
var successElement = document.querySelector('.success');
var errorElement = document.querySelector('.error');
var loaderElement = document.querySelector('.loader');
successElement.classList.remove('visible');
errorElement.classList.remove('visible');
loaderElement.classList.add('visible');
var form = document.querySelector('form');
var extraDetails = {
amount: 100,
name: form.querySelector('input[name=cardholder-first-name]').value + ' ' + form.querySelector('input[name=cardholder-last-name]').value,
company_name: 'acme',
email: '[email protected]',
phone: form.querySelector('input[name=phone]').value,
address1: '100 S Orange Ave',
address2: '',
city: 'Orlando',
region: 'FL',
currency: 'USD',
address_state: 'FL',
account_zip: '32811',
country: 'US',
order_id: '100',
capture: 'Y',
vault: 'Y',
vault_id: form.querySelector('input[name=vault_id]').value,
};
console.log(extraDetails);
runner.tokenize((res) => {
// console.log(res);
var xhr = new XMLHttpRequest();
xhr.open("POST", '<http://localhost:3001>' + '/charge', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onerror = function (err) {
errorElement.textContent = typeof err === 'object' ? (err && err.error) || Object.keys(err).map((k) => err[k].join(' ')).join(' ') : JSON.stringify(err);
errorElement.classList.add('visible');
loaderElement.classList.remove('visible');
};
var params = JSON.stringify({
...extraDetails,
account_token: document.querySelector('#mytoken').value,
expiration: document.querySelector('input[name=expmonth]').value + document.querySelector('input[name=expyear]').value,
cvn: document.querySelector('input[name=cvv]')?.value || '222',
});
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
alert(xhr.responseText);
var resp = JSON.parse(xhr.responseText);
console.log(resp);
if (resp['trans_id']) {
successElement.querySelector('.token').textContent = resp['trans_id'];
successElement.classList.add('visible');
loaderElement.classList.remove('visible');
} else {
errorElement.textContent = typeof resp === 'object' ? (resp && resp.error) || Object.keys(resp).map((k) => resp[k].join(' ')).join(' ') : JSON.stringify(resp);
errorElement.classList.add('visible');
loaderElement.classList.remove('visible');
}
}
}
console.log(params);
// send the request and parse the response
xhr.send(params);
console.log(res.account_token)
}, form.querySelector('input[name=expmonth]').value, form.querySelector('input[name=expyear]').value)
};
When there is an error where the html element cannot be specified, check to ensure html includes form ID or credit card field identifier. The below must be present if using element: ‘#run-form’
<div id="run-form"></div>
Since cvvFieldSelector
was omitted, runner.js will use the default #securityCode-container
selector as well as the cardNumberFieldSelector
if omitted, so #cardNumber-container
selector should be used.
<div class="group">
<label id="cardNumber-label">Card Number</label>
<div id="cardNumber-container"></div>
</div>
<div class="group" >
<label id="securityCode-label">Cvv</label>
<div id="securityCode-container"></div>
</div>
© 2024 Run Payments LLC