@radonsdk/payments24 providersOne charge() across 24 processors.
Global, African, and crypto — Stripe to Flutterwave to Coinbase Commerce. Provider quirks (auth schemes, minor vs major units, wildly different webhooks) are absorbed inside each adapter and never leak into your code.
import { RadonPayments, money } from "@radonsdk/payments";
const payments = new RadonPayments({
providers: { stripe: {} },
defaultProvider: "stripe",
});
const charge = await payments.charge({
amount: money(1999, "USD"),
customer: { email: "ada@example.com" },
});24 providers, one API
charge, refund, subscriptions, and webhooks — every provider implements the same typed shape.
Money done right
Amounts are integer minor units plus an ISO-4217 currency. Zero-decimal (JPY) and three-decimal (KWD) currencies are handled for you.
Normalized webhooks
Every provider's events collapse into one schema. One handler — payments.webhooks.handle(req) — verifies the signature and normalizes.
Provider-agnostic coupons
A built-in coupon engine: validate, apply, and redeem — percentage or fixed, currency-aware, usage-limited.
Hooks & middleware
Composable lifecycle hooks and around-style middleware, bundled into shareable plugins (fraud checks, analytics, tax).
Escape hatch
result.raw always holds the untouched provider response, and BaseProvider lets you register your own processor.
5 free, 19 on Pro — same call for every one.
A small, typed surface.
payments.charge({ amount, customer }): Promise<ChargeResult>One-time charge; returns a normalized result with status and redirectUrl.
payments.refund({ chargeId, amount? }): Promise<RefundResult>Full or partial refund on any provider.
payments.subscriptions.create(input): Promise<SubscriptionResult>Create, cancel, and retrieve recurring subscriptions.
payments.webhooks.handle(request): Promise<NormalizedEvent>Verify + normalize a provider webhook into one event schema.
payments.coupons.apply(code, amount): Promise<DiscountResult>Validate and apply a coupon to an amount before charging.
money(1999, "USD")Build a Money value in integer minor units — $19.99 here.
const event = await payments.webhooks.handle({
body: req.rawBody, // exact bytes, not parsed JSON
headers: req.headers,
});
if (event.type === "charge.succeeded") {
await fulfill(event.data.reference);
}Minor units, and raw webhook bytes
money(1999, "USD") is $19.99 — pass a float and it throws; use majorMoney(19.99, "USD"). And webhook signatures are computed over the exact bytes received — pass req.rawBody, never parsed-and-re-serialized JSON, or verification fails.