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

@haroldtran/react-native-pax

v1.1.0

Published

React Native native module for PAX devices

Readme

@haroldtran/react-native-pax

npm version License: MIT

React Native library to integrate with PAX payment devices using the POSLink SDK. This library provides a bridge between React Native applications and PAX payment terminals for processing various payment transactions.

Maintained and enhanced by @phattran1201

Features

  • 🔌 Connect over any POSLink transport: TCP, SSL, HTTP, HTTPS, UART, USB, AIDL, BLUETOOTH (via initPOSLinkConn)
  • 🔎 Device discovery helpers for building a connect UI (USB / serial / Bluetooth scanning)
  • 💳 Process credit and debit card payments (Sale)
  • 🔄 Handle voids (Void Sale)
  • 📊 Batch operations and settlement
  • 🔙 Process refunds (Return)
  • 📱 Android (full) + iOS (network & Bluetooth) support

📖 For the complete, step-by-step integration walkthrough — every connection type, device-picker UI, permissions, and error handling — see CONNECTION_GUIDE.md.

Installation

yarn add @haroldtran/react-native-pax

iOS Setup

iOS is supported. As of v1.1.0 the iOS native module is at feature parity with Android for the transaction and connection APIs (TCP/SSL/HTTP/HTTPS/BLUETOOTH). UART/USB/AIDL are Android-only and are rejected on iOS with UNSUPPORTED_CONN_TYPE.

Fixing Symbol Conflicts (Required)

This library bundles libPOSLinkAdmin.a, which exports the same unz*/zip* symbols as SSZipArchive. Without the fix, the linker will throw duplicate symbol errors at build time.

To resolve this, use the provided helper react_native_pax_pods.rb:

1. Require the helper at the top of your Podfile:

require_relative '../node_modules/@haroldtran/react-native-pax/react_native_pax_pods'

2. Call it inside your post_install block:

post_install do |installer|
  react_native_pax_pods(installer) # <== add this
  # ... other post_install steps
end

What this does: it prefixes all conflicting unz*/zip* symbols in SSZipArchive with ssz_ via GCC_PREPROCESSOR_DEFINITIONS, so the linker sees distinct names and the conflict is resolved.

iOS Simulator on Apple Silicon (Required if you build for the Simulator)

The bundled PAX static libraries (libPOSLinkAdmin.a, libPOSLinkSemiIntegration.a) are fat libs containing x86_64 + arm64, but the arm64 slice is built for iOS device only — the vendor does not ship an arm64 simulator slice.

On an Apple Silicon Mac (M1/M2/M3) the Simulator is arm64, so the linker picks the device arm64 slice and fails with:

Building for 'iOS-simulator', but linking in object file
(.../libPOSLinkAdmin.a[arm64][...](...o)) built for 'iOS'
Linker command failed with exit code 1

You have two options:

  • Recommended — build on a real device. The arm64 device slice matches and links fine. (A card terminal SDK has to be tested on a real device anyway.)

  • To run on the Simulator, force it to use the x86_64 slice by excluding arm64 for the simulator SDK. Add to your Podfile post_install:

    post_install do |installer|
      react_native_pax_pods(installer)
      installer.pods_project.build_configurations.each do |config|
        config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
      end
      # ... other post_install steps
    end

    Also set the same EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64 on your app target, and run Xcode/Simulator under Rosetta.

The proper long-term fix is for PAX to ship an .xcframework (which can hold a separate arm64 simulator slice). Until then, the workaround above is required for Simulator builds.

General iOS Setup

  1. Navigate to your iOS project directory and install pods:
cd ios && pod install
  1. Make sure your iOS deployment target is 11.0 or higher in your Podfile:
platform :ios, '11.0'
  1. Bluetooth Permissions (Required if using BLUETOOTH connection type): Add the following key to your ios/YourAppName/Info.plist file (iOS will crash on initialization if this is missing and Bluetooth connection is attempted):
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>This app requires Bluetooth access to connect to PAX payment terminals.</string>

