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

@paygater/js

v0.1.3

Published

Paygate client-side JavaScript SDK for embedded payment forms

Readme

@paygater/js

Client-side JavaScript SDK for Paygate — embed a fully hosted payment form in any web app using just your public key.

npm version License: MIT TypeScript


Overview

@paygater/js gives merchants a drop-in payment form that handles Visa, Mastercard, Apple Pay, and Mada — all from a single mount() call.

How it works under the hood:

Browser                      Paygate API              Stripe / Checkout.com
───────────────────────────────────────────────────────────────────────────
new Paygate('pk_test_…')
  │
  ├─ GET /v1/public/config ──────────────────────→  { stripe_publishable_key }
  │
  ├─ loads Stripe.js (from js.stripe.com)
  │
  ├─ renders payment method tabs + Stripe iframe
  │
  ├─ customer enters card (stays inside Stripe iframe — never touches your JS)
  │
  └─ onToken('tok_xxx', 'card') called
         │
         └─ your server: POST /v1/charges ────────────────────────────────→  captured

Your public key (pk_test_…) is the only credential that ever touches the browser. The secret key (sk_test_…) lives exclusively on your server.


Installation

npm install @paygater/js

CDN (no build step):

<script type="module">
  import { Paygate } from 'https://cdn.jsdelivr.net/npm/@paygater/js/dist/index.mjs';
</script>

Quick start

Vanilla JS / HTML

<div id="payment-form"></div>

<script type="module">
  import { Paygate } from '@paygater/js';

  const pg = new Paygate('pk_test_your_key_here');

  await pg.mount('#payment-form', {
    methods: ['card', 'apple_pay', 'mada'],
    currency: 'SAR',

    onToken: async (token, method) => {
      // Send token to YOUR backend — never call Paygate directly from the browser
      const res = await fetch('/checkout', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token, method, amount: 5000 }),
      });

      const { charge_id } = await res.json();
      window.location.href = `/order/${charge_id}`;
    },

    onError: (err) => {
      console.error(err.message);
    },
  });
</script>

React / Next.js

'use client';
import { useEffect, useRef } from 'react';
import { Paygate } from '@paygater/js';

export function PaygateForm({ onSuccess }: { onSuccess: (chargeId: string) => void }) {
  const containerRef = useRef<HTMLDivElement>(null);
  const pgRef = useRef<Paygate | null>(null);

  useEffect(() => {
    if (!containerRef.current) return;

    const pg = new Paygate(process.env.NEXT_PUBLIC_PAYGATE_PUBLIC_KEY!);
    pgRef.current = pg;

    pg.mount(containerRef.current, {
      methods: ['card', 'apple_pay', 'mada'],
      currency: 'SAR',
      onToken: async (token, method) => {
        const res = await fetch('/api/checkout', {
          method: 'POST',
          body: JSON.stringify({ token, method }),
        });
        const { charge_id } = await res.json();
        onSuccess(charge_id);
      },
      onError: (err) => console.error(err.message),
    });

    return () => pg.unmount();
  }, []);

  return <div ref={containerRef} />;
}

Server-side charge (after onToken)

The token from onToken is meaningless without a server-side charge call. Your backend receives the token and calls Paygate:

POST https://paygate-api.fly.dev/v1/charges
Authorization: Bearer sk_test_your_secret_key
Idempotency-Key: order-abc-123
Content-Type: application/json

{
  "amount": 5000,
  "currency": "SAR",
  "payment_method": "card",
  "token": "tok_1Nj4xQ2eZvKYlo2C..."
}

Response:

{
  "id": "a1b2c3d4-...",
  "status": "captured",
  "amount": 5000,
  "currency": "SAR",
  "payment_method": "card",
  "provider": "stripe",
  "environment": "sandbox"
}

See the Paygate API docs for the full charge, refund, and webhook reference.


API reference

new Paygate(publicKey, options?)

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | publicKey | string | Yes | Your Paygate public key — pk_test_… for sandbox, pk_live_… for production | | options.apiUrl | string | No | Paygate API base URL. Defaults to https://paygate-api.fly.dev |

Throws PaygateError immediately if the key format is invalid.


pg.mount(selector, options)

Fetches SDK config from Paygate, loads Stripe.js, and renders the payment form.

