@quickpay/node
Server-side Node.js SDK for creating checkout sessions, managing subscriptions, and handling webhooks.
Installation
npm install @quickpay/nodeInitialization
Initialize the SDK with your server key. Never expose this key in client-side code.
import { QuickPay } from '@quickpay/node';
const qp = new QuickPay('sk_live_your_server_key');Security
Your server key (sk_live_...) grants full API access. Store it in environment variables and never commit it to source control.
Checkout Sessions
checkoutSessions.create()
Create a new checkout session. Returns a session object with an ID and client secret.
const session = await qp.checkoutSessions.create({
amount: 99.99,
currency: 'USD',
mode: 'embedded', // 'embedded' | 'hosted'
paymentType: 'oneTime', // 'oneTime' | 'subscription'
successUrl: 'https://yoursite.com/success?session_id={CHECKOUT_SESSION_ID}',
cancelUrl: 'https://yoursite.com/cancel',
customer: {
email: '[email protected]',
name: 'Jane Doe',
},
lineItems: [
{ name: 'Pro Plan', quantity: 1, unitAmount: 99.99 },
],
metadata: {
orderId: 'order_12345',
},
});
// session.id — 'cs_live_abc123'
// session.clientSecret — 'cs_live_abc123_secret_xyz789'
// session.url — hosted checkout URL (only for mode: 'hosted'){CHECKOUT_SESSION_ID} in successUrl or cancelUrl is replaced with the session id. To collect an invoice you already issued, pass invoiceId or invoiceReference instead of an amount and line items:
const session = await qp.checkoutSessions.create({
invoiceReference: 'INV-7F3K2Q', // or invoiceId: 7731 — not both
mode: 'hosted',
paymentType: 'oneTime',
successUrl: 'https://yoursite.com/paid?session_id={CHECKOUT_SESSION_ID}',
});
// Amount and currency come from the invoice. Calling this again while that
// session is still open returns the same session.checkoutSessions.retrieve()
Retrieve an existing checkout session by its ID.
const session = await qp.checkoutSessions.retrieve('cs_live_abc123');
console.log(session.status); // 'open' | 'complete' | 'expired'
console.log(session.paymentStatus); // 'unpaid' | 'paid' | 'no_payment_required'
console.log(session.amountTotal); // 99.99Subscriptions
List subscriptions
const subscriptions = await qp.subscriptions.list({
customerId: 'cus_abc123',
status: 'active', // 'active' | 'paused' | 'cancelled' | 'past_due'
limit: 10,
});
for (const sub of subscriptions.data) {
console.log(sub.id, sub.plan.name, sub.currentPeriodEnd);
}Cancel a subscription
const cancelled = await qp.subscriptions.cancel('sub_abc123', {
cancelAtPeriodEnd: true, // Let the subscription run until the end of the billing period
});Pause a subscription
const paused = await qp.subscriptions.pause('sub_abc123', {
resumeAt: '2025-02-01T00:00:00Z', // Optional: auto-resume date
});Resume a subscription
const resumed = await qp.subscriptions.resume('sub_abc123');Webhooks
webhooks.constructEvent()
Parse and verify an incoming webhook payload. Throws an error if the signature is invalid.
import express from 'express';
import { QuickPay } from '@quickpay/node';
const app = express();
const qp = new QuickPay('sk_live_your_server_key');
// Use raw body for signature verification
app.post('/webhooks/quickpay', express.raw({ type: 'application/json' }), (req, res) => {
let event;
try {
event = qp.webhooks.constructEvent(
req.body, // Raw request body
req.headers['x-webhook-signature'], // Signature header
'whsec_your_webhook_secret' // Your webhook signing secret
);
} catch (err) {
console.error('Webhook signature verification failed:', err.message);
return res.status(400).send('Invalid signature');
}
// Handle the event
switch (event.type) {
case 'checkout.session.completed':
const session = event.data;
// Fulfill the order
break;
case 'payment.succeeded':
// Record the payment
break;
case 'subscription.renewed':
// Extend access
break;
case 'payment.failed':
// Notify the customer
break;
}
res.json({ received: true });
});webhooks.verifySignature()
Verify a webhook signature without parsing the payload. Returns a boolean.
const isValid = qp.webhooks.verifySignature(
rawBody,
signatureHeader,
'whsec_your_webhook_secret'
);
if (!isValid) {
throw new Error('Invalid webhook signature');
}Tip
Always use the raw request body (not a parsed JSON object) for signature verification. If you're using Express, apply express.raw() middleware to your webhook route.
Error Handling
import { QuickPayError } from '@quickpay/node';
try {
const session = await qp.checkoutSessions.create({ /* ... */ });
} catch (err) {
if (err instanceof QuickPayError) {
console.error(err.type); // 'invalid_request' | 'authentication' | 'rate_limit'
console.error(err.code); // 'amount_too_small'
console.error(err.message); // Human-readable message
console.error(err.statusCode); // HTTP status code
}
}