Android Setup

The Android setup is automatic. The library will be linked automatically when you rebuild your project.

Usage

Import the library

import {
  initPOSLink,
  initPOSLinkConn,
  makePayment,
  makeRefund,
  makeVoid,
  makeCloseBatch,
} from '@haroldtran/react-native-pax';

Initialize Connection

The general way (recommended) — initPOSLinkConn(config)

initPOSLinkConn connects over any transport the SDK supports. Pass a config object whose type selects the transport; only the fields relevant to that type are used.

// Network (most common) — TCP / SSL / HTTP / HTTPS
await initPOSLinkConn({ type: 'TCP', ip: '192.168.1.100', port: '10009' });
await initPOSLinkConn({ type: 'SSL', ip: '192.168.1.100', port: '10009' });

// Serial (Android)
await initPOSLinkConn({ type: 'UART', serialPort: 'COM1', baudRate: '9600' });

// USB (Android) — auto-requests USB permission on connect
await initPOSLinkConn({ type: 'USB' });                 // optional: { deviceName }

// AIDL (Android) — app running on the PAX device itself (BroadPOS)
await initPOSLinkConn({ type: 'AIDL' });

// Bluetooth / BLE
await initPOSLinkConn({ type: 'BLUETOOTH', macAddr: 'AA:BB:CC:DD:EE:FF' });

| type | Required fields | Optional fields | Platform | | -------------------- | ------------------------ | ----------------------- | ------------- | | TCP/SSL/HTTP/HTTPS | ip, port | timeout | Android + iOS | | UART | serialPort, baudRate | timeout | Android | | USB | — | deviceName, timeout | Android | | AIDL | — | — | Android | | BLUETOOTH | macAddr | timeout | Android + iOS |

  • port defaults to 10009, timeout defaults to 60000 ms.
  • On iOS, UART/USB/AIDL are rejected with UNSUPPORTED_CONN_TYPE.
  • Returns a PaxInitModel: { status: boolean, serialNumber?: { modelName, appName, serialNumber } }. Only proceed to transactions when status === true.

To build a UI that lets the user pick/scan a device (USB list, serial ports, Bluetooth scan) and to handle runtime permissions, see CONNECTION_GUIDE.md — it includes a full ConnectScreen example and the helper APIs (listUsbDevices, getSupportedBaudRates, listSerialPorts, checkBluetoothEnable, startBluetoothSearch, getBluetoothDeviceList, stopBluetoothSearch, requestUsbPermission).

The legacy way (TCP only) — initPOSLink(ip)

Kept for backward compatibility; equivalent to initPOSLinkConn({ type: 'TCP', ip, port }).

try {
  const result = await initPOSLink('192.168.1.100'); // IP of the POS device
  // or: await initPOSLink('192.168.1.100', { port: '10009', timeout: 60000 });
  console.log('PAX device initialized:', result);
} catch (error) {
  console.error('Failed to initialize PAX device:', error);
}

Process a Payment

makePayment(id?, amount, tip?, paymentType?, ecrRefNum?, showTip?)positional arguments. Pass undefined for any optional argument you want to skip. All money values are in cents (1000 = $10.00).

import { makePayment, CreditTransactionType } from '@haroldtran/react-native-pax';

