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

mypos-online-checkout

v0.1.1

Published

TypeScript SDK for the myPOS Online Checkout API — generate signed payment forms and validate webhooks, with optional React helpers.

Readme

myPOS Online Checkout

A TypeScript SDK for the myPOS Online Checkout API, designed for server-side use in Node.js applications.

It handles RSA-SHA256 request signing, webhook signature verification, and provides typed wrappers for all IPC methods — so you can integrate myPOS payments without touching raw HTTP or cryptography directly.

Features

  • Purchase — generate signed form fields for the myPOS hosted checkout page
  • Webhook validation — verify the RSA-SHA256 signature on incoming IPCPurchaseNotify callbacks
  • Store a Card — tokenize a card via the hosted checkout page for future charges
  • Charge Stored Card — charge a stored card token directly, no customer redirect required (requires myPOS enablement)
  • Payment Status — query the outcome of any order by its Order ID
  • Refund — issue full or partial refunds by transaction reference
  • Reversal — void a transaction before it settles
  • Pre-Authorization — hold funds on a card without charging, then capture or cancel later
  • Authorization (stored card) — reserve funds using a card token, capture or reverse on demand
  • Transfer of Funds — mandate management, send money, and request money between myPOS accounts
  • Optional React helpers — a <PaymentForm> component and usePaymentForm hook for rendering signed checkout forms
  • Dual ESM/CJS build — works with import and require, ships full TypeScript types

Requirements

  • Node.js ≥ 18
  • A myPOS merchant account with Online Checkout enabled
  • The configuration pack (base64 string) or individual credentials from the myPOS merchant portal

Server-only. All methods that sign requests or call the myPOS API use your private key and must only run in server-side code. Never expose credentials to the browser.


Installation

npm install mypos-online-checkout

Setup

1. Get your credentials

Log in to the myPOS merchant portal and download your configuration pack — a single base64-encoded string that contains your Store ID, Wallet Number, RSA private key, public certificate, and Key Index. Store it as a server-side environment variable.

MYPOS_CONFIG_PACK=eyJzaWQiOiI...   # base64 config pack from the portal
MYPOS_TEST_MODE=true               # set false in production

2. Initialize the client

import { MyPOSClient } from 'mypos-online-checkout';

const client = new MyPOSClient({
  configPack: process.env.MYPOS_CONFIG_PACK!,
  testMode:   process.env.MYPOS_TEST_MODE === 'true',
});

Alternatively, supply credentials individually if you prefer to store them as separate environment variables:

const client = new MyPOSClient({
  storeId:           process.env.MYPOS_STORE_ID!,
  walletNumber:      process.env.MYPOS_WALLET_NUMBER!,
  privateKey:        process.env.MYPOS_PRIVATE_KEY!,
  publicCertificate: process.env.MYPOS_PUBLIC_CERT!,
  keyIndex:          1,
  testMode:          true,
});

Instantiate the client once and reuse it across requests (e.g. as a module-level singleton or via a singleton pattern in your framework).


Methods

Purchase

The myPOS purchase flow works differently from a typical API call — the payment is initiated by submitting an HTML form directly to the myPOS hosted checkout page from the browser. Your server generates and signs the form fields; the browser submits them.

1. Generate signed form fields (server-side)

const fields = client.generatePurchaseFields(
  {
    items: [
      {
        article:  'Blue Widget',
        quantity: 2,
        price:    14.99,
        amount:   29.98,
      },
    ],
  },
  `ORDER-${Date.now()}`,           // unique Order ID
  {
    currency:  'EUR',
    urlOk:     'https://mystore.com/checkout/success',
    urlCancel: 'https://mystore.com/checkout/cancel',
    urlNotify: 'https://mystore.com/api/mypos/webhook',
  }
);
// fields is a plain Record<string, string> — safe to serialise across the server/client boundary

2. Render the form (client-side, with React helper)

import { PaymentForm } from 'mypos-online-checkout/react';

// Pass fields and checkoutUrl as props from the server component
<PaymentForm
  fields={fields}
  checkoutUrl={mypos.checkoutUrl}
  submitLabel="Pay Now"
/>

Or without the React helper:

<form method="POST" action="https://www.mypos.com/vmp/checkout-test/">
  <!-- render one hidden input per field -->
  <button type="submit">Pay Now</button>
