API Reference

Documentation (v2.0)

Passage.Js

How to Integrate Passage.JS Into Website - Tutorial Video

Passage.js is a JavaScript library that allows merchants to securely collect sensitive payment information from users and send it directly to Valor. Merchants can integrate the library and fully customize the checkout form according to their requirements. Authentication is handled using a Client Token, which is generated via the GetClientToken API (explained in a later section).


Integrating Valor Payment Gateway with Passage.js

You can integrate Valor Payment Gateway using Passage.js by following these simple steps:

  1. Generate Credentials
    Obtain your APP ID, APP Key, and EPI, which are required for integration.

  2. Retrieve Client Token
    Use the GetClientToken API to generate a secure client token for authentication.

  3. Include Passage.js Script
    Add the Passage.js library to your frontend and pass the received token to the data-clientToken attribute in your checkout form.

  4. Create Checkout Form
    Build a form with the required fields for payment collection. Set the form’s action to the API endpoint that calls Valor’s Sale API.

  5. Handle Sale API Response
    Process the response returned from the Sale API to confirm payment success or handle errors.


Getting ID and Keys

In order to integrate and use Passage.js, the merchants will need to use their APP ID, APP Key and EPI to generate a Client Token.

You can take the following steps to generate or retrieve your keys:

Step 1: Login to the Valor portal

Step 2: Click on "Manage" option in "Virtual Terminal" in side menu

Step 3: Under "API KEYS" you can find your APP ID, APP Key and EPI


Generating Client Token

Merchants can generate a Client Token to handle authentication instead of using APP ID and APP Key. The generated token should be used in the Passage.js script via the data-clientToken attribute.

Example Client Token:

7b9e2a55-720d-4533-bb70-9376a378eae4

API Endpoints for Client Token

EnvironmentURL
Demohttps://securelink-staging.valorpaytech.com:4430
Livehttps://securelink.valorpaytech.com:4430

Sample API Calls

<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://securelink-staging.valorpaytech.com:4430/?appid=WaJeJErcv5xpqZa2UZz6LZod5MSyyfJw&appkey=53PWdki5U0PGSVhRnVoFsfVSbuDutsA8&epi=2203082193&txn_type=sale&token=26F9A99643197174FE11B29A4A76145773C0B93D&amount=5.00&surchargeIndicator=0&surchargeAmount=5.00&phone=5628398878&address1=2%20Jericho%20Plz&city=Jericho&state=NY&shipping_country=US&billing_country=US&zip=50001&saleAPI=', [
  'headers' => [
    'accept' => 'application/json',
  ],
]);

echo $response->getBody();
import requests

url = "https://securelink-staging.valorpaytech.com:4430/?appid=WaJeJErcv5xpqZa2UZz6LZod5MSyyfJw&appkey=53PWdki5U0PGSVhRnVoFsfVSbuDutsA8&epi=2203082193&txn_type=sale&token=26F9A99643197174FE11B29A4A76145773C0B93D&amount=5.00&surchargeIndicator=0&surchargeAmount=5.00&phone=5628398878&address1=2%20Jericho%20Plz&city=Jericho&state=NY&shipping_country=US&billing_country=US&zip=50001&saleAPI="

headers = {"accept": "application/json"}

response = requests.post(url, headers=headers)

print(response.text)
const sdk = require('api')('@valorapi/v1.0#2lhelnbcau0v');

sdk.saleApi({
  appid: 'WaJeJErcv5xpqZa2UZz6LZod5MSyyfJw',
  appkey: '53PWdki5U0PGSVhRnVoFsfVSbuDutsA8',
  epi: '2203082193',
  txn_type: 'sale',
  token: '26F9A99643197174FE11B29A4A76145773C0B93D',
  amount: '5.00',
  surchargeIndicator: '0',
  surchargeAmount: '5.00',
  phone: '5628398878',
  address1: '2%20Jericho%20Plz',
  city: 'Jericho',
  state: 'NY',
  shipping_country: 'US',
  billing_country: 'US',
  zip: '50001',
  saleAPI: ''
})
  .then(({ data }) => console.log(data))
  .catch(err => console.error(err));