try {
  const paymentResult = await makePayment(
    'txn-123', // 1. id?         — your transaction id (optional; pass undefined to skip)
    1000, // 2. amount      — REQUIRED, in cents. 1000 = $10.00
    150, // 3. tip?        — tip in cents (optional). 150 = $1.50; use 0/undefined for none
    CreditTransactionType.Credit, // 4. paymentType? — 1 = Credit (default), 2 = Debit
    'ECR123', // 5. ecrRefNum?  — YOUR reference. STRONGLY recommended: you need it later to void/refund
    true // 6. showTip?    — true = let the customer enter a tip on the terminal
  );

  console.log('Payment result:', paymentResult);
  // paymentResult (PaxResponseModel) contains:
  // - status: boolean            — overall success
  // - isPaymentSuccess: boolean  — payment-specific success
  // - cardHolder / cardNumber (masked) / cardType / entryMethod
  // - refNum / transactionId / transactionNo / transactionDateTime
  // - amount / tipAmount / surcharge
  // - message, data (raw detail), sn ...
} catch (error) {
  console.error('Payment failed:', error);
}

Minimal call (just charge $10.00, no tip UI):

await makePayment(undefined, 1000, undefined, CreditTransactionType.Credit, 'ECR123', false);

⚠️ Always pass a unique ecrRefNum — it is the key you use to makeVoid/makeRefund/checkVoidOrRefundTransaction that same transaction later.

Process a Refund

makeRefund(amount, ecrRefNum) — both required.

try {
  const refundResult = await makeRefund(
    1500, // amount to refund, in cents. 1500 = $15.00
    'ECR123' // ecrRefNum of the ORIGINAL transaction being refunded
  );
  console.log('Refund result:', refundResult); // PaxResponseModel
} catch (error) {
  console.error('Refund failed:', error);
}

Void a Transaction

makeVoid(ecrRefNum) — voids the transaction by its ECR reference (no amount needed).

try {
  const voidResult = await makeVoid('ECR123'); // ecrRefNum of the transaction to void
  console.log('Void result:', voidResult); // PaxResponseModel
} catch (error) {
  console.error('Void failed:', error);
}

Close Batch

makeCloseBatch() — takes no arguments; settles the current batch.

try {
  const batchResult = await makeCloseBatch();
  console.log('Batch close result:', batchResult); // PaxResponseModel
} catch (error) {
  console.error('Batch close failed:', error);
}

Other operations

import {
  cancelTransaction,
  checkVoidOrRefundTransaction,
  getBatchInformation,
} from '@haroldtran/react-native-pax';

// Cancel the command currently running on the terminal (no args)
await cancelTransaction();

// Check whether a given ECR ref can be voided/refunded (pass the ecrRefNum)
const info = await checkVoidOrRefundTransaction('ECR123');

// Read the current batch totals (no args) → PaxBatchInformationResponseModel
const batch = await getBatchInformation();

Error Handling & Response Classification

The library returns raw response codes from the native SDK (via PaxResponseModel). Because error classification rules ("which code indicates a communication timeout vs. a user cancellation") are business-logic specific, the library provides a set of JavaScript helpers in src/pax-error.ts to normalize and classify transaction outcomes.

You can import toPaxResult, fromThrown, and PaxErrorType to process transaction responses:

import { toPaxResult, fromThrown, PaxErrorType } from '@haroldtran/react-native-pax';

try {
  const rawResponse = await makePayment(undefined, 1000, undefined, 1, 'ECR123', false);
  const result = toPaxResult(rawResponse);

  if (result.ok) {
    console.log('Transaction approved:', result.data); // result.data is PaxResponseModel
  } else {
    const error = result.error;
    console.error(`Transaction failed: ${error.message} (Code: ${error.code})`);
    
    // Switch on classified error type
    switch (error.type) {
      case PaxErrorType.Communication:
        console.log('Communication error. Suggest retrying:', error.retryable); // true
        break;
      case PaxErrorType.UserCanceled:
        console.log('User aborted transaction on the terminal.');
        break;
      case PaxErrorType.HostDeclined:
        console.log('Card issuer/bank declined transaction (e.g. insufficient funds).');
        break;
      case PaxErrorType.TerminalDeclined:
        console.log('Terminal declined transaction.');
        break;
      case PaxErrorType.Duplicate:
        console.log('Duplicate transaction detected.');
        break;
      default:
        console.log('Unknown error.');
    }
  }
} catch (error) {
  // Handles native module promise rejection (e.g. no terminal connected)
  const result = fromThrown(error);
  console.error('Fatal native error:', result.error.message);
}

