Skip to content

Repository files navigation

PayKit

PayKit Banner

One API for Stripe, Razorpay, PayPal, and 25+ payment providers

npm version License: MIT TypeScript Tests

Features β€’ Quick Start β€’ Documentation β€’ Examples β€’ Adapters


Why PayKit?

Problem: Payment providers have different APIs, data formats, and integration patterns. Switching providers or supporting multiple regions means rewriting your entire payment stack.

Solution: PayKit provides a single, type-safe API that works across all major payment providers. Write your integration once, swap providers instantly.

// Same code works for Stripe, Razorpay, PayPal, and 25+ providers
const charge = await paykit.charges.create({
  amount: 5000,
  currency: 'usd',
  metadata: { orderId: 'order_123' }
});

Switch providers in 2 lines:

- import { StripeAdapter } from '@squaredr/paykit/stripe';
- const paykit = new PayKit({ adapter: new StripeAdapter({ secretKey }) });
+ import { RazorpayAdapter } from '@squaredr/paykit/razorpay';
+ const paykit = new PayKit({ adapter: new RazorpayAdapter({ keyId, keySecret }) });

Your business logic stays the same. No rewrites. No vendor lock-in.


✨ Features

🎯 Unified API

One interface for charges, refunds, customers, subscriptions, webhooks, and payment methods across all providers

πŸ”’ Type-Safe

Full TypeScript coverage with normalized types. IntelliSense works everywhere, catching errors at compile-time

πŸ”Œ Zero Lock-In

Swap providers without changing business logic. Test locally with mock adapter, deploy with real providers

πŸͺ Normalized Webhooks

Unified webhook events regardless of provider. Write one handler for all payment events

🌍 Multi-Provider Routing

Route payments by currency, region, or custom rules. Accept INR via Razorpay, USD via Stripe automatically

βš›οΈ React Components

Drop-in <CheckoutForm>, <CardInput>, and hooks. Works with Stripe Elements, Razorpay Checkout, PayPal buttons

Plus: Tree-shakeable exports β€’ Official SDKs under the hood β€’ Comprehensive error normalization β€’ Health checks β€’ Test mode support β€’ Edge runtime compatible


πŸ“¦ Packages

Package Description Size npm
@squaredr/paykit Core SDK + all adapters (Stripe, Razorpay, PayPal) 26 KB npm
@squaredr/paykit-react React components & hooks 7 KB npm
@squaredr/paykit-js Vanilla JS/TS frontend SDK (headless) 4 KB npm

πŸš€ Quick Start

Installation

# Install core SDK
npm install @squaredr/paykit

# Install provider SDKs (peer dependencies - choose what you need)
npm install stripe              # For Stripe
npm install razorpay            # For Razorpay
npm install @paypal/paypal-server-sdk  # For PayPal

# For React
npm install @squaredr/paykit-react

Backend: Create a Payment

import { PayKit } from '@squaredr/paykit';
import { StripeAdapter } from '@squaredr/paykit/stripe';

// Initialize with your provider
const paykit = new PayKit({
  adapter: new StripeAdapter({
    secretKey: process.env.STRIPE_SECRET_KEY!
  })
});

// Create a charge
const charge = await paykit.charges.create({
  amount: 5000,        // $50.00 (amounts in smallest unit)
  currency: 'usd',
  description: 'Premium subscription',
  metadata: {
    userId: 'user_123',
    plan: 'premium'
  }
});

// Send clientSecret to frontend
res.json({ clientSecret: charge.clientSecret });

Frontend: Collect Payment (React)

import { PayKitProvider, CheckoutForm } from '@squaredr/paykit-react';
import { StripeClientAdapter } from '@squaredr/paykit/stripe/client';

function App() {
  const [clientSecret, setClientSecret] = useState('');

  return (
    <PayKitProvider
      clientAdapter={new StripeClientAdapter(process.env.NEXT_PUBLIC_STRIPE_KEY!)}
    >
      <CheckoutForm
        clientSecret={clientSecret}
        onSuccess={(result) => {
          console.log('Payment successful!', result);
          // Show success message, redirect to thank you page
        }}
        onError={(error) => {
          console.error('Payment failed:', error.message);
          // Show error message
        }}
        appearance={{
          theme: 'stripe',
          variables: { colorPrimary: '#0070f3' }
        }}
      />
    </PayKitProvider>
  );
}

Handle Webhooks

import express from 'express';

app.post('/webhooks', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['stripe-signature'] as string;

  // Verify and parse webhook
  const event = paykit.webhooks.construct({
    payload: req.body,
    signature,
    secret: process.env.STRIPE_WEBHOOK_SECRET!
  });

  // Handle unified events (same for all providers!)
  switch (event.type) {
    case 'charge.succeeded':
      await fulfillOrder(event.data.id);
      break;
    case 'charge.failed':
      await handleFailure(event.data.id);
      break;
    case 'subscription.canceled':
      await cancelAccess(event.data.customer);
      break;
  }

  res.json({ received: true });
});

πŸ”Œ Supported Providers

Free & Open Source (MIT License)

Provider Status Subpath Import Features
Stripe βœ… Stable @squaredr/paykit/stripe Charges, Refunds, Customers, Subscriptions, Payment Methods, Webhooks
Razorpay βœ… Stable @squaredr/paykit/razorpay Charges, Refunds, Customers, Subscriptions, Payment Methods, Webhooks
PayPal βœ… Stable @squaredr/paykit/paypal Charges, Refunds, Subscriptions, Payment Methods (Vault), Webhooks
Mock βœ… Stable @squaredr/paykit/testing Full API simulation for local development

Frontend Adapters:

  • @squaredr/paykit/stripe/client - Stripe Elements integration
  • @squaredr/paykit/razorpay/client - Razorpay Checkout integration

Coming Soon (Paid Adapter Bundles)

Additional providers available as one-time purchase adapter bundles:

Bundle Price Providers Included
Individual $19 Any single provider
India Pack $49 Cashfree, PhonePe, Paytm, BillDesk
Global Pack $79 Square, Adyen, Mollie, Braintree, Authorize.net
All Access $149 All current + future adapters (lifetime)

View Pricing & Roadmap β†’


πŸ’‘ Examples

Multi-Provider Routing

Route payments intelligently based on currency or region:

import { PaymentRouter } from '@squaredr/paykit';
import { StripeAdapter } from '@squaredr/paykit/stripe';
import { RazorpayAdapter } from '@squaredr/paykit/razorpay';

const router = new PaymentRouter({
  adapters: [
    new StripeAdapter({ secretKey: process.env.STRIPE_SECRET_KEY! }),
    new RazorpayAdapter({
      keyId: process.env.RAZORPAY_KEY_ID!,
      keySecret: process.env.RAZORPAY_KEY_SECRET!
    })
  ],
  rules: [
    { currency: 'inr', provider: 'razorpay' },  // INR β†’ Razorpay
    { currency: 'usd', provider: 'stripe' },     // USD β†’ Stripe
    { default: 'stripe' }                        // Fallback β†’ Stripe
  ]
});

// Automatically routes to the right provider
const charge = await router.createCharge({
  amount: 50000,
  currency: 'inr'  // Will use Razorpay
});

Subscriptions

// Create a subscription
const subscription = await paykit.subscriptions.create({
  customer: 'cus_123',
  amount: 2999,           // $29.99/month
  currency: 'usd',
  interval: 'month',
  intervalCount: 1
});

// Cancel subscription
await paykit.subscriptions.cancel(subscription.id);

// List customer subscriptions
const subs = await paykit.subscriptions.list({ customer: 'cus_123' });

Refunds

// Full refund
await paykit.refunds.create({
  chargeId: 'ch_123',
  reason: 'Customer requested'
});

// Partial refund
await paykit.refunds.create({
  chargeId: 'ch_123',
  amount: 2500,  // $25.00
  reason: 'Partial order cancellation'
});

Error Handling

import { PaymentError } from '@squaredr/paykit';

try {
  await paykit.charges.create({ amount, currency });
} catch (error) {
  if (error instanceof PaymentError) {
    switch (error.code) {
      case 'card_declined':
        // Show user-friendly message
        break;
      case 'insufficient_funds':
        // Suggest alternative payment method
        break;
      case 'authentication_required':
        // Trigger 3D Secure flow
        break;
      default:
        // Generic error handling
    }
  }
}

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        Your Application Layer            β”‚
β”‚   (Express, Next.js, Fastify, etc.)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  v
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      @squaredr/paykit (Core)             β”‚
β”‚  β€’ PayKit Client                         β”‚
β”‚  β€’ Unified Types & Interfaces            β”‚
β”‚  β€’ Payment Router                        β”‚
β”‚  β€’ Error Normalization                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       v                     v              v
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stripe      β”‚      β”‚ Razorpay    β”‚  β”‚ PayPal       β”‚
β”‚ Adapter     β”‚      β”‚ Adapter     β”‚  β”‚ Adapter      β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                    β”‚                 β”‚
       v                    v                 v
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ stripe      β”‚      β”‚ razorpay    β”‚  β”‚ @paypal/paypal-      β”‚
β”‚ (npm)       β”‚      β”‚ (npm)       β”‚  β”‚ server-sdk (npm)     β”‚
β”‚ Peer Dep    β”‚      β”‚ Peer Dep    β”‚  β”‚ Peer Dep             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How it works:

  1. Your app uses PayKit's unified API
  2. PayKit routes to the appropriate adapter
  3. Adapter translates to provider's native SDK
  4. Provider SDK makes actual API calls
  5. Response is normalized back to PayKit types

