npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vantagepay/vantagepay

v0.17.4

Published

VantagePay API wrapper and SDK for integrating into VantagePay payment, consumer and merchant services.

Downloads

53

Readme

VantagePay API and Client SDK

The VantagePay client SDK is intended to be used by web or mobile applications to integrate into the VantagePay payments, consumer and merchant API's.

The library includes automatic retries for network failures and automatic token refresh on expiry. You can optionally subscribe to events published by the library to react appropriately from the client as well.


Installation

Install the latest package into your project from NPM.

npm install @vantagepay/vantagepay --save

Basic Usage

The library can be imported just like any other NPM package.

import { VantagePay, ApiTokens, ApiError } from '@vantagepay/vantagepay'

Once imported you can create an instance with options specific to your environment.

const VantagePayClient = new VantagePay({ baseUrl: 'https://sandbox-api.vantagepay.dev/' })

When you are done using the client or when the application exits, you can close the client to flush logs, unsubscribe to events and cancel active web requests.

await VantagePayClient.close()

The following options are available when creating an instance.

{
  // The partner URL you are integrating with, this will point to the local development server by default.
  baseUrl: 'https://sandbox-api.vantagepay.dev/',

  // Optional extra headers (string key/value pairs) that you may want to send to the server with each call.
  headers: {
    'X-EXAMPLE-HEADER': 'Test'
  },

  // Optional language if you need to have response messages translated.
  language: 'en',

  // The number of automatic retries required for network failures, the default is 3.
  retries: 3,

  // For additional request/response and signal logging which can be useful when debugging.
  consoleLogging: false,

  // The batch size limit when logs should immediately be sent to the server, the default is 100, use 0 to disable.
  logBatchSize: 100,

  // The interval in milliseconds to send any queued logs the server, the default is 60000, use 0 to disable.
  logBatchInterval: 60000,
}

To flush any logs to the server you can call the log.flush() method manually or close() on the client instance when closing your application.

// Do this when the application close to push final logs to the server.
VantagePayClient.log.flush()

// You can also just close the client when you are done using it.
await VantagePayClient.close()

The instance will contain all the methods available for making API calls. All methods return a Promise so you can either use modern async/await syntax or promise-based chaining. The rest of the examples that follow use the async/await syntax.

Error Handling

The API will respond with typical REST HTTP error status codes (4xx and 5xx) for errors that will trigger an exception. You can use the following generic error handling code for the typical exceptions that you may experience.

try {
  // ... Call a method on the client library.
} catch (error) {
  // First check if it's an API error.
  if (error instanceof ApiError) {
    // You can always display the `message` property to handle things generically.
    console.error('\n%s\n', error.message)

    // Or you can decide to handle things in a custom way depending on the status code.
    if (error.statusCode === 400 || error.statusCode === 422) {  // 400/422 - Validation Errors
      if (Array.isArray(error.result)) {
        // Multiple errors.
        error.result.forEach(validationError => console.error(validationError))
      }
      else {
        // Single error message.
        console.error(error.message || error.result)
      }
    }
    else if (error.statusCode === 401 || error.statusCode === 403) {  // 401/403 - Auth Errors
      // Login calls will contain extra information on failure (401).
      // No access will not have any specific details on why (403).
    }
    else if (error.statusCode === 429) {  // 429 - Too Many Requests
      // Contains the limit.
      console.error(error.message)
      // This will also contain a standard 'Retry-After' header if you need to know how long to wait.
    }
    else if (error.statusCode === 500) {  // 500 - Server Error
      // General error message.
      console.error(error.message)
    }
    else {
      console.error('Unknown status code from VantagePay client library: ' + error.statusCode)
      throw error
    }
  } else {
    // Not a client library error...
    throw error
  }
}

Authentication

Login

Use credentials to login and retrieve access and refresh tokens.

