DuckyPayเอกสาร

@duckypay/react

UI-only bindings for the hosted checkout — an embedded iframe, a pay button, and a hook. No API key ever reaches the browser.

Install#

terminal
npm install @duckypay/react

React 18 and 19 are supported. Import @duckypay/react/styles.css once if you use the default button styling.

The pattern#

Create the charge server-side, pass the invoiceId down, render a component:

the split
// 1. Server: create the charge with @duckypay/node
const charge = await duckypay.charges.create({ chainId: 137, amount: '25000000' });

// 2. Return only the invoiceId to the browser — never your API key
return Response.json({ invoiceId: charge.invoiceId });

// 3. Client: hand it to any of the components above.

<DuckyPayCheckout>#

Embeds the hosted checkout in an iframe that auto-sizes to its content.

Pay.tsx
import { DuckyPayCheckout } from '@duckypay/react';
import '@duckypay/react/styles.css';

export function Pay({ invoiceId }: { invoiceId: string }) {
  return (
    <DuckyPayCheckout
      invoiceId={invoiceId}
      onSuccess={({ txHash, chainId }) => router.push(`/thanks?tx=${txHash}`)}
      onError={(e) => toast.error(e.message)}
      onExpire={() => toast('This quote expired — refresh for a new one')}
    />
  );
}
invoiceIdstringrequired

The charge to render.

theme'light' | 'dark'optional

Checkout theme override.

localestringoptional

Checkout language, e.g. "th".

autoResizebooleanoptional

Follow the iframe's content height (default true).

onReady / onSuccess / onError / onExpire / onClosehandlersoptional

Typed lifecycle callbacks — see Events below.

<DuckyPayButton>#

A drop-in pay button that opens the checkout in a centered popup (or navigates, with mode="redirect"). If the popup is blocked, it falls back to redirect automatically.

Button.tsx
import { DuckyPayButton } from '@duckypay/react';

<DuckyPayButton
  invoiceId={charge.invoiceId}
  mode="popup"              // 'popup' (default) or 'redirect'
  onSuccess={handlePaid}
>
  Pay with crypto
</DuckyPayButton>

useDuckyPayCheckout()#

Headless control for custom UI — same events, your markup.

hook.ts
import { useDuckyPayCheckout } from '@duckypay/react';

const checkout = useDuckyPayCheckout({
  onSuccess: ({ invoiceId }) => refetchOrder(invoiceId),
  onClose: () => track('checkout_dismissed'),
});

// Anywhere in your handlers:
checkout.open({ invoiceId });      // centered popup (falls back to redirect if blocked)
checkout.redirect({ invoiceId }); // full-page navigation
checkout.close();

App-wide defaults (baseUrl, locale) can be set once with <DuckyPayProvider>.

Events & security#

  • onSuccess receives { invoiceId, txHash, chainId }; onExpire fires when the quote deadline passes; onClose when the buyer dismisses the popup unpaid.
  • Messages from the checkout are origin-checked and shape-validated — a hostile page can’t forge a success event into your handlers.