Runner.js
Runner.js Overview
Runner.js is a browser-side JavaScript library used to tokenize and send sensitive payment information directly from a user’s browser, keeping your customers’ data secure and your software fully PCI-compliant. A single integration to Runner.js can be used to handle tokenization for all supported Payments API products in Run Developer.
The library is continually updated to support the gateways available through Run Developer and to provide more flexibility to you, our integrated partners. If you have any feedback or questions about the service, please reach out to us at integrations@runpayments.io
Runner.js Parameters
The following table is a list of possible parameters that can be passed when calling Runner.js to tokenize a customer’s payment account:
| Attribute | Description | Account Types | 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 | All | Yes |
publicKey | Your Public key linked to your account | All | Yes |
css | Styling that will get applied to the iframe (account number/cvv) fields in case of card entry. Please send bot url encoded version or JS object | All | No |
env | Possible values: local (requests sent to localhost:8000), staging (requests sent to javelin-staging env), production (requests sent to Run/Javelin production) | All | No |
useExpiry | If true, it will render expiry month/year fields | Card | No |
useCvv | If true it will render the cvv field | Card | No |
cardLabel | Set your own label for the card number input field | Card | No |
cvvLabel | Set your own label for cvv field | Card | No |
expiryLabel | Set your own label for expiry field | Card | No |
cardPlaceholder | Placeholder text for card number field | Card | No |
cvvPlaceholder | Placeholder text for cvv field | Card | No |
accountNumberPlaceholder | Placeholder text for account number field | ACH | No |
routingNumberPlaceholder | Placeholder text for routing number field | ACH | No |
repeatedAccountNumberPlaceholder | Placeholder text for repeated account number field | ACH | No |
accountNumberLabel | Custom label for account number field | ACH | No |
routingNumberLabel | Custom label for routing number field | ACH | No |
repeatedAccountNumberLabel | Custom label for repeated account number label | ACH | No |
accountTypeLabel | Custom label for account type (IStream). Valid account type values are 1, 2, and 3 (Checking, Saving, and Ledger). | ACH | No |
customerNameLabel | Custom label for customer name (IStream) | ACH | No |
entryClassCodeLabel | Custom label for entry class code (IStream) | ACH | No |
tokenizeAutomatically | If you want Runner.js to call tokenize after user stops typing instead of using onBlur event. Default false | All | No |
inactivityto | How long to wait (in ms) for tokenize to be called. Works only if tokenizeAutomatically is set to true. Default 300 | All | No |
errorsMap | URL encoded JS object of custom errors that you can supply to override default error messages. Only applies to ACH form and card connect gateway.Example: URL encoded the following object{"1": "Account number is required","2": "Account number repeat does not match","3": "Routing number is required","4": "Routing number must be 9 digits","5": "Account type is required","6": "Customer name is required",}; | All | No |
errorType | Ability to choose the way errors are displayed in ACH form (applies only to card connect gateway). Possible values: field - errors will be shown below each invalid input fieldlist - errors will be shown as unordered list at the top of the form | All | No |
Examples
Cardpointe Gateway
Passing Merchant ID while using the same Public Key to render the correct version of the iFrame
1 var runner = new Runner(); 2 runner.init({ 3 element: '#run-form', 4 publicKey: 'N1uWuiv8KneR8Rppnnt5fw2n', 5 mid: '800000001780',
Example:
1 var runner = new Runner(); 2 runner.init({ 3 element: '#run-form', 4 publicKey: '<public key>', 5 mid: '<option mid to route to>', 6 useExpiry: true, 7 useCvv: true, 8 cardLabel: 'label', 9 cvvLabel: 'cvv label', 10 expiryLabel: 'Expiration Date<b> (MM/YYYY) </b>', 11 inactivityto: 300, 12 cardPlaceholder: 'Card Number #', 13 cvvPlaceholder: 'CVV #' 14 }); 15 16 runner.onTokenize (function (runnerResult) { 17 console.log(`tokenized: ${JSON.stringify(runnerResult)}`); 18 }); 19 20 document.querySelector('#paybutton').onclick = () => { 21 var successElement = document.querySelector('.success'); 22 var errorElement = document.querySelector('.error'); 23 var loaderElement = document.querySelector('.loader'); 24 25 successElement.classList.remove('visible'); 26 errorElement.classList.remove('visible'); 27 loaderElement.classList.add('visible'); 28 29 var form = document.querySelector('form'); 30 31 var extraDetails = { 32 amount: 10000, 33 name: form.querySelector('input[name=cardholder-first-name]').value + ' ' + form.querySelector('input[name=cardholder-last-name]').value, 34 company_name: 'acme', 35 email: '', 36 phone: form.querySelector('input[name=phone]').value, 37 address1: "4547 East Thompson Street'", 38 address2: '1234', 39 address_city: 'Orlando', 40 address_state: 'FL', 41 account_zip: '32811', 42 address_country: 'USA', 43 order_id: '100', 44 capture: 'Y', 45 46 }; 47 48 runner.tokenize((res) => { 49 var xhr = new XMLHttpRequest(); 50 xhr.open("POST", 'http://<your backend url>' + '/charge', true); 51 xhr.setRequestHeader('Content-Type', 'application/json'); 52 53 var params = JSON.stringify({ 54 ...extraDetails, 55 account_token: res.account_token, 56 expiration: res.expiry, 57 58 }); 59 60 xhr.onreadystatechange = function() { 61 if (xhr.readyState == XMLHttpRequest.DONE) { 62 var resp = JSON.parse(xhr.responseText); 63 console.log(resp); 64 65 if (resp['trans_id']) { 66 successElement.querySelector('.token').textContent = resp['trans_id']; 67 successElement.classList.add('visible'); 68 loaderElement.classList.remove('visible'); 69 } else { 70 errorElement.textContent = typeof resp === 'object' ? (resp && resp.error) || Object.keys(resp).map((k) => resp[k].join(' ')).join(' ') : JSON.stringify(resp); 71 errorElement.classList.add('visible'); 72 loaderElement.classList.remove('visible'); 73 } 74 } 75 } 76 77 xhr.send(params); 78 79 }) 80 };
Full HTML example:
Example:
1 <form onsubmit="return false;"> 2 <div class="group"> 3 <label> 4 <span>First Name</span> 5 <input 6 name="cardholder-first-name" class="field input-box" placeholder="Jane" /> 7 </label> 8 <label> 9 <span>Last Name</span> 10 <input name="cardholder-last-name" class="field input-box" placeholder="Doe" /> 11 </label> 12 <label> 13 <span>Phone</span> 14 <input name="phone" class="field input-box" placeholder="+1000000000000" /> 15 </label> 16 </div> 17 <div class="group" style="height: 200px;"> 18 <label> 19 <span>Card</span> 20 <div id="card-element" class="field"> 21 <div id="run-form"></div> 22 </div> 23 </label> 24 </div> 25 <button id="paybutton">Pay</button> 26 <div class="outcome"> 27 <div class="error"></div> 28 <div class="success"> 29 Successful! The Result is 30 <span class="token"></span> 31 </div> 32 <div class="loader" style="margin: auto"> 33 </div> 34 </form> 35 36 37 38 39 40 ### Cybersource Gateway 41 42 If on your form there is a div like this: 43 44 ```jsx 45 <div id="cvvId"></div>
Then in the init function, you should have cvvFieldSelector: '#cvvId',
Example:
1 runner.init({ 2 element: '#run-form', 3 publicKey: 'TQhD2CRs9hedqYkozkdM4GnW', 4 useCvv: true, 5 cybersourceCvvField: '#cvvId', 6 cvvLabel: 'test cvv label', 7 cardLabel: 'test card label', 8 css: { 9 formContainer: { 10 'input': { 11 'font-size': '26px', 12 'color': 'red' 13 }, 14 }, 15 cardNumber: { 16 'input': { 17 'font-size': '16px', 18 'color': 'green' 19 }, 20 }, 21 } 22 });
Full HTML example:
1 <div id="pay-example"> 2 3 <form id="my-sample-form" onsubmit="return false;"> 4 <div id="run-form"></div> 5 <div class="group"> 6 <label> 7 <span>First Name</span> 8 <input name="cardholder-first-name" class="field input-box" placeholder="Jane" /> 9 </label> 10 <label> 11 <span>Last Name</span> 12 <input name="cardholder-last-name" class="field input-box" placeholder="Doe" /> 13 </label> 14 <label> 15 <span>Phone</span> 16 <input name="phone" class="field input-box" placeholder="+1000000000000" /> 17 </label> 18 <label> 19 <span>Vault ID</span> 20 <input name="vault_id" class="field input-box" placeholder="" /> 21 </label> 22 </div> 23 <div class="group"> 24 <label id="cardNumber-label">Card Number</label> 25 <div id="cardNumber-container"></div> 26 </div> 27 <div class="group" > 28 <label id="securityCode-label">Cvv</label> 29 <div id="cvvId"></div> 30 <%# <input name="cvv" id="cvvId" class="field input-box" /> %> 31 </div> 32 33 <div class="group" > 34 <label id="exp-label">Exp month</label> 35 <input name="expmonth" class="field input-box" placeholder="" /> 36 <label id="exp-label">Exp year</label> 37 <input name="expyear" class="field input-box" placeholder="" /> 38 </div> 39 40 <div class="group"> 41 <label id="exp-label">Transaction ID to capture:</label> 42 <input name="capture_id" /> 43 </div> 44 45 <div class="group"> 46 <label id="exp-label">Transaction ID to void:</label> 47 <input name="void_id" /> 48 </div> 49 50 <div class="group"> 51 <label id="exp-label">Transaction ID to refund:</label> 52 <input name="refund_id" /> 53 </div> 54 55 <button id="pay-button">Pay $100</button> 56 </form> 57 </div>
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.
1 <div class="group"> 2 <label id="cardNumber-label">Card Number</label> 3 <div id="cardNumber-container"></div> 4 </div> 5 <div class="group" > 6 <label id="securityCode-label">Cvv</label> 7 <div id="securityCode-container"></div> 8 </div>
Payroc Gateway
The Payroc Gateway implementation requires specific field selectors and configuration options to properly handle form validation and tokenization.
1 <div id="pay-example"> 2 3 <form id="my-sample-form" onsubmit="return false;"> 4 <div id="run-form"></div> 5 <div class="group"> 6 <div class="card-holder-name"></div> 7 <div class="card-holder-name-error error-message"></div> 8 <label> 9 <span>Phone</span> 10 <input name="phone" class="field input-box" placeholder="+1000000000000" /> 11 </label> 12 <label> 13 <span>Vault ID</span> 14 <input name="vault_id" class="field input-box" placeholder="" /> 15 </label> 16 </div> 17 <div class="group" > 18 <label id="cardNumber-label">Card Number</label> 19 <div id="cardNumber-container"></div> 20 <div id="cardNumber-error"></div> 21 </div> 22 <div class="group cvv-wrapper" > 23 <label id="securityCode-label">Cvv</label> 24 <div id="securityCode-container"></div> 25 <div id="securityCode-error"></div> 26 </div> 27 28 <div class="group"> 29 <label> 30 <span>Expiration</span> 31 <div id="expiration-container"></div> 32 <div id="expiration-error"></div> 33 </label> 34 </div> 35 36 <div id="pay-button"></div> 37 <div class="outcome"> 38 <div class="error"></div> 39 <div class="success"> 40 Successful! The Result is 41 <span class="token"></span> 42 43 </div> 44 <div class="loader" style="margin: auto"> 45 </div> 46 </div> 47 </form> 48 </div>
ACH (iStream and Fiserv ACH)
Both iStream and Fiserv ACH gateways provide bank account tokenization with customizable field labels and validation. The implementation supports automatic or manual tokenization depending on your requirements.
1 <div id="pay-example"> 2 <form id="my-sample-form" onsubmit="return false;"> 3 <div id="run-form"></div> 4 <div class="group"> 5 <label> 6 <span>Customer Name</span> 7 <input name="customer_name" class="field input-box" placeholder="John Doe" /> 8 </label> 9 </div> 10 <button id="pay-button">Process ACH Payment</button> 11 <div class="outcome"> 12 <div class="error"></div> 13 <div class="success"> 14 Successful! The Result is 15 <span class="token"></span> 16 </div> 17 <div class="loader" style="margin: auto"></div> 18 </div> 19 </form> 20 </div>