Classified Error Model (PaxError)

When toPaxResult returns { ok: false, error }, the error object matches the following interface:

  • type (PaxErrorType): The classified error category (None, Communication, UserCanceled, TerminalDeclined, HostDeclined, Duplicate, Unknown).
  • code (string): The primary response or host code (e.g., '94', 'ERROR').
  • message (string): Friendly description text for logging or showing to users.
  • retryable (boolean): Indication of whether the transaction is safe to retry immediately (e.g., true for connection timeout, false for declined card).
  • raw (PaxRawCodes): The complete, unclassified raw codes returned by POSLink SDK (useful for debugging).

Full flow example (connect → pay → void)

import {
  initPOSLinkConn,
  makePayment,
  makeVoid,
  CreditTransactionType,
} from '@haroldtran/react-native-pax';

async function run() {
  // 1. Connect (TCP here; swap `type` for USB/Bluetooth/etc.)
  const conn = await initPOSLinkConn({
    type: 'TCP',
    ip: '192.168.1.100',
    port: '10009',
    timeout: 60000,
  });
  if (!conn.status) throw new Error('Not connected');

  // 2. Charge $10.00 as Credit, allow tip on terminal, keep our ref
  const ecrRefNum = `ECR-${Date.now()}`;
  const pay = await makePayment(
    undefined, // id
    1000, // amount (cents)
    undefined, // tip
    CreditTransactionType.Credit,
    ecrRefNum,
    true // showTip
  );
  if (!pay.isPaymentSuccess) throw new Error(pay.message);

  // 3. Later, void that same transaction using its ecrRefNum
  await makeVoid(ecrRefNum);
}

API Reference

initPOSLinkConn(config)

Initializes the connection to the PAX device over any supported transport.

Parameters:

  • config (PaxConnConfig): { type, ip?, port?, serialPort?, baudRate?, deviceName?, macAddr?, timeout? } — see the connection-types table above.

Returns: Promise<PaxInitModel>{ status, serialNumber? }

initPOSLink(ip, options?)

Legacy TCP-only initializer (equivalent to initPOSLinkConn({ type: 'TCP', ... })).

Parameters:

  • ip (string): Device IP address
  • options (object, optional): { port?: string; timeout?: number }

Returns: Promise<PaxInitModel>

makePayment(id?, amount, tip?, paymentType?, ecrRefNum?, showTip?)

Initiates a payment transaction.

Parameters:

  • id (string, optional): Transaction ID
  • amount (number): Payment amount in cents (e.g., 1000 = $10.00)
  • tip (number, optional): Tip amount in cents (e.g., 150 = $1.50)
  • paymentType (number, optional): Type of payment (1 = Credit, 2 = Debit, see CreditTransactionType enum)
  • ecrRefNum (string, optional): ECR reference number (recommended — required to void/refund later)
  • showTip (boolean, optional): true to let the customer enter a tip on the terminal

Returns: Promise<PaxResponseModel>

makeRefund(amount, ecrRefNum)

Initiates a refund transaction.

Parameters:

  • amount (number): The amount to refund in cents
  • ecrRefNum (string): ECR reference number of the original transaction

Returns: Promise<PaxResponseModel>

makeVoid(ecrRefNum)

Voids the transaction with the given ECR reference number.

Parameters:

  • ecrRefNum (string): ECR reference number of the transaction to void

Returns: Promise<PaxResponseModel>

makeCloseBatch()

Closes the current batch of transactions.

Returns: Promise<PaxResponseModel>

Device Discovery Helpers

These functions help you scan and list available connection targets (such as USB devices, serial ports, or Bluetooth/BLE terminals) to populate dropdowns or list pickers in your connection UI.

listUsbDevices()