CURL *hnd = curl_easy_init();

curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, stdout);
curl_easy_setopt(hnd, CURLOPT_URL, "https://securelink-staging.valorpaytech.com:4430/?appid=WaJeJErcv5xpqZa2UZz6LZod5MSyyfJw&appkey=53PWdki5U0PGSVhRnVoFsfVSbuDutsA8&epi=2203082193&txn_type=sale&token=26F9A99643197174FE11B29A4A76145773C0B93D&amount=5.00&surchargeIndicator=0&surchargeAmount=5.00&phone=5628398878&address1=2%20Jericho%20Plz&city=Jericho&state=NY&shipping_country=US&billing_country=US&zip=50001&saleAPI=");

struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "accept: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);

CURLcode ret = curl_easy_perform(hnd);
using RestSharp;


var options = new RestClientOptions("https://securelink-staging.valorpaytech.com:4430/?appid=WaJeJErcv5xpqZa2UZz6LZod5MSyyfJw&appkey=53PWdki5U0PGSVhRnVoFsfVSbuDutsA8&epi=2203082193&txn_type=sale&token=26F9A99643197174FE11B29A4A76145773C0B93D&amount=5.00&surchargeIndicator=0&surchargeAmount=5.00&phone=5628398878&address1=2%20Jericho%20Plz&city=Jericho&state=NY&shipping_country=US&billing_country=US&zip=50001&saleAPI=");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
var response = await client.PostAsync(request);

Console.WriteLine("{0}", response.Content);

package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://securelink-staging.valorpaytech.com:4430/?appid=WaJeJErcv5xpqZa2UZz6LZod5MSyyfJw&appkey=53PWdki5U0PGSVhRnVoFsfVSbuDutsA8&epi=2203082193&txn_type=sale&token=26F9A99643197174FE11B29A4A76145773C0B93D&amount=5.00&surchargeIndicator=0&surchargeAmount=5.00&phone=5628398878&address1=2%20Jericho%20Plz&city=Jericho&state=NY&shipping_country=US&billing_country=US&zip=50001&saleAPI="

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Add("accept", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(string(body))

}
require 'uri'
require 'net/http'

url = URI("https://securelink-staging.valorpaytech.com:4430/?appid=WaJeJErcv5xpqZa2UZz6LZod5MSyyfJw&appkey=53PWdki5U0PGSVhRnVoFsfVSbuDutsA8&epi=2203082193&txn_type=sale&token=26F9A99643197174FE11B29A4A76145773C0B93D&amount=5.00&surchargeIndicator=0&surchargeAmount=5.00&phone=5628398878&address1=2%20Jericho%20Plz&city=Jericho&state=NY&shipping_country=US&billing_country=US&zip=50001&saleAPI=")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["accept"] = 'application/json'

response = http.request(request)
puts response.read_body

Sample Response

{
  "error_no": "S00",
  "error_code": "00",
  "clientToken": "7b9e2a55-720d-4533-bb70-9376a378eae4",
  "validity": "2023-01-05 12:44:01"
}

Required Fields

FieldTypeLengthMandatoryDescription
appidstring32YesContact Valor PayTech
appkeystring32YesContact Valor PayTech
txn_typestring15YesType of transaction (e.g., sale)
epinumeric10YesMerchant EPI number

Integrating the Script

After retrieving the client token, integrate the Passage.js script in your checkout page where you want to process card details and payments. Pass the token to the script using the data-clientToken attribute.

Passage.js is a comprehensive payment form library supporting both Credit Cards and ACH payments with secure tokenization and seamless integration.


Table of Contents

  1. Overview
  2. Features
  3. Installation
  4. Quick Start
  5. Configuration
  6. Payment Methods
  7. Events & Callbacks
  8. Custom Data
  9. API Reference
  10. Integration Examples
  11. Security
  12. Troubleshooting

