Guides


Run Developer Home

Getting Started

Tokenize with Runner.js

Reporting with Run Merchant

Boarding API

Validation & Deployment

Changelog

What is Runner.js?


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>

Usage


  1. Add Runner.js to your website by adding the following script tag to the ‘head’ of your HTML file.
<script src=”https://javelin.runpayments.io/javascripts/runner.js”></script>
  1. Initialize Runner.js.
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
    });
  1. (Optional) Subscribe to iframe loaded event:
runner.onLoaded(function() {
       console.log('loaded');
  });
  1. 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.

  2. 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);

})};
     

Parameters


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

Examples


Cardpointe Gateway

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',

Cybersource Gateway

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

Go to top