Returns a list of connected USB devices (Android only; returns an empty list [] on iOS).

  • Returns: Promise<PaxUsbDevice[]>{ deviceName, productName, vendorId, productId }[]

requestUsbPermission()

Asks the user for USB permission for a device (Android only; returns false on iOS). Unlike legacy methods, this method awaits the user's action and resolves only after permission is granted or denied.

  • Returns: Promise<boolean>true if permission is granted, false if denied or no device is connected.

listSerialPorts()

Scans and returns the available serial/COM ports (Android only; returns an empty list [] on iOS).

  • Returns: Promise<string[]> — e.g., ["/dev/ttyS0", "/dev/ttyUSB0"]

getSupportedBaudRates()

Returns the list of valid baud rates for serial communication (Android only; returns [] on iOS).

  • Returns: Promise<string[]> — e.g., ["9600", "19200", "115200"]

checkBluetoothEnable()

Checks if Bluetooth is currently enabled on the device. On iOS, this initializes the core Bluetooth central manager. Make sure you have declared the NSBluetoothAlwaysUsageDescription plist key, otherwise the app will crash.

  • Returns: Promise<boolean>true if Bluetooth is enabled, false otherwise.

startBluetoothSearch(options?)

Starts scanning for Bluetooth devices. MAC-deduped results are cached internally.

  • Parameters:
    • options (object, optional):
      • useBle (boolean, optional): true to scan for BLE, false for classic Bluetooth (default is false).
      • timeout (number, optional): Scan duration in milliseconds (default is 1000).
  • Returns: Promise<boolean>

getBluetoothDeviceList()

Polls and retrieves the list of Bluetooth devices found since startBluetoothSearch was called.

  • Returns: Promise<PaxBtDevice[]>{ name, mac, rssi }[]

stopBluetoothSearch()

Stops the Bluetooth scan and clears the internal cached device list.

  • Returns: Promise<boolean>

Response Objects

PaxResponseModel

The response object returned by all transaction functions. Key fields include:

Status & Result:

  • status (boolean): Overall operation success status
  • isPaymentSuccess (boolean): Payment-specific success flag
  • message (string): Response message or error description

Transaction Details:

  • id (string): Transaction ID
  • transactionId (string): Global unique transaction identifier
  • transactionNo (string): Transaction sequence number
  • refNum (string): Reference number
  • transactionDateTime (string): Date/time of transaction

Card & Payment Info:

  • cardType (string): Card type/brand (e.g., VISA, MASTERCARD)
  • cardNumber (string): Masked card number
  • cardHolder (string): Card holder name
  • entryMethod (string): How card was entered (SWIPED_MSD, CONTACT_CHIP, CONTACTLESS_CHIP, etc.)

Amount Details:

  • amount (string): Transaction amount
  • tipAmount (string): Tip amount
  • surcharge (string): Additional fees/surcharge

Additional Data:

  • data (object): Detailed response data including account info, trace info, AVS info, etc.
  • sn (string): Serial number

CreditTransactionType Enum

Available payment types:

  • CreditTransactionType.Credit (1): Credit card transaction
  • CreditTransactionType.Debit (2): Debit card transaction
  • CreditTransactionType.Empty (0): Not set/default

See src/type.ts for the complete interface definition.

Requirements

  • React Native 0.63+
  • Android API level 21+ (Full support)
  • iOS 11.0+ (Limited support - implementation pending)
  • PAX payment terminal with POSLink SDK support
  • TCP/IP network connection to PAX terminal

Current Platform Support

| Feature | Android | iOS | | --------------------- | ------- | --- | | Initialize Connection | ✅ | ✅ | | Payment Processing | ✅ | ✅ | | Refunds | ✅ | ✅ | | Voids | ✅ | ✅ | | Batch Operations | ✅ | ✅ |

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

Support

For PAX device documentation and support, visit PAX Developer Portal.