</form>

3. Validate the webhook (server-side)

myPOS POSTs a signed IPCPurchaseNotify callback to urlNotify after the customer pays.

// Next.js App Router route handler
import { NextRequest } from 'next/server';

export async function POST(req: NextRequest) {
  const formData = await req.formData();
  const result = await mypos.validateWebhook(formData);

  if (!result.valid) {
    return new Response('Invalid signature', { status: 400 });
  }

  const { orderId, ipcTrnref, amount, currency, paymentStatus } = result;
  // paymentStatus === 1 means successful — fulfill the order
  await fulfillOrder(orderId, ipcTrnref);

  return new Response('OK');
}

Key points:

  • OrderID must be unique per paid order. myPOS rejects duplicate Order IDs after a successful payment.
  • urlNotify must be an HTTPS URL with no port number.
  • Always validate the webhook signature before trusting the payload.

Store a Card

Tokenize a customer's card for future charges by running a standard IPCPurchase with cardTokenRequest: 2. The customer completes a small verification charge on the myPOS hosted checkout page; the reusable card token is returned in the IPCPurchaseNotify webhook.

// Server-side: generate signed fields
const fields = client.generatePurchaseFields(
  { items: [{ article: 'Card storage', quantity: 1, price: 0.50, amount: 0.50 }] },
  `STORE-${Date.now()}`,
  {
    currency:         'EUR',
    cardTokenRequest: 2, // store a reusable card token
    urlOk:     'https://mystore.com/store-card/success',
    urlCancel: 'https://mystore.com/store-card/cancel',
    urlNotify: 'https://mystore.com/api/mypos/webhook',
  }
);

// In your webhook handler — result.cardToken is the reusable token
const result = client.validateWebhook(formData);
if (result.isValid && result.cardToken) {
  await db.saveCardToken(userId, result.cardToken, result.pan);
}

The card token is sensitive — store it server-side and never expose it to the browser. A minimum charge of €0.50 is required to verify the card.


Charge Stored Card

Charge a stored card token directly without redirecting the customer to the hosted checkout page (IPCIAPurchase). Uses the same cart structure as generatePurchaseFields().

This method must be explicitly enabled by myPOS for your merchant account. Contact myPOS support to request access before using it in production.

const result = await client.iaPurchase({
  cardToken: 'TOKEN_FROM_STORE_CARD_WEBHOOK',
  orderId:   `IA-${Date.now()}`,
  cart: {
    items: [{ article: 'Monthly subscription', quantity: 1, price: 29.99, amount: 29.99 }],
  },
  currency: 'EUR',
});

if (result.success) {
  console.log('Charged:', result.ipcTrnref, result.amount, result.currency);
} else {
  console.error(`[${result.status}] ${result.statusMsg}`);
}

Use a unique orderId per charge — different from the order that originally stored the card. The currency must match the currency of the original purchase that produced the token.


Payment Status

Query the current status of an order by its Order ID.

const result = await client.getPaymentStatus({
  orderId: 'ORDER-1234567890',
  includeDeclinedPayments: false, // set true to get individual decline reason codes
});

if (result.success && result.paymentStatus === 1) {
  // paymentStatus: 1=Successful, 2=Pending, 3=Unsuccessful, 4=Reversed
  console.log('Trnref:', result.ipcTrnref);
  console.log('Amount:', result.amount, result.currency);
}

Refund

Issue a full or partial refund using the transaction reference from the purchase webhook.

const result = await client.refund({
  ipcTrnref: '12345678923',    // from IPCPurchaseNotify webhook
  amount:    9.99,
  currency:  'EUR',
  orderId:   'REF-ORDER-001', // optional — use a distinct ID from the original
});

if (result.success) {
  console.log('Refund confirmed:', result.ipcTrnref);
}

Partial refunds are supported — pass any amount up to the original transaction total. The currency must match the original transaction currency.


Reversal

Void a transaction in full before it settles at the network level.

const result = await client.reversal({
  ipcTrnref: '12345678923', // from IPCPurchaseNotify webhook
});

if (result.success) {
  console.log('Reversed:', result.ipcTrnref);
}

