Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

awesome-node-checkout

npm version license

A framework-agnostic payment checkout library for Node.js, written in TypeScript.
Drop-in payment orchestration for Express, NestJS, Fastify and any other Node.js framework — connect any payment provider through a single interface.

Inspired by awesome-node-auth. Same philosophy: no framework lock-in, no DB lock-in, implement one interface and you're done.


Installation

npm install awesome-node-checkout

Quick Start

import { CheckoutConfigurator, PayPalProvider, NexiProvider, SatispayProvider } from 'awesome-node-checkout';
import * as fs from 'fs';

const checkout = new CheckoutConfigurator();

checkout
  .registerProvider(new PayPalProvider({
    clientId: process.env.PAYPAL_CLIENT_ID!,
    clientSecret: process.env.PAYPAL_CLIENT_SECRET!,
    environment: 'sandbox',
  }))
  .registerProvider(new NexiProvider({
    merchantId: process.env.NEXI_MERCHANT_ID!,
    macKey: process.env.NEXI_MAC_KEY!,
    environment: 'sandbox',
  }))
  .registerProvider(new SatispayProvider({
    keyId: process.env.SATISPAY_KEY_ID!,
    privateKey: fs.readFileSync('private.pem', 'utf8'),
    environment: 'sandbox',
    serverUrl: 'https://myapp.com',
  }));

// Use directly — no HTTP framework needed
const result = await checkout.createPayment('paypal', {
  amount: 49.99,
  currency: 'EUR',
  description: 'Order #1234',
  returnUrl: 'https://myapp.com/payment/success',
  cancelUrl: 'https://myapp.com/payment/cancel',
  orderId: 'ORD-1234',
});

if (result.approvalUrl) {
  // redirect the user to result.approvalUrl
}

With Express adapter

import express from 'express';
import { createCheckoutRouter } from 'awesome-node-checkout/express';

const app = express();
app.use(express.json());

// Mounts all checkout routes under /checkout
app.use('/checkout', createCheckoutRouter(checkout));

app.listen(3000);

With Fastify (or any other framework)

Use the CheckoutConfigurator methods directly in your own routes:

fastify.post('/checkout/:provider', async (req, reply) => {
  const result = await checkout.createPayment(req.params.provider, req.body);
  reply.status(result.success ? 201 : 400).send(result);
});

fastify.post('/checkout/:provider/webhook', async (req, reply) => {
  const result = await checkout.handleWebhook(req.params.provider, req.body, req.headers);
  reply.send(result);
});

Routes (Express adapter)

Method Path Description
POST /:provider Create a payment
POST /:provider/execute Execute/capture a payment
GET /:provider/redirect Handle provider redirect callback
GET /:provider/:id Get payment details
POST /:provider/refund Refund a payment
POST /:provider/webhook Handle provider webhook

Payment Flows

Flow Providers Description
redirect PayPal, Nexi User is redirected to provider, returns with query params
webhook Satispay Provider calls a webhook URL after async confirmation
direct (future) Synchronous processing (card tokenization, etc.)

Events

checkout.events
  .on('payment.created',   ({ provider, paymentId }) => { /* ... */ })
  .on('payment.completed', ({ provider, paymentId }) => { /* ... */ })
  .on('payment.failed',    ({ provider, error })     => { /* ... */ })
  .on('payment.refunded',  ({ provider, paymentId }) => { /* ... */ })
  .on('webhook.received',  ({ provider, data })      => { /* ... */ });

Custom Transaction Store

By default, SatispayProvider uses an in-memory store to correlate webhooks with orders.
For multi-instance deployments, implement ITransactionStore:

import { ITransactionStore, TransactionData } from 'awesome-node-checkout';

class RedisTransactionStore implements ITransactionStore {
  async save(key: string, data: TransactionData): Promise<void> { /* ... */ }
  async get(key: string): Promise<TransactionData | null> { /* ... */ }
  async delete(key: string): Promise<void> { /* ... */ }
}

new SatispayProvider({
  keyId: '...',
  privateKey: '...',
  transactionStore: new RedisTransactionStore(),
});

Custom Provider

Extend BasePaymentProvider to add any payment provider:

import { BasePaymentProvider, PaymentRequest, PaymentResult } from 'awesome-node-checkout';

export class StripeProvider extends BasePaymentProvider {
  readonly name = 'stripe';
  readonly flow = 'redirect' as const;

  async createPayment(request: PaymentRequest): Promise<PaymentResult> {
    // ... call Stripe API
  }
  // ... implement other methods

  async handleRedirect(query: Record<string, any>): Promise<PaymentResult> {
    // ... handle Stripe redirect
  }
}

checkout.registerProvider(new StripeProvider({ secretKey: '...' }));

Built-in Providers

Provider Flow Notes
PayPal redirect Orders API v2
Nexi redirect eCommerce DispatcherServlet + MAC SHA-1
Satispay webhook Business API v1, RSA-SHA256 signature

License

MIT

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages