PayProvider
React context that loads balances and resumes checkout confirmation.
PayProvider is required by all React components and hooks. Put it above
the parts of your app that show or spend credits.
import { PayProvider } from "@/components/pay/provider";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<PayProvider
baseUrl={process.env.NEXT_PUBLIC_PAY_URL!}
publishableKey={process.env.NEXT_PUBLIC_PAY_KEY!}
>
{children}
</PayProvider>
);
}Install
npx shadcn@latest add https://pay.vantezzen.io/r/pay-provider.jsonUsage
Credit-code projects
import { PayProvider } from "@/components/pay/provider";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<PayProvider
baseUrl={process.env.NEXT_PUBLIC_PAY_URL!}
publishableKey={process.env.NEXT_PUBLIC_PAY_KEY!}
>
{children}
</PayProvider>
</body>
</html>
);
}External-auth projects
For logged-in apps, keep PAY_SECRET_KEY on your server and let the browser
components call same-origin bridge routes that you own.
<PayProvider
baseUrl={process.env.NEXT_PUBLIC_PAY_URL!}
publishableKey={process.env.NEXT_PUBLIC_PAY_KEY!}
mode="external_auth"
externalUserId={user.id}
externalApiBasePath="/api/pay"
>
{children}
</PayProvider>The bridge should expose POST /api/pay/wallet, POST /api/pay/checkout,
POST /api/pay/portal, and optionally POST /api/pay/deduct, all backed by
createPayServerClient(). Validate the current session in those routes before
using externalUserId.
Props
| Prop | Type | Required | Description |
|---|---|---|---|
baseUrl | string | Yes | Public URL of your vantezzen/pay instance. |
publishableKey | string | Yes | Project publishable key, starting with pay_pk_. |
mode | "credit_codes" | "external_auth" | No | Defaults to credit_codes. |
externalUserId | string | For external auth | Stable user id from your app. |
externalApiBasePath | string | No | Same-origin bridge path for external-auth server calls. Defaults to /api/pay. |
storageKey | string | No | Custom localStorage key for credit-code wallets. |
children | React.ReactNode | Yes | UI that can read or spend credits. |
What it does
- Creates a
createPayClient()client. - Loads the wallet on mount - balances, unlocked features, and subscriptions.
- Exposes the client through
usePay(). - Exposes balances and deduction helpers through
useCredits(). - Exposes feature access through
useFeature()and subscriptions throughuseSubscription(). - Caches the product catalog once and shares it through
useProducts(). - Runs a handler after a completed checkout through
useCheckoutPaid(). - Starts checkout with desktop popup/mobile redirect behavior through
usePayCheckout(). - Watches pending checkout orders in the background and refreshes when the order is paid.
- Dispatches a
pay:checkout-paidbrowser event after popup completion or redirect resume.WalletButtonuses this to show the post-purchase wallet reminder.
useProducts
Read the project's product catalog. The catalog is fetched once and shared — purchase dialogs and your own pricing UI read the same cache.
const { products, loading } = useProducts();| Field | Type | Description |
|---|---|---|
products | Product[] | null | The catalog, or null before the first load completes. |
loading | boolean | true until the first load settles. |
error | string | null | Message from the last failed load, or null. |
refresh | () => Promise<void> | Force a refetch (e.g. after you know the catalog changed). |
useCheckoutPaid
Run a handler whenever a checkout started from this page is confirmed paid — popup completion, redirect resume, or background confirmation.
useCheckoutPaid((order) => toast.success(`Payment received (${order.status})`));The wallet context (balances, features, subscriptions) has already been
refreshed by the time the handler fires, and the handler does not need to be
memoized. The raw PAY_CHECKOUT_PAID_EVENT constant remains available for
non-React listeners.