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

@zippypay/checkout

v1.2.2

Published

Zippy Pay checkout SDK — embed inline or in a modal on any merchant site

Readme

@zippypay/checkout

npm version License: MIT

Browser checkout SDK for Zippy Pay merchants. Embed payment UI inline on a checkout page or open it in a modal. Works with vanilla JavaScript, React, Vue, Angular, and any stack that runs modern JavaScript.

Styles are scoped inside Shadow DOM — no extra CSS import is required.


Install

npm install @zippypay/checkout
yarn add @zippypay/checkout
pnpm add @zippypay/checkout

Before the SDK runs

Your server creates a payment session and passes credentials to the checkout page:

| Field | Description | |---|---| | sessionId | Payment session identifier — safe in URLs | | clientToken | Short-lived token from your server — browser only, never public |

Never expose merchant API credentials in browser code. Never put clientToken in QR codes, query strings, logs, or analytics.


Quick start

JavaScript / TypeScript

import { ZippyPay } from '@zippypay/checkout';

const checkout = ZippyPay.create({
  environment: 'production',
  sessionId: '11111111-1111-4111-8111-111111111111',
  clientToken: 'zps_…',
  mode: 'inline',
  container: '#zippy-checkout',
  theme: { primary: '#2563eb' },
  onComplete: (session) => console.log('Paid', session),
});

Modal

ZippyPay.create({
  environment: 'production',
  sessionId,
  clientToken,
  mode: 'modal',
  closeOnBackdropClick: true,
  closeOnEscape: true,
  onClose: () => console.log('Modal closed'),
});

Web Component

<script type="module">
  import '@zippypay/checkout';
</script>

<zippy-pay-checkout
  environment="production"
  session-id="11111111-1111-4111-8111-111111111111"
  mode="inline"
  theme-primary="#2563eb"
></zippy-pay-checkout>

<script type="module">
  const el = document.querySelector('zippy-pay-checkout');
  el.clientToken = 'zps_…'; // property, not HTML attribute
  el.addEventListener('zippy-complete', (e) => console.log(e.detail));
</script>

Script tag (UMD)

Load from a public npm CDN:

<script src="https://unpkg.com/@zippypay/checkout@1/dist/index.min.js"></script>
<script>
  ZippyPay.create({
    environment: 'production',
    sessionId: '…',
    clientToken: 'zps_…',
    mode: 'inline',
    container: '#zippy-checkout',
  });
</script>

Pin the version in production (e.g. @1.2.0 instead of @1).


Environments

| Environment | Use when | |---|---| | production | Live merchant checkout | | staging | Pre-production testing | | development | Local development with a proxy |

Use the same environment where your server created the payment session.


Configuration

type ZippyPayConfig = {
  environment: 'production' | 'staging' | 'development';
  sessionId: string;
  clientToken: string;
  mode?: 'inline' | 'modal';
  container?: HTMLElement | string; // required for inline
  theme?: ZippyTheme;
  /** Restrict web checkout methods. Omit for full chooser (QR + manual). */
  checkoutPolicy?: 'QR' | 'MANUAL';
  /**
   * Phone-only app handoff. Ignored on desktop.
   * Default policy: `enforce` (SDK 1.2.0+). Pass `{ policy: 'off' }` for web-only on phone.
   */
  mobileApp?: { policy?: 'off' | 'option' | 'enforce' };
  redirectOnComplete?: boolean;
  redirectOnFailure?: boolean;
  closeOnBackdropClick?: boolean;
  closeOnEscape?: boolean;
  onReady?: (session) => void;
  onSessionUpdate?: (session) => void;
  onComplete?: (session) => void;
  onExpired?: (session) => void;
  onError?: (error: ZippyPayError) => void;
  onClose?: () => void;
};

Instance methods: open(), close() (modal), destroy()

Checkout policy

Control which payment methods customers can use:

| Config | Customer sees | |---|---| | (omit checkoutPolicy) | Full chooser — QR + manual | | checkoutPolicy: 'QR' | QR only | | checkoutPolicy: 'MANUAL' | Manual Zippy ID only |

Mobile app (phone)

On phone, customers can pay in the Zippy app via Pay with Zippy. On desktop, mobile app settings are ignored — customers use QR and/or manual per checkoutPolicy.

| mobileApp.policy | Phone behavior | |---|---| | enforce (default) | Auto-starts Pay with Zippy; QR/manual hidden until app handoff fails | | option | Full chooser plus a “Pay with Zippy” button | | off | Web checkout only (QR / manual per checkoutPolicy) |

Omitting mobileApp (or policy) is the same as enforce (SDK 1.2.0+). To keep web-only checkout on phone (behavior before 1.2.0):

mobileApp: { policy: 'off' }

Pay with Zippy flow

  1. Customer taps Pay with Zippy (or checkout auto-starts it when enforce).
  2. The button becomes disabled and shows Opening Zippy… for up to 8 seconds.
  3. The SDK opens the app from that tap — checkout stays on your page:
    • iOS: https://zippypay.io/app/merchant-payment/{sessionId}
    • Android: intent URL for the same HTTPS link targeting com.zippy.pay
  4. If the app opens → Complete your payment in the Zippy app.
  5. If the app does not open → failed handoff UI:
    • Try again
    • Or pay another way (QR and/or manual per checkoutPolicy)
    • Install Zippy (bottom) — opens the native store; not opened automatically