Benefits:

  • βœ… Use official SDKs under the hood (not reinventing the wheel)
  • βœ… Swap providers without code changes
  • βœ… Test locally with mock adapter
  • βœ… Tree-shake unused adapters (only bundle what you use)

πŸ§ͺ Development

Prerequisites

  • Node.js >= 20.0.0
  • pnpm >= 9.15.3 (recommended) or npm >= 11.0.0

Setup

git clone https://github.com/SquaredR98/paykit.git
cd paykit
pnpm install
pnpm run build
pnpm test

Project Structure

paykit/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ core/          # @squaredr/paykit (SDK + all adapters)
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”‚   β”œβ”€β”€ adapters/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ stripe/      # Stripe adapter + client
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ razorpay/    # Razorpay adapter + client
β”‚   β”‚   β”‚   β”‚   └── paypal/      # PayPal adapter
β”‚   β”‚   β”‚   β”œβ”€β”€ types/           # Unified types
β”‚   β”‚   β”‚   └── index.ts         # Main exports
β”‚   β”‚   └── package.json
β”‚   β”œβ”€β”€ sdk-js/        # @squaredr/paykit-js (frontend SDK)
β”‚   └── react/         # @squaredr/paykit-react (React components)
β”œβ”€β”€ website/           # Documentation site (Fumadocs)
β”œβ”€β”€ turbo.json
└── package.json

Commands

pnpm run build          # Build all packages
pnpm test               # Run all tests (252 passing)
pnpm run test:watch     # Watch mode
pnpm run typecheck      # Type check all packages
pnpm run lint           # Lint with Biome
pnpm run lint:fix       # Auto-fix linting issues
pnpm run clean          # Clean build artifacts

Testing

All packages use Vitest.

# Run all tests
pnpm test

# Test specific package
pnpm test --filter @squaredr/paykit

# Watch mode
pnpm test:watch

# Coverage
pnpm test --coverage

πŸ“š Documentation

Full documentation: squaredr.tech/products/paykit/docs

Getting Started

Provider Guides

Advanced

API Reference


🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Areas We Need Help

  • πŸ› Bug fixes and issue reports
  • πŸ“ Documentation improvements
  • ✨ Feature requests and RFC discussions
  • πŸ§ͺ Test coverage expansion
  • 🌍 Internationalization

πŸ“„ License

MIT License - see LICENSE for details.

What's Free?

βœ… Core SDK (@squaredr/paykit) βœ… All included adapters (Stripe, Razorpay, PayPal) βœ… React components (@squaredr/paykit-react) βœ… JS SDK (@squaredr/paykit-js) βœ… Mock/testing adapter βœ… Full source code βœ… Commercial use allowed βœ… No attribution required

What's Paid?

Additional provider adapters (Square, Adyen, Cashfree, etc.) are available as one-time purchase adapter bundles. No subscriptions, no vendor lock-in.

View Pricing β†’


πŸ’¬ Support


🌟 Show Your Support

If PayKit saves you time and effort, please consider:

  • ⭐ Starring the repo
  • 🐦 Sharing on Twitter
  • πŸ“ Writing a blog post about your experience
  • πŸ’¬ Joining our community discussions

πŸ—ΊοΈ Roadmap

Q1 2027

  • βœ… Core SDK with Stripe & Razorpay
  • βœ… React components
  • βœ… PayPal adapter (official SDK migration)
  • 🚧 Documentation site
  • πŸ“… Square adapter (paid)
  • πŸ“… Adyen adapter (paid)

Q2 2027

  • πŸ“… India Pack (Cashfree, PhonePe, Paytm)
  • πŸ“… Global Pack (Mollie, Braintree, Authorize.net)
  • πŸ“… Advanced routing rules
  • πŸ“… Payment analytics dashboard

Q3 2027

  • πŸ“… Mobile SDKs (React Native, Flutter)
  • πŸ“… Serverless framework plugins
  • πŸ“… CLI for provider migration

Full Roadmap β†’


Built with ❀️ by SquaredR

Website β€’ Documentation β€’ GitHub β€’ npm

Releases

Packages

Contributors

Languages