| Option | Type | Required | Description | |--------|------|----------|-------------| | selector | string \| HTMLElement | Yes | CSS selector string or DOM element to render into | | methods | PaymentMethod[] | No | Methods to show. Default: ['card', 'apple_pay', 'mada'] | | currency | string | No | ISO 4217 currency code. Default: 'SAR' | | onToken | (token: string, method: PaymentMethod) => void \| Promise<void> | Yes | Fires when the customer submits a valid payment | | onError | (error: PaygateError) => void | Yes | Fires on tokenization or network errors |

Returns Promise<void>. Rejects with PaygateError if the target element isn't found or the config fetch fails.


pg.unmount()

Destroys the payment form and cleans up all DOM changes and event listeners. Safe to call multiple times. Always call this in component cleanup (e.g. React useEffect return).


Payment methods

| Method | Constant | Processor | Networks | Sandbox | |--------|----------|-----------|----------|---------| | Credit / Debit card | "card" | Stripe | Visa, Mastercard | Stripe test cards | | Apple Pay | "apple_pay" | Stripe | Apple Pay | Safari + sandbox Apple ID | | Mada | "mada" | Checkout.com | Saudi domestic debit | Fixed test token tok_mada |

Mada in sandbox: Checkout.com Frames requires domain registration and a Checkout.com public key. The sandbox SDK simulates Mada using a fixed accepted test token so you can test the full charge flow without that setup.


Security

Public key vs secret key

| Key | Prefix | Scope | Safe in browser? | |-----|--------|-------|-----------------| | Public key | pk_test_ / pk_live_ | Identifies your account. Cannot authorize charges. | ✅ Yes | | Secret key | sk_test_ / sk_live_ | Authorizes all API operations. | ❌ Never |

The SDK only ever uses the public key — to call GET /v1/public/config and retrieve the Stripe publishable key on your behalf. No charge is created from the browser.

PCI DSS scope

Card fields (card, apple_pay) are rendered inside a Stripe-hosted <iframe> on the js.stripe.com domain. Due to browser same-origin policy:

  • Your JavaScript cannot read what the customer types
  • Raw card numbers never touch your page, your servers, or Paygate's servers
  • Only Stripe receives card data — Stripe returns a one-time token

This means your integration is outside PCI DSS scope for cardholder data. Stripe is the PCI-compliant data processor.

HTTPS

The SDK emits a console.warn if mounted on a non-localhost HTTP origin. Stripe Elements and Apple Pay both require HTTPS in production.


Test cards

Use these in sandbox mode (pk_test_…). Any future expiry date and any 3-digit CVV work.

| Scenario | Card number | Brand | Result | |----------|------------|-------|--------| | Successful charge | 4242 4242 4242 4242 | Visa | captured | | Successful charge | 5555 5555 5555 4444 | Mastercard | captured | | Visa debit | 4000 0566 5566 5556 | Visa | captured | | Card declined | 4000 0000 0000 0002 | Visa | failed | | Insufficient funds | 4000 0000 0000 9995 | Visa | failed | | 3D Secure required | 4000 0025 0000 3155 | Visa | authorized (pending 3DS) | | Expired card | 4000 0000 0000 0069 | Visa | failed | | Mada (sandbox) | any input | Mada | captured via tok_mada |


TypeScript

The package ships with full type declarations. Key exported types:

import type { PaymentMethod, MountOptions, PaygateConfig, PaygateError } from '@paygater/js';

type PaymentMethod = 'card' | 'apple_pay' | 'mada';

interface MountOptions {
  methods?: PaymentMethod[];
  currency?: string;
  onToken: (token: string, method: PaymentMethod) => void | Promise<void>;
  onError: (error: PaygateError) => void;
}

Local development

git clone https://github.com/MahmoudBakr23/paygate-js.git
cd paygate-js
npm install
npm run build      # compile once → dist/
npm run dev        # watch mode
npm run typecheck  # tsc --noEmit (no emit, type check only)

Output in dist/:

| File | Format | Use | |------|--------|-----| | index.mjs | ESM | import in bundlers, CDN | | index.js | CommonJS | require() in Node.js | | index.d.ts | TypeScript | Type declarations |


Related

| Repo | Description | |------|-------------| | paygate-api | Rails 8 gateway API — charges, refunds, webhooks | | paygate-dashboard | Next.js 15 merchant dashboard | | paygate-docs | API documentation (Fumadocs) |


License

MIT