try {
 
  const testLogin = await VantagePayClient.auth.login('test', 'test@#$123abCD')

  // Store tokens in secure storage if you want to use biometrics etc.
  my_secure_storage.set('accessToken', testLogin.accessToken)
  my_secure_storage.set('refreshToken', testLogin.refreshToken)

  // An alternative is to just use the static ApiTokens object where the tokens are stored after a login/refresh.
  my_secure_storage.set('accessToken', ApiTokens.accessToken)
  my_secure_storage.set('refreshToken', ApiTokens.refreshToken)

} catch (error) {
    if (error.statusCode === 401) {
    // Authentication error
    // {
    //   invalidUsernameOrPassword: true,
    //   mustChangePassword: false,
    //   mustValidatePhoneNumber: false,
    //   mustValidateEmailAddress: false,
    //   registrationRequired: false,
    //   lockedOut: false
    // }

    const authError = error.result

    if (authError.mustChangePassword) {
      console.log('Navigate to a change password page, the token is internally set to allow calls to auth.changePassword()')

      // A successful change will automatically log you in.
      await VantagePayClient.auth.changePassword('NewComplexP@55word!')
    }

    if (authError.mustValidatePhoneNumber || authError.mustValidateEmailAddress) {
      console.log('Navigate to the OTP page password page, the token is internally set to allow calls to auth.resendOtp() and auth.validateOtp()')

      // A successful OTP verification will automatically log you in.
      await VantagePayClient.auth.validateOtp('1234')
    }

    if (authError.deactivated) {
      console.log('User account has been deactivated')
    }

    if (authError.lockedOut) {
      console.log('User is currently locked out')
    }

    if (authError.invalidUsernameOrPassword) {
      console.log('User credentials supplied are invalid')
    }
  }

  if (error.statusCode === 429) {
    // Rate limited
    // Maximum number of requests exceeded. The maximum number of requests allowed is 3 per 30s. Please try again in 13 second(s).
    console.log(error.message)
  }
}

Using Existing Tokens

Tokens are kept in memory for the lifetime of the client instance and are used automatically to make authenticated calls and refresh when necessary. To avoid having to login each time your application starts, you can store access and refresh tokens (securely using biometrics for example) and re-use them when starting the application to "auto-login". You simply assign any tokens you have to the static instance of ApiTokens.

ApiTokens.accessToken = my_secure_storage.get('accessToken') || null
ApiTokens.refreshToken = my_secure_storage.get('refreshToken') || null

It is usually not necessary to set the accessToken, if there is no access token then an automatic refresh will be triggered to retrieve one. You can also use this to clear out tokens manually which is also used internally when logout is called.

Logout

Logout of the system which revokes the refresh token as well. Use this when you need to forcibly log a user out due to multiple device unlock failures for example.

await VantagePayClient.auth.logout()

Refresh

This is used internally to automatically refresh if the access token is no longer valid. If you need to refresh manually for any reason to start a new access session then you can call this as well to avoid expiry. This will use the current refresh token that has been set (ApiKeys.refreshToken).

await VantagePayClient.auth.refresh()

Lookups

There are a number of lookup values that can be retrieved from the server. This is preferred over static client data because it allows for dynamic configuration and disabling of things from the server without redeploying the client.

Currencies

Get a list of configured currencies for the partner. The isAvailable flag can be used to disable items from selection, the text will also indicate if it is currently available. Other properties can be useful for displaying currency values.

var currencies = await VantagePayClient.lookups.getCurrencies()

Example Output

[
  {
    isAvailable: true,
    currency: 'GHS',
    currencyName: 'Ghana Cedi',
    currencyCode: 'GHS',
    symbol: '¢',
    numericIsoCode: 936
  },
  {
    isAvailable: true,
    currency: 'NGN',
    currencyName: 'Nigeria Naira',
    currencyCode: 'NGN',
    symbol: '₦',
    numericIsoCode: 566
  },
  {
    isAvailable: true,
    currency: 'ZAR',
    currencyName: 'South Africa Rand',
    currencyCode: 'ZAR',
    symbol: 'R',
    numericIsoCode: 710
  }
]

Countries

Get a list of configured countries for the partner. The isAvailable flag can be used to disable items from selection, the text will also indicate if it is currently available. Other values are useful for adding drop-downs to mobile numbers for example.

var countries = await VantagePayClient.lookups.getCountries()

Example Output

[
  {
    isAvailable: true,
    country: 'GHA',
    countryName: 'Ghana',
    longIsoCode: 'GHA',
    shortIsoCode: 'GH',
    numericIsoCode: 288,
    diallingCode: '233'
  },
  {
    isAvailable: true,
    country: 'NGA',
    countryName: 'Nigeria',
    longIsoCode: 'NGA',
    shortIsoCode: 'NG',
    numericIsoCode: 566,
    diallingCode: '234'
  },
  {
    isAvailable: false,
    country: 'ZAF',
    countryName: 'South Africa (Currently Unavailable)',
    longIsoCode: 'ZAF',
    shortIsoCode: 'ZA',
    numericIsoCode: 710,
    diallingCode: '27'
  }
]

Languages

Get a list of configured languages for the partner. The isAvailable flag can be used to disable items from selection, the text will also indicate if it is currently available. This can be useful for apps that are translated to change the language header.

var languages = await VantagePayClient.lookups.getLanguages()

Example Output

[ { isAvailable: true, languageCode: 'ENG', languageName: 'English' } ]

Mobile Wallet Operators