Overview

PassageJS v2.0 is a vanilla JavaScript payment library that provides secure, PCI-compliant payment processing for both credit cards and ACH (bank account) payments. Key features include:

  • Automatic card tokenization
  • Real-time validation
  • Comprehensive event system for seamless integration

Key Benefits

  • 🔒 Secure – Card tokenization ensures sensitive data never touches your servers
  • 🎨 Customizable – Flexible UI with inline and lightbox modes
  • 📱 Responsive – Mobile-optimized design for all devices
  • ⚡ Fast – Vanilla JavaScript with no dependencies
  • 🔧 Flexible – Comprehensive event system and custom data support

Features

Payment Processing

  • Credit card tokenization via Valor PayTech API
  • Direct ACH payment submission
  • Real-time form validation and automatic field formatting
  • Session management

UI/UX

  • Inline and lightbox display modes
  • Responsive design
  • Custom styling options
  • Card type detection with icons
  • Loading states and error messages

Integration

  • Comprehensive event system
  • Custom data injection
  • Parent form integration
  • Multiple callback options
  • Easy configuration updates

Installation

Option 1: Direct Script Include

<script src="https://js.valorpaytech.com/V2/js/Passage.min.js"></script>

Option 2: Module Import

import PassageJS from './passage-v2.js';

HTML Setup

Add a container element where the payment form will render:

<div id="valor-fields"></div>

Or, for custom form IDs:

<div id="custom_form_id"></div>

Quick Start

Basic Credit Card Setup

const passage = new PassageJS({
  clientToken: 'your_valor_client_token',
  epi: 'your_valor_epi',
  formAction: '/process-payment',
  
  onSuccess: (result) => {
    console.log('Payment successful:', result);
    window.location.href = '/success';
  },
  
  onError: (error) => {
    console.error('Payment failed:', error);
    alert('Payment failed. Please try again.');
  }
});

Lightbox Mode

const passage = new PassageJS({
  clientToken: 'your_valor_client_token',
  epi: 'your_valor_epi',
  formAction: '/process-payment',
  variant: 'lightbox',
  submitText: 'Pay Now'
});

Configuration

Required Settings

OptionTypeDescription
clientTokenstringYour Valor PayTech client token
epistringYour Valor PayTech EPI identifier
formActionstringURL where payment data will be submitted

Core Settings Example

const config = {
  clientToken: 'your_client_token',
  epi: 'your_epi',
  formAction: '/process-payment',
  
  // Optional
  isDemo: true,
  formMethod: 'POST',
  customData: {},
  
  // UI Settings
  variant: 'inline', // 'inline' | 'lightbox'
  theme: 'default',
  submitText: 'Pay Now',
  submitBg: '#005cb9',
  submitColor: '#fff',
  
  enableACH: true,
  defaultPaymentMethod: 'credit-card',
  
  // Form Fields
  showLogo: false,
  showCardholderName: true,
  showEmail: false,
  showPhone: false,
  showBillingAddress: false,
  showAdditonalInput1: false,
  showAdditonalInput2: false,
  showAdditonalInput3: false,
  showCustomAmount: false,

  // Custom form container ID
  formFieldId: "custom_form_id",
  
  // Session
  sessionExpiryMinutes: 5
};

Default Values

const passage = new PassageJS({
  defaults: {
    cardholderName: 'John Doe',
    email: '[email protected]',
    phone: '(555) 123-4567',
    address1: '123 Main St',
    zip: '10001'
  }
});

Payment Methods

Credit Card Processing

  1. User enters card details → real-time validation
  2. Form submission → card data sent to Valor for tokenization
  3. Token received → sensitive data replaced with secure token
  4. Form submitted → only token and metadata sent to your server

Server receives:

  • card_token
  • payment_method (credit-card)
  • cardholder_name (if enabled)
  • Customer and custom data

ACH (Bank Account) Processing

Server receives:

  • payment_method (ach)
  • routing_number
  • account_number
  • account_type (checking or savings)
  • account_holder_name
  • Customer and custom data

Events & Callbacks

Event System Example

passage.on('tokenReceived', (data) => {
  console.log('Card tokenized:', data.token);
});

passage.on('formSubmitting', (data) => {
  console.log('Submitting to:', data.action);
});

passage.on('validationChanged', (data) => {
  console.log('Form valid:', data.isValid);
});

Available Events

EventDescription
initializedLibrary loaded and ready
lightboxOpenedLightbox modal opened
lightboxClosedLightbox modal closed
paymentMethodChangedUser switched payment method
fieldChangedForm field value changed
fieldBlurredForm field lost focus
validationChangedForm validation state changed
beforeSubmitBefore payment processing starts
tokenReceivedCredit card token received
formSubmittingForm being submitted to server
afterSubmitAfter form submission
successPayment completed successfully
errorPayment processing failed
sessionExpiredPayment session expired

Legacy Callbacks Example

const passage = new PassageJS({
  onSuccess: (result) => console.log('Payment successful:', result),
  onError: (error) => console.error('Payment failed:', error),
  onValidationChange: (isValid, validation) => console.log('Form valid:', isValid),
  onTokenReceived: (token, method) => console.log('Token received:', token),
  onFormSubmit: (formData, action) => console.log('Form submitting to:', action)
});

Custom Data

During Initialization

customData: {
  order_id: 'ORDER-12345',
  amount: '99.99',
  currency: 'USD',
  customer_id: 'CUST-789'
}

Dynamically

passage.setCustomData({ promo_code: 'SUMMER20', discount_amount: '10.00' });

Event-Based

passage.on('beforeSubmit', () => {
  passage.setCustomData({
    timestamp: new Date().toISOString(),
    session_id: getSessionId()
  });
});

Using Parent Form

<form id="checkout-form">
  <input type="hidden" name="order_id" value="ORDER-12345">
  <div id="valor-fields"></div>
</form>

API Reference

Constructor: new PassageJS(config)

Public Methods

  • setCustomData(data) – Add/update custom data
  • getCustomData() – Get current custom data
  • updateConfig(newConfig) – Update configuration dynamically
  • getValidationState() – Get form validation state
  • reset() – Reset form to initial state
  • destroy() – Remove PassageJS instance

Event Methods

  • on(eventName, callback) – Listen to events
  • off(eventName, callback) – Remove event listener
  • once(eventName, callback) – Listen once

E-commerce Checkout

// Complete e-commerce integration
function initializeCheckout(cart) {
  const passage = new PassageJS({
    clientToken: 'your_token',
    epi: 'your_epi',
    formAction: '/process-payment',
    variant: 'lightbox',
    
    customData: {
      order_id: generateOrderId(),
      subtotal: cart.subtotal,
      tax: cart.tax,
      shipping: cart.shipping,
      total: cart.total,
      items_count: cart.items.length
    }
  });
  
  // Update total when payment method changes
  passage.on('paymentMethodChanged', (data) => {
    const fee = data.method === 'ach' ? 0 : 2.99;
    updateOrderTotal(cart.total + fee);
  });
  
  // Track successful payments
  passage.on('success', (result) => {
    analytics.track('payment_completed', {
      order_id: passage.getCustomData().order_id,
      payment_method: result.paymentMethod,
      amount: cart.total
    });
    
    window.location.href = '/order-confirmation';
  });
}


Handling the Response

Once the form is submitted, it triggers the Sale API call to process the payment.
After the transaction is completed, the API will return a response object that can be used to display a confirmation or error message to the customer, for example, by redirecting them to a Thank You page or showing an error popup.

The response will contain information such as the transaction status, response code, and authorization details.

You can find detailed information about the Sale API request and response structure, including all parameters, in the official API documentation.
For a comprehensive list of error codes and their meanings, refer to the Valor API Documentation.


Test Card & AVS Information

FieldValue
Address8320
Zip Code85284