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

@paycode/connect

v0.1.4

Published

PayCode Connect SDK for TypeScript

Downloads

43

Readme

PayCode Connect TypeScript SDK

📦 For a full working integration, check out the example app.

Setup

Initialize the SDK by calling setup(), which returns a promise that resolves to the PayCodeConnect singleton instance. This should be called once during your app's initialization.

import { setup } from "@paycode/connect";

// Using async/await
const pc = await setup();

// Or with a promise chain
setup().then((pc) => { /* ... */ });

React hook example

import { type PayCodeConnect, setup } from "@paycode/connect";
import { useEffect, useState } from "react";

export function usePayCode() {
  const [pc, setPc] = useState<PayCodeConnect | null>(null);

  useEffect(() => {
    setup().then(setPc);
  }, []);

  return pc;
}

Connecting

To pair with a PoS terminal, generate a connection ticket and display it as a QR code. In this example we use the qrcode package to render it:

const ticket = pc.generateTicket();

// Render the ticket as a QR code
import QRCode from "qrcode";
QRCode.toCanvas(document.getElementById("qcanvas"), ticket, {});

Once the QR code is scanned by a PayCode PoS terminal, the connection is established.

Reconnecting

After a successful first connection, the SDK persists the pairing ticket in local storage. If the user later revisits your site (or refreshes the page) and the PoS terminal is still active, you can restore the connection instantly, no QR code required:

await pc.reconnectToLastNode();

This will throw an error if no previous connection exists, so you should handle that case:

try {
  await pc.reconnectToLastNode();
} catch {
  // No previous session, fall back to QR code pairing
  const ticket = pc.generateTicket();
  QRCode.toCanvas(document.getElementById("qcanvas"), ticket, {});
}

You can set reconnect to retry the connection automatically by passing retryTimes parameter:

await pc.reconnectToLastNode(3); // This will retry 3 times

Receiving events

PayCodeConnect exposes a typed event emitter, allowing you to subscribe to events like connected, presence, scanner, and emvState using callback handlers.

Connected event

Fires when the connection state with a PoS terminal changes. Returns true when connected and false when the connection is lost.

pc.on("connected", (connected: boolean) => { /* ... */ });

EMV State

Fires throughout the EMV transaction lifecycle after calling startEMV(). The callback receives an EMVData object whose fields are populated depending on the current state:

| State | Fields | Description | |---|---|---| | awaitingCard | state, metadata? | Terminal is waiting for a card to be presented | | processing | state, metadata? | Transaction is being processed | | error | state, message, code, metadata? | Transaction failed | | success | state, transaction, metadata? | Transaction completed successfully | | reversal | state, message, code, metadata? | Reversal result — code is 0 for success, 1 for error |

Note: If metadata was passed to startEMV(), it will be present on every state event for that transaction.

pc.on("emvState", (data: EMVData) => {
  // handle state change
});

Example payloads per state:

// awaitingCard, processing
{ state: "awaitingCard" }

// error
{ state: "error", message: "Transaction failed", code: -8019 }

// success
{ state: "success", transaction: { authorization: "...", reference: "...", folio: "...", /* ... */ } }

// reversal
{ state: "reversal", message: "success", code: 0 }

Presence event

Fires with false when messages are no longer reaching the connected PoS terminal, even if the connection hasn't been fully lost yet. Fires with true once the terminal becomes responsive again.

pc.on("presence", (hasPresence: boolean) => { /* ... */ });

Scanner event

You can use a connected PoS terminal as a barcode scanner. To enable this, first set the scannerPrefixes capability (see Set Capabilities). Once configured, this event fires whenever the terminal scans a barcode, returning the scanned value as a string.

pc.on("scanner", (barcode: string) => { /* ... */ });

Commands

Once connected, you can remotely control the PoS terminal through the following commands:

| Command | Description | |---|---| | startEMV(amount, emvType?, metadata?) | Start a transaction | | cancelEMV() | Cancel a transaction | | reverseTransaction(folio) | Reverse a previous transaction | | printTransaction(folio) | Reprint a transaction receipt | | setCapabilities(capabilities) | Configure terminal capabilities | | authorize(email, password) | Authenticate with the terminal | | setPin(pin, password) | Set a PIN on the terminal | | authorizePin(pin) | Authenticate using a PIN | | logout() | Log out of the terminal |

Start EMV

Starts an EMV transaction on the connected PoS terminal. The amount is in MXN only for now. The optional emvType parameter defaults to "Combined" and can be set to "Emv", "Amex", or "Combined". Subscribe to the emvState event to track the transaction lifecycle.

| Parameter | Type | Default | Description | |---|---|---|---| | amount | number | (required) | The transaction amount in MXN. | | emvType | "Emv" | "Amex" | "Combined" | "Combined" | The type of EMV transaction. | | metadata | Record<string, unknown> | undefined | Arbitrary data to attach to this transaction. Echoed back on every emvState event for this transaction. |

await pc.startEMV(150.00);

// Or specify the EMV type
await pc.startEMV(150.00, "Amex");

// Pass metadata to correlate events with your application state
await pc.startEMV(150.00, "Combined", {
  customerId: 1234,
  orderId: "ORD-5678",
});

When metadata is provided, it is included in the metadata field of every emvState event emitted for that transaction:

pc.on("emvState", (data: EMVData) => {
  console.log(data.state);    // "awaitingCard" | "processing" | "success" | ...
  console.log(data.metadata); // { customerId: 1234, orderId: "ORD-5678" }
});

Cancel EMV

Cancels an EMV transaction that is still in the state 'awaitingCard', if it has started processing the transaction can't be cancelled and this call will be ignored.

await pc.cancelEMV();

Reverse Transaction

Reverses a previously completed transaction by its folio number. Listen to the emvState event for the reversal result.

await pc.reverseTransaction("123456789");

Print Transaction

Reprints the receipt for a previously completed transaction by its folio number.

await pc.printTransaction("123456789");

Set Capabilities

Configures the terminal's capabilities. Available options:

  • scannerPrefixes — Array of barcode prefixes to enable the scanner event
  • pingInternetConnectivity — Enable internet connectivity checks
  • forceRemoteControl — Force the terminal into remote control mode
  • disableManualPayments — Disable manual payment entry on the terminal
await pc.setCapabilities({
  scannerPrefixes: ["PREFIX1", "PREFIX2"],
  forceRemoteControl: true,
});

Authorize

Authenticates with the connected PoS terminal using email and password credentials.

await pc.authorize("[email protected]", "password");

Set PIN

Sets a PIN on the terminal for PIN-based authentication. Requires the account password for verification.

await pc.setPin("1234", "password");

Authorize PIN

Authenticates with the terminal using a previously configured PIN.

await pc.authorizePin("1234");

Logout

Logs out of the connected PoS terminal.

await pc.logout();