A reversal voids the transaction entirely. If the transaction has already settled, use Refund instead.


Pre-Authorization

Pre-authorization is a two-stage flow: first hold the funds on the customer's card (via the hosted page), then either capture or void the hold later.

Pre-Authorize (hold funds via hosted page)

Works like Purchase — generate signed fields server-side, submit the form from the browser.

const fields = client.generatePreAuthFields(
  {
    items: [{ article: 'Hotel Stay', quantity: 1, price: 200, amount: 200 }],
  },
  `PREAUTH-${Date.now()}`,
  {
    currency:  'EUR',
    urlOk:     'https://mystore.com/pre-auth/success',
    urlCancel: 'https://mystore.com/pre-auth/cancel',
    urlNotify: 'https://mystore.com/api/mypos/webhook',
  }
);

Store the orderId from the urlNotify webhook — it is required for Complete and Cancel.

Complete (capture held funds)

const result = await client.completePreAuth({
  orderId:  'PREAUTH-1234567890',
  amount:   150.00, // can be less than or equal to the pre-authorized amount
  currency: 'EUR',
});

Cancel (void the hold)

const result = await client.cancelPreAuth({
  orderId: 'PREAUTH-1234567890',
});

Status

const result = await client.getPreAuthStatus({
  orderId: 'PREAUTH-1234567890',
});
// result.status: 1=Pending, 3=Captured, 4=Declined, 5=Reversed, 6=Cancelled
// result.expiryDate: ISO date string — act before the hold expires

Authorization (stored card)

Use these methods to reserve and settle funds against a card token obtained from a prior purchase.

To receive a card token, include cardTokenRequest: 1 (one-time token) or cardTokenRequest: 2 (reusable token) in generatePurchaseFields(). The token is delivered in the IPCPurchaseNotify webhook.

Authorize

const result = await client.authorize({
  orderId:   `AUTH-${Date.now()}`,
  amount:    49.99,
  currency:  'EUR',
  cardToken: 'YOUR_CARD_TOKEN',
  itemName:  'Subscription renewal',
});
// Store result.orderId — needed for Capture or Reverse

Capture

const result = await client.captureAuthorization({
  orderId:  'AUTH-1234567890',
  amount:   49.99,
  currency: 'EUR',
});

Reverse

const result = await client.reverseAuthorization({
  orderId: 'AUTH-1234567890',
});

List pending authorizations

const result = await client.listAuthorizations();

if (result.success && result.authorizations) {
  for (const auth of result.authorizations) {
    console.log(auth.orderId, auth.amount, auth.currency);
  }
}

Transfer of Funds

Note: These methods require additional enablement or a signed contract with myPOS. Contact [email protected] for access.

Mandate Management

Register or cancel a direct debit mandate against a customer's myPOS account. A registered mandate is required before calling Request Money.

// Register
await client.mandateManagement({
  mandateReference:     'MANDATE-001',
  customerWalletNumber: '12345678901',
  action:               1,                        // 1=Register, 2=Cancel
  mandateText:          'Monthly subscription',  // optional
});

// Cancel
await client.mandateManagement({
  mandateReference:     'MANDATE-001',
  customerWalletNumber: '12345678901',
  action:               2,
});

Send Money

Transfer funds from your myPOS merchant account to another myPOS account.

const result = await client.sendMoney({
  customerWalletNumber: '12345678901',
  amount:               50.00,
  currency:             'EUR',
  transactionReference: `TRF-${Date.now()}`,
  reason:               'Invoice #12345',
});

Request Money

Pull funds from a customer's myPOS account using a pre-registered mandate.

const result = await client.requestMoney({
  mandateReference:     'MANDATE-001',
  customerWalletNumber: '12345678901',
  orderId:              `REQ-${Date.now()}`,
  amount:               99.99,
  currency:             'EUR',
  reason:               'Invoice #12345',
});

Configuration Reference

MyPOSConfig

Two forms are accepted — provide either configPack or individual credential fields. The two forms are mutually exclusive.