Install Zippy store links (fixed by Zippy, not merchant-configurable):

| Platform | Web / QR | Install button (native) | |---|---|---| | iOS | App Store | itms-apps://apps.apple.com/in/app/zippypay/id6806799311 | | Android | Google Play | market://details?id=com.zippy.pay |

Deep links and QR payloads use sessionId only — never include clientToken.

Switching from mobile app to QR or manual

If checkout started as MOBILE_APP and the customer has not yet claimed payment in the app, they may switch from the failed handoff screen:

| Customer picks | SDK behavior | |---|---| | QR code | Starts QR checkout (pay timer is not reset) | | Zippy account (manual) | Opens manual entry; backend switches to MANUAL when the payer is verified and attached |

After payment is claimed in the app or a payer is attached on manual, method switching is no longer available.

Theming

| Token | CSS variable | Default | |---|---|---| | primary | --zippy-primary | #3f63f3 | | primaryForeground | --zippy-primary-foreground | #ffffff | | background | --zippy-background | #ffffff | | surface | --zippy-surface | #f8fafc | | text | --zippy-text | #0f172a | | textMuted | --zippy-text-muted | #64748b | | border | --zippy-border | #e2e8f0 | | borderRadius | --zippy-radius | 20px | | fontFamily | --zippy-font-family | DM Sans stack | | mode | — | light | dark | auto |

Web component: use theme-primary, theme-mode, etc.


Checkout experience

The SDK guides customers through payment and keeps your page updated until the session reaches a final state.

Payment methods

| Method | Customer experience | |---|---| | QR | Scan a QR code in the Zippy app, then confirm payment in the app | | Manual | Enter a Zippy ID, verify identity, then confirm payment in the app | | Mobile app (phone) | Tap Pay with Zippy → pay in the app; fallback to QR/manual if the app cannot open |

After QR or manual checkout is committed, customers generally cannot switch methods. Exception: MOBILE_APP → QR/MANUAL is allowed before claim, via the failed handoff fallbacks.

Timers and amount

  • A bottom pay progress bar shows during the pay window (including idle Pay with Zippy).
  • The inline countdown timer is hidden on idle and Opening Zippy…; it appears after the app opens, on failed handoff, and while awaiting payment.
  • Display the amount from the session passed to your callbacks (onReady, onSessionUpdate, onComplete) — do not rely on amount props from your own page markup alone.
  • Sessions also have idle and absolute expiry boundaries handled by the SDK UI.

Web component

Attributes

| Attribute | Values | |---|---| | environment | production, staging, development | | session-id | Session UUID | | mode | inline, modal | | checkout-policy | QR, MANUAL | | mobile-app-policy | off, option, enforce (default: enforce when omitted) | | theme-* | See theming table above |

Set clientToken via the property (not an HTML attribute).

Events

| Event | When | |---|---| | zippy-ready | Checkout loaded and ready | | zippy-session-update | Session status updated | | zippy-complete | Payment succeeded | | zippy-expired | Session expired | | zippy-error | Checkout error | | zippy-close | Modal closed |


Framework notes

React

'use client';

import { useEffect, useRef } from 'react';
import '@zippypay/checkout';

export function ZippyCheckout({ sessionId, clientToken }: Props) {
  const ref = useRef<HTMLElement & { clientToken: string }>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    el.clientToken = clientToken;
    const onComplete = (e: Event) => console.log((e as CustomEvent).detail);
    el.addEventListener('zippy-complete', onComplete);
    return () => el.removeEventListener('zippy-complete', onComplete);
  }, [clientToken]);

  return (
    <zippy-pay-checkout
      ref={ref}
      environment="production"
      session-id={sessionId}
      mode="inline"
    />
  );
}

Or imperative: ZippyPay.create({ container: ref.current, … }) and destroy() on unmount.

Vue 3

Import @zippypay/checkout, set el.clientToken in onMounted, listen for @zippy-complete.

Angular

Import the package, use CUSTOM_ELEMENTS_SCHEMA, set nativeElement.clientToken in ngAfterViewInit.


Error handling

Use onError to receive a ZippyPayError with code, status, and detail. If checkout cannot continue (for example, an invalid or expired token), show your own recovery flow — typically creating a new session on your server and re-initializing the SDK.


Security checklist

  1. Never bundle merchant API credentials in browser code.
  2. Keep clientToken in memory only.
  3. Put only sessionId in QR codes and app deep links — never the client token.
  4. Use the session amount from SDK callbacks, not from unchecked page props.

Requirements

  • Modern browsers with ES2020, fetch, Shadow DOM, and Custom Elements
  • Node.js ≥ 18 for local development / bundlers

More documentation

Full integration guide and framework examples:

github.com/IMAGINE-INNOVATION-LIMITED/zippy-pay-web-sdk


License

MIT © Imagine Innovation Limited