@alguna/checkout-sdk

中文文档
1.0.0发布于 2026/10/16UNLICENSEDTypeScriptESM + CJS零依赖近 30 天下载 3209

Embed Alguna Checkout in your product — a themeable, isolated checkout component

原始使用文档
文档目录15 节
  1. Quickstart
  2. 0. One-time setup (Alguna dashboard)
  3. 1. Decide who the buyer is (three identity modes)
  4. 2. Create a session (your server)
  5. 3. Mount the checkout (your frontend)
  6. 4. React to completion (your server)
  7. Appearance
  8. Styling
  9. Custom pay button
  10. Saved cards
  11. Terms of service
  12. Trust line
  13. Reacting to scroll
  14. Sessions & errors
  15. Security model

@alguna/checkout-sdk

Embed Alguna Checkout in your product. Your server mints a checkout session with your secret API key; your frontend mounts the component with the returned URL; Alguna handles payment collection, tax, and account/subscription creation — the same trust model as Stripe's embedded Checkout.

The checkout renders inside an iframe served from Alguna's origin. This is a hard isolation boundary: your page's CSS can't reach into the checkout, and the checkout can't restyle your page. Card entry uses Stripe's own iframe (so your site stays out of PCI scope). Style the checkout only through the appearance prop — the same model as Stripe Elements. The SDK ships no stylesheet; there's nothing to import.

npm install @alguna/checkout-sdk

Quickstart

0. One-time setup (Alguna dashboard)

  1. Create an API key: Settings → API keys (format id.secret — server secret, never ship it to a browser).
  2. Have at least one payment processor connected (e.g. Stripe) for the legal entity you bill from.

1. Decide who the buyer is (three identity modes)

Your situationWhat to send on session createWhat checkout does
Buyer is an existing Alguna customercustomer_id (or customer_alias)Charges that customer; can show their saved cards (see Saved cards)
Buyer is logged into your productcustomer: { name, email, address? … }Creates the Alguna customer from what you already know — no re-typing
Buyer is anonymous (public pricing page)(nothing)Checkout collects email/name itself before payment

2. Create a session (your server)

const response = await fetch("https://api.alguna.io/checkout-sessions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ALGUNA_API_KEY}`,
    "Alguna-Version": "2026-04-01", // pin the API version
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    customer: { name: "Acme Corp", email: "[email protected]" }, // mode 2
    plan_id: "plan_...",              // or line_items: [...] / amount
    client_reference_id: "order_1234", // echoed on the webhook
    expires_in_seconds: 3600,
  }),
});
const session = await response.json();
// → { id, url, session_token, amount, currency, expires_at, ... }

3. Mount the checkout (your frontend)

React:

import { AlgunaCheckout } from "@alguna/checkout-sdk/react";

<AlgunaCheckout
  url={session.url}
  layout="compact"                       // your page provides the context
  appearance={{ accentColor: "#4d68eb" }}
  onComplete={({ checkoutSessionId }) => showSuccess()}
  onError={({ code }) => {
    if (code === "session_expired") refreshSession(); // mint a new one, re-mount
  }}
/>;

Vanilla:

import { AlgunaCheckout } from "@alguna/checkout-sdk";

const checkout = AlgunaCheckout.init({
  url: session.url,
  container: "#checkout",
  onComplete: () => (window.location.href = "/welcome"),
});
// checkout.update({ appearance }); checkout.destroy();

onComplete fires the moment payment succeeds — replace or unmount the component and take the customer forward; the checkout shows only a brief neutral confirmation.

4. React to completion (your server)

Subscribe to the checkout.session.completed webhook — its payload carries accountId, subscriptionId, paymentId, invoiceId, and your clientReferenceId — or poll GET /checkout-sessions/{id} until payment_id/subscription_id appear.

Appearance

Everything applies live (no re-mount) over your organization's dashboard branding:

appearance={{
  preset: "soft",              // or "minimal" | "sharp" — a curated
                               // starting point; every field below overrides it
  accentColor: "#4f46e5",      // CTAs & highlights
  primaryColor: "#0f0f0f",
  mode: "dark",                // dark canvas
  borderRadius: 12,            // cards, inputs, buttons
  fontFamily: "Georgia, serif",// no font download — use stacks you load
  density: "compact",          // tighter vertical rhythm
  payButtonLabel: "Subscribe for {amount}",
  colors: {                    // fine-grained palette
    surface: "#0b1220", card: "#111a2e", text: "#e7e5e4",
    mutedText: "#a8a29e", border: "#1f2b45", inputBackground: "#0e1626",
    inputBorder: "#2563eb",    // input outlines, separate from `border` (the
                               // frame) — set `border` to the surface color to
                               // flatten the frame while keeping fields outlined
  },
}}

Component sizing: layout: "compact" drops the checkout's own heading for in-page embedding. The iframe auto-resizes to its content; pass maxHeight to cap it, and the form scrolls inside the component above that height.

Styling

The only supported way to style the checkout is the appearance prop — colors, border radius, font family, light/dark mode, and curated presets. Because the checkout is isolated in an iframe, your page's CSS cannot (and should not) target it. This mirrors how Stripe Elements and Primer are styled.

Custom pay button

Render your own pay button instead of the built-in one:

const ref = useRef<AlgunaCheckoutRef>(null);
const [state, setState] = useState<CheckoutState>();

<AlgunaCheckout
  ref={ref}
  url={session.url}
  hidePayButton
  onCheckoutStateChange={setState}
  onComplete={...}
/>
<button disabled={!state?.canSubmit} onClick={() => ref.current?.submit()}>
  {state?.isProcessing ? "Processing…" : "Pay"}
</button>

hidePayButton hides our button (the "payments are secure and encrypted" line stays); submit() on the ref triggers payment; onCheckoutStateChange reports { canSubmit, isProcessing, isComplete, error } so you can drive your button.

Saved cards

By default every buyer — new or returning — enters their card fresh. To let a returning customer pay with a card they've used before, pass showSavedPaymentMethods (only meaningful for customer_id / customer_alias sessions, where we know who the buyer is):

<AlgunaCheckout url={session.url} showSavedPaymentMethods />

With it on, a customer who has a card on file sees it pre-selected, with a "use a different card" option to enter a new one. Cards are managed in your customer-facing settings, not edited inline at checkout.

Terms of service

The checkout shows a terms-acceptance checkbox that must be ticked before the buyer can pay. It links your legal entity's terms of service — the same terms configured for that entity elsewhere (quotes, hosted checkout) — so nothing needs to be passed on the SDK.

To make the checkbox optional (not block payment), pass requireTermsAcceptance={false}:

<AlgunaCheckout url={session.url} requireTermsAcceptance={false} />

Trust line

The "Payments are secure and encrypted" line under the pay button can be hidden:

<AlgunaCheckout url={session.url} hidePaymentSecurityText />

Reacting to scroll

The checkout iframe is sized to its content, so wheel gestures over it are forwarded to your page (which scrolls by default). To handle scrolling yourself — e.g. inside a custom scroll container — use onScroll:

<AlgunaCheckout url={session.url} onScroll={(deltaY) => myScroller.scrollBy(0, deltaY)} />

It mirrors onResize.

Sessions & errors

  • Sessions expire (expires_in_seconds, default 24h, max 7d). Create one per checkout attempt.
  • onError codes: session_expired (mint a fresh session and re-mount) and load_failed (retry / support).

Security model

The checkout runs in an iframe from Alguna's origin, so your page never touches sensitive data or the checkout's DOM:

  • Session tokens are short-lived and single-purpose. Each is minted by your server (with your secret key) for one checkout, scoped to that session, and expires (expires_in_seconds). The browser only ever holds this scoped token, never your API key.
  • Card data never enters your DOM. It's captured inside Stripe's iframe (nested within the checkout iframe), so your site stays in PCI SAQ-A scope.
  • Your CSS can't reach the checkout, and vice versa. The iframe is a hard boundary — style only through appearance.
  • Origin allowlisting. Orgs can restrict which sites may embed their checkout (dashboard setting); the embed refuses to render on a disallowed origin. The SDK passes your page's origin so the checkout can scope every postMessage to it.

版本与发布记录

@alguna/checkout-sdk 共发布 13 个版本,首次发布于 2026/08/06;过去 12 个月发布了 13 个版本。

版本发布日期距今
1.0.0latest2026/10/1622 天前
0.8.12026/09/221 个月前
0.8.02026/09/211 个月前
0.7.02026/09/161 个月前
0.6.02026/09/151 个月前
0.5.02026/09/022 个月前

关于 @alguna/checkout-sdk 的常见问题

@alguna/checkout-sdk 是什么?

Embed Alguna Checkout in your product — a themeable, isolated checkout component

如何安装 @alguna/checkout-sdk?

在项目目录运行 npm install @alguna/checkout-sdk,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react-dom(>=18)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@alguna/checkout-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@alguna/checkout-sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@alguna/checkout-sdk 可以商用吗?

@alguna/checkout-sdk 使用 UNLICENSED 许可。作者声明为 UNLICENSED,即不授予公开使用许可(与公共领域的 Unlicense 不同)。使用前需获得作者授权。以上为概括,不构成法律意见,请以许可原文为准。

@alguna/checkout-sdk 的下载量有多少?

根据 npm 官方下载统计,@alguna/checkout-sdk 在 2026/10/06 – 2026/11/04 这 30 天内被下载 3,209 次,日均约 107 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@alguna/checkout-sdk 还在维护吗?

最新版本 1.0.0 发布于 2026/10/16(22 天前);至今共发布 13 个版本,其中过去 12 个月发布了 13 个;首次发布于 2026/08/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。