| Option | Type | Description | | --------------------- | ----------- | ------------------------------------------------------------------------ | | configPack | string | Base64-encoded config pack from the myPOS merchant portal (recommended) | | storeId | string | Store ID (sid) — alternative to configPack | | walletNumber | string | Wallet number (cn) — alternative to configPack | | privateKey | string | PEM-encoded RSA private key — alternative to configPack | | publicCertificate | string | PEM-encoded public certificate — alternative to configPack | | keyIndex | number | Key index (idx) — alternative to configPack | | testMode | boolean | Use the sandbox environment. Default:false | | source | string | Sent as the Source field on every request. Default: 'NodeJS SDK' | | partnerId | string | myPOS Partners Program partner ID — enables IPC version 1.4.1 | | applicationId | string | myPOS Partners Program application ID |

Supported languages

The language field in PurchaseConfig and PreAuthConfig accepts: EN, FR, IT, DE, SV, PT, NL, EL, BG, ES.


Error handling

The SDK throws typed errors for configuration and signing failures:

import { MyPOSConfigError, MyPOSSignatureError, MyPOSCartError } from 'mypos-online-checkout';

try {
  const fields = mypos.generatePurchaseFields(cart, orderId, config);
} catch (err) {
  if (err instanceof MyPOSCartError)    { /* empty cart or invalid item */ }
  if (err instanceof MyPOSSignatureError) { /* private key is malformed */ }
  if (err instanceof MyPOSConfigError)  { /* config pack could not be decoded */ }
}

For API calls (refund, getPaymentStatus, etc.), errors from the myPOS gateway are returned as result.success === false with a status code and statusMsg string rather than thrown exceptions.


React helper

The optional mypos-online-checkout/react sub-package exports a ready-made form component and hook. React 18+ is required as a peer dependency.

import { PaymentForm } from 'mypos-online-checkout/react';

// Render a signed payment form — fields come from generatePurchaseFields() on the server
<PaymentForm
  fields={fields}
  checkoutUrl={mypos.checkoutUrl}
  submitLabel="Pay Now"
/>

Next.js usage guide

Project structure

app/
  checkout/
    page.tsx          ← Server Component: generates signed fields
    CheckoutForm.tsx  ← Client Component ('use client'): renders <PaymentForm>
  api/
    mypos/
      webhook/
        route.ts      ← Route Handler: validates IPCPurchaseNotify

Server Component (app/checkout/page.tsx)

import { mypos } from '@/lib/mypos';

export default async function CheckoutPage() {
  const fields = mypos.generatePurchaseFields(
    { items: [{ article: 'Product', quantity: 1, price: 9.99, amount: 9.99 }] },
    `ORDER-${Date.now()}`,
    {
      currency:  'EUR',
      urlOk:     `${process.env.NEXT_PUBLIC_BASE_URL}/checkout/success`,
      urlCancel: `${process.env.NEXT_PUBLIC_BASE_URL}/checkout/cancel`,
      urlNotify: `${process.env.NEXT_PUBLIC_BASE_URL}/api/mypos/webhook`,
    }
  );

  return <CheckoutForm fields={fields} checkoutUrl={mypos.checkoutUrl} />;
}

Client Component (app/checkout/CheckoutForm.tsx)

'use client';
import { PaymentForm } from 'mypos-online-checkout/react';
import type { PaymentFormFields } from 'mypos-online-checkout';

export function CheckoutForm({
  fields,
  checkoutUrl,
}: {
  fields: PaymentFormFields;
  checkoutUrl: string;
}) {
  return <PaymentForm fields={fields} checkoutUrl={checkoutUrl} submitLabel="Pay Now" />;
}

Webhook route (app/api/mypos/webhook/route.ts)

import { NextRequest } from 'next/server';
import { mypos } from '@/lib/mypos';

export async function POST(req: NextRequest) {
  const formData = await req.formData();
  const result = await mypos.validateWebhook(formData);

  if (!result.valid || result.paymentStatus !== 1) {
    return new Response('Ignored', { status: 200 });
  }

  await fulfillOrder(result.orderId, result.ipcTrnref);
  return new Response('OK');
}

Shared client singleton (lib/mypos.ts)

import { MyPOSClient } from 'mypos-online-checkout';

export const mypos = new MyPOSClient({
  configPack: process.env.MYPOS_CONFIG_PACK!,
  testMode:   process.env.MYPOS_TEST_MODE === 'true',
});

API reference

Full IPC method documentation is available on the myPOS developer portal:


License

MIT