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

@paygood1/collect-react

v0.15.0

Published

React wrapper for PayGood card collection core

Readme

@paygood1/collect-react

React wrapper for @paygood1/collect-core with a drop-in <PaymentInstrumentCollect /> component.

Install

npm install @paygood1/collect-react @paygood1/collect-core

Payment instruments

Set the instrument prop to choose what to collect:

| instrument | Description | | --- | --- | | "card" (default) | Card number, expiration, and CVC | | "bank_account" | US ACH or Canadian EFT bank account details |

For bank accounts, use allowedBankCountries to restrict collection to "US", "CA", or both. When a single country is provided, the in-component country selector is hidden and that country is used automatically.

Basic usage

Your backend must bootstrap a session key before rendering the component. First create a tokenization intent, then exchange that intent token for a session key:

  1. POST /tokenization/intents with your merchant API key as bearer auth and a customerId in the request body.
  2. Use the token value returned from step 1 as bearer auth on POST /tokenization/sessions.

Pass the resulting sessionKey into the component:

import { PaymentInstrumentCollect } from "@paygood1/collect-react";

const sessionKey = await fetch("/api/tokenization/session", {
  method: "POST"
}).then((response) => response.json()).then((body) => body.sessionKey);

export function Checkout() {
  return (
    <PaymentInstrumentCollect
      instrument="card"
      mode="sandbox"
      sessionKey={sessionKey}
      onTokenized={(result) => {
        if (result.kind === "token_intent") {
          chargeWithIntent(result.tokenIntentId);
        } else {
          chargeWithToken(result.tokenId);
        }
      }}
    />
  );
}

Bank account example with country restrictions:

<PaymentInstrumentCollect
  instrument="bank_account"
  allowedBankCountries={["US"]}
  mode="sandbox"
  sessionKey={sessionKey}
  onTokenized={(result) => {
    if (result.kind === "token_intent") {
      chargeWithIntent(result.tokenIntentId);
    } else {
      chargeWithToken(result.tokenId);
    }
  }}
/>

Perform the intent and session requests server-side. Do not expose your merchant API key in the browser.

Save card behavior

By default the component shows a Save for later checkbox (unchecked). One-off checkouts create a token intent; checking the box creates a persistent token.

For subscription or mandate flows where the card must be saved, pass requireSaveCard. This hides the checkbox and always creates a token:

<PaymentInstrumentCollect
  instrument="card"
  mode="sandbox"
  sessionKey={sessionKey}
  requireSaveCard
  tokenizeButtonLabel="Subscribe"
  onTokenized={(result) => {
    console.log(result.kind === "token" ? result.tokenId : result.tokenIntentId);
  }}
/>

Tokenization result

onTokenized receives a discriminated TokenizationResult:

type TokenizationResult =
  | { kind: "token"; tokenId: string; fingerprint: string; type: "card" | "bank_account" }
  | {
      kind: "token_intent";
      tokenIntentId: string;
      fingerprint: string;
      type: "card" | "bank_account";
    };

When the save checkbox is unchecked (default), the result is a token intent. When checked, or when requireSaveCard is set, the result is a persistent token.

Session key from your backend

Use a backend route to run the intent-to-session flow and return only sessionKey to the browser:

// Server-side example
const intentResponse = await fetch("https://api-sandbox.paygood.co/tokenization/intents", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_MERCHANT_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ customerId: "cust_123" })
});
const { token } = await intentResponse.json();

const sessionResponse = await fetch("https://api-sandbox.paygood.co/tokenization/sessions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json"
  }
});
const { sessionKey } = await sessionResponse.json();

Then pass it to the component:

<PaymentInstrumentCollect
  mode="sandbox"
  sessionKey={sessionKey}
  onTokenized={(result) => {
    if (result.kind === "token_intent") {
      chargeWithIntent(result.tokenIntentId);
    } else {
      chargeWithToken(result.tokenId);
    }
  }}
/>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | instrument | "card" \| "bank_account" | "card" | Payment instrument to collect | | allowedBankCountries | AllowedBankCountry[] | all countries | Bank flows only. Restrict to "US", "CA", or both | | mode | "sandbox" \| "production" | "sandbox" | PayGood environment | | sessionKey | string | — | Basis Theory session key from your backend | | mountOptions | object | — | Passed to core.mount() | | requireSaveCard | boolean | false | Subscription/mandate flows. Hides checkbox and always creates a token | | saveCardLabel | string | "Save for later" | Checkbox label when requireSaveCard is false | | tokenizeButtonLabel | string | "Confirm" | Submit button label | | collectCustomerDetails | boolean | true | Collect full name and billing address on card flows only (ignored for bank) | | defaultBillingAddressExpanded | boolean | false | Whether billing address starts expanded | | customerDetails | CustomerDetails | — | Controlled customer details | | defaultCustomerDetails | Partial<CustomerDetails> | — | Initial values in uncontrolled mode | | onCustomerDetailsChange | (details) => void | — | Called whenever customer details change | | onTokenized | (result, context?) => void | — | Called after tokenization; context.customerDetails is a submit-time snapshot | | onChange | (payload) => void | — | Field changes and bank country changes | | onReady | () => void | — | Called when the component is ready | | onError | (error) => void | — | Called on errors |

Import AllowedBankCountry and ALLOWED_BANK_COUNTRIES from @paygood1/collect-core when you need the canonical allowed values.

Customer details and billing address

By default the component collects a full name and a collapsible US/CA billing address before card tokenization. Bank account flows do not collect customer or billing details.

import {
  PaymentInstrumentCollect,
  type CustomerDetails
} from "@paygood1/collect-react";

export function Checkout() {
  const [customerDetails, setCustomerDetails] = useState<CustomerDetails | null>(null);

  return (
    <PaymentInstrumentCollect
      sessionKey={sessionKey}
      onCustomerDetailsChange={setCustomerDetails}
      onTokenized={(result, context) => {
        createPaymentInstrument({
          fullName: context!.customerDetails.fullName,
          billingAddress: context!.customerDetails.billingAddress,
          tokenIntentId: result.kind === "token_intent" ? result.tokenIntentId : undefined,
          tokenId: result.kind === "token" ? result.tokenId : undefined
        });
      }}
    />
  );
}

Pass collectCustomerDetails={false} to disable customer fields and preserve the previous payment-only behavior.