@vonpay/checkout-node
v2.6.1
Published
Von Payments Checkout SDK for Node.js
Readme
@vonpay/checkout-node
Node.js / TypeScript SDK for the Von Payments Checkout API. Create hosted checkout sessions, verify webhook signatures, and validate signed return redirects.
Install
npm install @vonpay/checkout-nodeRequires: Node 20+. ESM only. Zero runtime dependencies.
Quick start
import { VonPayCheckout, VonPayError } from "@vonpay/checkout-node";
const vonpay = new VonPayCheckout("vp_sk_test_...");
const session = await vonpay.sessions.create({
amount: 1499,
currency: "USD",
country: "US",
successUrl: "https://example.com/order/123/confirm",
});
console.log(session.checkoutUrl);
// https://checkout.vonpay.com/checkout?session=vp_cs_test_...Discrete-lifecycle API
The paymentIntents, refunds, tokens, and capabilities namespaces give server-side control over payment intents, alongside the existing hosted-checkout sessions flow.
// Create a payment intent (auth + capture)
const intent = await vonpay.paymentIntents.create(
{
amount: 1499,
currency: "usd",
captureMethod: "automatic",
metadata: { orderId: "ord_42" },
},
{ idempotencyKey: "ord_42-charge-1" },
);
console.log(intent.id, intent.status); // "vpi_live_…", "succeeded"
// Auth-only + later capture (fulfillment-on-ship)
const auth = await vonpay.paymentIntents.create({ amount: 1499, currency: "usd", captureMethod: "manual" });
await vonpay.paymentIntents.capture(auth.id, { amountToCapture: 1499 });
// Refund a captured intent (partial or full)
const refund = await vonpay.refunds.create({ paymentIntent: intent.id, amount: 500 });
// Create a reusable token for save-card / MIT flows
const token = await vonpay.tokens.create({ buyerId: "buyer_42", setupForFutureUse: "off_session" });
// Read the merchant's processor capability matrix before invoking optional ops
const caps = await vonpay.capabilities.get();
if (caps.supportedOperations.partialRefund) {
// partial refunds supported — safe to offer partial-refund UI
}The SDK presents a camelCase API and translates to the server's snake_case wire format automatically.
Webhooks API — read endpoints
webhookSubscriptions and webhookEvents give read access to the merchant's registered endpoints and stored event records. Available in 0.8.0+; requires a secret key (vp_sk_*).
// List a merchant's webhook subscriptions (Stripe-style cursor pagination)
const page = await vonpay.webhookSubscriptions.list({ limit: 25 });
for (const sub of page.data) {
console.log(sub.id, sub.enabledEvents, sub.status);
}
if (page.hasMore) {
const next = await vonpay.webhookSubscriptions.list({
limit: 25,
startingAfter: page.data[page.data.length - 1].id,
});
}
// Retrieve a single subscription by id
const sub = await vonpay.webhookSubscriptions.retrieve("whsub_test_abc");
// Retrieve a stored webhook event record
const evt = await vonpay.webhookEvents.retrieve("evt_test_abc");
console.log(evt.type, evt.payload);Write endpoints (create / update / delete / rotate-signing-secret / send-test-event) are not yet exposed in this SDK.
Features
- Typed session / webhook / error objects — full
CheckoutSession,SessionStatus,WebhookEvent,WebhookSubscription,WebhookEventRecord,VonPayError, discriminated-unionErrorCode. - Webhook verification —
webhooks.constructEvent(rawBody, signatureHeader, signingSecret)parses thex-vonpay-signature: t=<unix>,v1=<hex>header, verifies HMAC-SHA256 over${t}.${rawBody}keyed by your per-endpoint signing secret (whsec_…), and enforces the freshness window (≤5 min old / ≤30 sec future). Accepts multiplev1=entries for zero-downtime secret rotation. - Return confirmation —
client.sessions.confirmReturn(params, sessionSecret)verifies the signature and confirms server-side that the payment succeeded, returning{ paid, signatureValid, status, reason }. Use this, and branch onpaid. ⛔verifyReturnSignature()is DEPRECATED and STOPS WORKING on or after 2026-10-13 — the redirect stops carryingsig/status/amount/currency/transaction_idat all, so there will be nothing to verify and it will refuse every return. Migrate before that date. (It was also never usable as merchant-side proof: the signature uses a platform-wide secret no merchant was ever issued.) It proves a message is AUTHENTIC, and a declined payment is signed just as validly, so atruefrom it was never proof of payment either. ⚠️reason === "still_pending"means the charge is in flight (the ordinary 3-D Secure case) — show a neutral "confirming your payment", never a failure. ⚠️paid: truestill does not mean safe to fulfil: record which session IDs you have already fulfilled, and prefer fulfilling from thecharge.succeededwebhook. ⚠️ Notsession.succeeded— that event is emitted internally but is not subscribable: it is absent from the merchant subscription catalog, which accepts an unknown event key, stores nothing and returns success. An endpoint subscribed to it receives nothing, forever, with no error raised at any layer.charge.succeededis the fulfilment event. - Auto-retry — exponential backoff on 429 / 5xx with
Retry-Afterheader support. - Request ID tracing — every response includes
X-Request-Idfor support tickets. - Rate-limit info — parsed from response headers into
VonPayError.rateLimit.
Documentation
License
MIT