Get a list of configured mobile wallet operators for the partner. The isAvailable flag can be used to disable items from selection, the text will also indicate if it is currently available. This can be used when setting up mobile wallets for example by limiting the types to only what the partner supports. The operatorCode is what can be passed into payment request packets for mobile wallet sources or destinations.

var mobileWalletOperators = await VantagePayClient.lookups.getMobileWalletOperators()

Example Output

[
  {
    isAvailable: false,
    operatorCode: 'ATG',
    operatorName: 'AirtelTigo (Currently Unavailable)'
  },
  { isAvailable: true, operatorCode: 'MTN', operatorName: 'MTN' },
  { isAvailable: true, operatorCode: 'VDF', operatorName: 'Vodafone' }
]

Banks

Get a list of configured banks for the partner. The isAvailable flag can be used to disable items from selection, the text will also indicate if it is currently available. This can be used when setting up bank accounts for example by limiting the types to only what the partner supports. The bankCode is what can be passed into payment request packets for bank account sources or destinations.

var banks = await VantagePayClient.lookups.getBanks()

You can also optionally filter the banks returned for a specific country.

// Only return banks in Ghana.
var banks = await VantagePayClient.lookups.getBanks('GHA')

Example Output

[
  {
    isAvailable: true,
    bank: 'ABG',
    bankCode: 'ABG',
    bankName: 'ABSA Bank Ghana',
    country: 'GHA'
  },
  {
    isAvailable: true,
    bank: 'ABL',
    bankCode: 'ABL',
    bankName: 'Access Bank Ghana',
    country: 'GHA'
  },
  {
    isAvailable: false,
    bank: 'FNB',
    bankCode: 'FNB',
    bankName: 'First National Bank Ghana (Currently Unavailable)',
    country: 'GHA'
  }
]

Card Issuer Country

It is sometimes necessary to determine which country a card was issued in, you can use the card issuer country lookup with a card number to lookup the country.

var country = await VantagePayClient.lookups.getCardIssuerCountry('5200000000000114')

Partial numbers are also supported, 6 digits is usually sufficient, 8 digits is better.

var country = await VantagePayClient.lookups.getCardIssuerCountry('520001')

Example Output

{
  isAvailable: true,
  country: 'MYS',
  countryName: 'Malaysia',
  longIsoCode: 'MYS',
  shortIsoCode: 'MY',
  numericIsoCode: 458,
  diallingCode: '60'
}

Subscribing to Events

The library uses pubsub-js to publish messages for subscribers. To subscribe to events you can use the events property on the client instance, which is a wrapper around PubSub so all the functions for the base library are available.

These events can be useful if your application needs to react to certain things happening behind the scenes. It is especially useful when used to automatically receive payment status updates during payment processing.

import { VantagePay, OnApiRetry, OnAutomaticRefresh, OnSessionStarted, OnSessionExpired } from '@vantagepay/vantagepay'
...
const onApiRetrySub = VantagePayClient.events.subscribe(OnApiRetry, (_, retryInfo) => console.log('API performed an automatic retry', retryInfo))
const onAutoRefreshSub = VantagePayClient.events.subscribe(OnAutomaticRefresh, (_, tokenResponse) => console.log('Automatic refresh was triggered', tokenResponse))
const onSessionStartedSub = VantagePayClient.events.subscribe(OnSessionStarted, () => console.log('Session started'))
const onSessionExpiredSub = VantagePayClient.events.subscribe(OnSessionExpired, () => console.log('Session expired'))
...
// Unsubscribe if you no longer want to receive events.
VantagePayClient.events.unsubscribe(onApiRetrySub)
VantagePayClient.events.unsubscribe(onAutoRefreshSub)
VantagePayClient.events.unsubscribe(onSessionStartedSub)
VantagePayClient.events.unsubscribe(onSessionExpiredSub)

OnSessionExpired ('login.session.expired')

This will be fired when an automatic refresh fails or a refresh token is no longer available when making a call and you are now logged out. No data will be included with this event.

OnAutomaticRefresh ('login.session.refreshed')

This will be fired when an automatic token refresh occurs. This is useful to know when new tokens are available that you may want to save in secure storage. The token response is included with the event, you can also use ApiTokens.accessToken and ApiTokens.refreshToken to read the new values.

OnApiRetry ('api.retry')

This will be fired whenever there is an automatic API request retry. This is useful to indicate to application users that the network may be slow or they lack connectivity. The data included in the event indicates how many times the call has been retried.

{ retryCount: 2 }

OnPaymentStatusUpdate ('payment.status')

During payment processing (call to payments.pay()) this will be fired for any status change to the payment. This is mainly due to transaction status changes that the client can display or react to. Certain status changes will also change the transaction amounts (adjustments, fees, failures and others). The recommendation here is to create a single view that renders the transaction status and on each event render the new state.

Transaction status data will be based on the request made. The source and destination data will be based on the source ans destinations provided in the request. All the possibilities will be documented separately.

OnPaymentComplete ('payment.complete')

This will be fired when the payment processing is complete. In the most basic payment processing client you can ignore OnPaymentStatusUpdate if you do not want to show progress and simply go to the completion screen when this fires. The event will include full payment status data the same as OnPaymentStatusUpdate so the transaction statuses and final amounts can be displayed. Success or failure will be based on the various transaction statues in the final results.

OnRequires3DSecure ('payment.wait.requires3dSecure')

If card payment requires 3D Secure the client will need to launch a browser ot open an iFrame with the supplied URL and wait for OnComplete3DSecure to be fired before closing the browser or iFrame. The data will include the URL to launch.

{ url: 'https://some_url_that_will_start-3ds' }

Pseudo Code

async function handleRequires3DS(signalData) {
  // You are given a URL that you simply need to launch or set at the `src` on an iFrame.
  webBrowser = await open(signalData.url)
}

OnComplete3DSecure ('payment.complete3dSecure')

This will fire once 3DS has completed as an indication that you can close the browser or iFrame that was launched when OnRequires3DSecure was fired. There is no additional data included in this event.

OnRequiresPin ('payment.wait.requiresPin')

This will be fired if a transaction requires a PIN/OTP. The event data will include the message to display to the user so they are aware of what to provide. The text field can generally be numbers only.

{ 
  message: 'Please enter you Vodafone PIN to complete this transaction.',
  transactionReference: '84125510-B042-417D-A532-47A7EBD47488',
  pinLength: 6
}

Once the PIN has been captured you can make a call to payments.submitPinCode() with the transactionReference that was sent in the event to continue payment processing.

Pseudo Code

function handleRequiresPin(signalData) {
  // You need to capture a PIN code and call `submitPinCode`.
  const pin = prompt(signalData.message)
  VantagePayClient.payments.submitPinCode(signalData.transactionReference, pin)
}

OnRequiresConfirmation ('payment.wait.requiresConfirmation')

This will be fired if a transaction requires confirmation such as additional fees or even to verify account information. The event data will include the message to display to the user so they are aware of what they are confirming. The dialog to display can just have Yes/No buttons.

{ 
  message: 'The transaction requires an additional e-levy fee of GHS 3.00. Do you want to continue?',
  transactionReference: '6FD502DE-20FF-4110-ABBE-8FE6D7733AAE',
  confirmationData: {
    amountInCents: 1025,
    sourceAccountHolder: 'Steve Rogers',
    destinationAccountHolder: 'Tony Stark',
    fees: []
  }
}

Once the response has been captured you can make a call to payments.submitConfirmation() with the transactionReference that was sent in the event to continue payment processing.

Pseudo Code

function handleRequiresConfirmation(signalData) {
  // You need to ask the user for a Yes/No answer.
  const confirmation = prompt(signalData.message + ' -Y/N - ')
  VantagePayClient.payments.submitConfirmation(signalData.transactionReference, confirmation === 'Y' || confirmation === 'y')
}

OnRequiresAddress ('payment.wait.requiresAddress')

This will be fired if address validation failed or an address is required but was not provided in the initial payment request. The event data will include the message to display to the user. The client should launch an address capture screen with the information provided (so it can corrected) a blank if no address information was provided.

{ 
  message: 'The address information provided does not appear to be valid. Please provide billing address information for this transaction.',
  transactionReference: '6F4F250E-BF64-4BC2-936C-02E5A2982969'
}

Once the address details have been captured you can make a call to payments.submitAddress() with the transactionReference that was sent in the event to continue payment processing.

Pseudo Code

function handleRequiresAddress(signalData) {
  // Let the user know what is required.
  alert(signalData.message)

  // You need to capture a PIN code and call `submitPinCode`.
  const address = {
    addressType:    prompt('Type: ')        || 'BILL',
    addressLine1:   prompt('Line 1: ')      || '10 Whitley Road',
    addressLine2:   prompt('Line 2: ')      || null,
    addressLine3:   prompt('Line 3: ')      || null,
    countryIsoCode: prompt('Country: ')     || 'ZAF',
    city:           prompt('City: ')        || 'Johannesburg',
    state:          prompt('State: ')       || null,
    postalCode:     prompt('Postal Code: ') || '2196',
  }

  VantagePayClient.payments.submitAddress(signalData.transactionReference, address)
}