JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 59
  • Score
    100M100P100Q77397F
  • License MIT

Package Exports

  • @tjoc/payments
  • @tjoc/payments/dist/index.js
  • @tjoc/payments/dist/index.mjs

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@tjoc/payments) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Payment Integration Package

A comprehensive payment integration system that intelligently routes payments between Stripe and Paystack based on geographical context, with built-in retry logic and fallback mechanisms.

Features

  • Intelligent Provider Routing: Automatically selects the best payment provider based on customer location and currency
  • Multi-Provider Support: Seamlessly integrates with both Stripe and Paystack
  • Geographic Detection: Detects customer country from IP address or browser locale
  • Retry Logic: Built-in retry mechanisms with exponential backoff
  • Fallback Support: Automatic fallback to secondary provider if primary fails
  • Webhook Handling: Unified webhook processing for both providers
  • TypeScript Support: Fully typed interfaces and comprehensive error handling

Installation

# Using pnpm (recommended)
pnpm add @tjoc/payments

# Using npm
npm install @tjoc/payments

# Using yarn
yarn add @tjoc/payments

Quick Start

Basic Setup

import { 
  PaymentRouter, 
  StripeProvider, 
  PaystackProvider,
  CountryDetectionService 
} from '@tjoc/payments';

// Initialize providers
const stripeProvider = new StripeProvider({
  apiKey: process.env.STRIPE_SECRET_KEY!,
});

const paystackProvider = new PaystackProvider({
  secretKey: process.env.PAYSTACK_SECRET_KEY!,
  publicKey: process.env.PAYSTACK_PUBLIC_KEY!,
});

// Create payment router
const paymentRouter = new PaymentRouter({
  providers: {
    primary: stripeProvider,
    fallback: paystackProvider
  },
  routing: {
    paystackCountries: ['NG', 'GH', 'ZA', 'KE'], // Nigeria, Ghana, South Africa, Kenya
    defaultProvider: 'stripe'
  },
  retryConfig: {
    maxRetries: 2,
    retryDelay: 1000
  }
});

Creating a Payment

// Create a payment with automatic provider selection
const transaction = await paymentRouter.createPayment({
  amount: 100.00,
  currency: 'USD',
  customerId: 'cust_123',
  description: 'Product purchase'
}, {
  country: 'US', // Optional: helps with provider selection
  currency: 'USD'
});

console.log('Payment created:', transaction.id);
console.log('Provider used:', transaction.provider);

Geographic Detection

// Detect country from IP address
const geoInfo = await CountryDetectionService.detectCountryFromIP('192.168.1.1');
if (geoInfo) {
  console.log('Country:', geoInfo.country);
  console.log('Currency:', geoInfo.currency);
}

// Get country information and preferred provider
const countryInfo = CountryDetectionService.getCountryInfo('NG');
console.log('Preferred provider for Nigeria:', countryInfo.preferredProvider); // 'paystack'

// Check if country supports Paystack
const supportsPaystack = CountryDetectionService.isPaystackCountry('NG');
console.log('Nigeria supports Paystack:', supportsPaystack); // true

API Reference

PaymentRouter

The main class that handles intelligent routing between payment providers.

Constructor

interface PaymentRouterConfig {
  providers: {
    primary: PaymentProvider;
    fallback?: PaymentProvider;
  };
  routing: {
    paystackCountries: string[]; // Country codes that should use Paystack
    defaultProvider: 'stripe' | 'paystack';
  };
  retryConfig?: {
    maxRetries: number;
    retryDelay: number;
  };
}

Methods

Payment Operations
// Create a new payment
createPay ment(options: CreatePaymentOptions, context?: PaymentContext): Promise<Transaction>

// Confirm a payment
confirmPayment(paymentId: string, context?: PaymentContext): Promise<Transaction>

// Cancel a payment
cancelPayment(paymentId: string, context?: PaymentContext): Promise<Transaction>

// Get payment details
getPayment(paymentId: string, context?: PaymentContext): Promise<Transaction>
Customer Operations
// Create a customer
createCustomer(data: Partial<Customer>, context?: PaymentContext): Promise<Customer>

// Update customer
updateCustomer(customerId: string, data: Partial<Customer>, context?: PaymentContext): Promise<Customer>

// Get customer
getCustomer(customerId: string, context?: PaymentContext): Promise<Customer>

// Delete customer
deleteCustomer(customerId: string, context?: PaymentContext): Promise<boolean>
Subscription Operations
// Create subscription
createSubscription(options: CreateSubscriptionOptions, context?: PaymentContext): Promise<Subscription>

// Update subscription
updateSubscription(subscriptionId: string, data: Partial<Subscription>, context?: PaymentContext): Promise<Subscription>

// Cancel subscription
cancelSubscription(subscriptionId: string, context?: PaymentContext): Promise<Subscription>

// Get subscription
getSubscription(subscriptionId: string, context?: PaymentContext): Promise<Subscription>

// List customer subscriptions
listCustomerSubscriptions(customerId: string, context?: PaymentContext): Promise<Subscription[]>

CountryDetectionService

Static service for geographic detection and provider recommendations.

Methods

// Detect country from IP address
static detectCountryFromIP(ipAddress?: string): Promise<GeoLocation | null>

// Detect country from browser
static detectCountryFromBrowser(): GeoLocation | null

// Get currency for country
static getCurrencyForCountry(countryCode: string): string

// Get preferred provider for country
static getPreferredProvider(countryCode: string): 'stripe' | 'paystack'

// Check if country supports Paystack
static isPaystackCountry(countryCode: string): boolean

// Get comprehensive country information
static getCountryInfo(countryCode: string): CountryInfo

Provider Classes

StripeProvider

interface StripeConfig {
  apiKey: string;
  webhookHandlers?: WebhookHandlerConfig;
}

const stripe = new StripeProvider(config);

PaystackProvider

interface PaystackConfig {
  secretKey: string;
  publicKey: string;
  webhookSecret?: string;
  testMode?: boolean;
}

const paystack = new PaystackProvider(config);

Routing Logic

The payment router uses the following logic to select providers:

  1. Country-based routing: If the customer's country is in the paystackCountries list, Paystack is preferred
  2. Currency-based routing: If the currency is NGN (Nigerian Naira), Paystack is preferred
  3. Default provider: Falls back to the configured default provider
  4. Retry logic: If the primary provider fails, retries with exponential backoff
  5. Fallback provider: If all retries fail, attempts with the fallback provider

Supported Countries for Paystack

  • NG - Nigeria
  • GH - Ghana
  • ZA - South Africa
  • KE - Kenya

Webhook Handling

Setting up Webhooks

// Stripe webhooks
const stripeProvider = new StripeProvider({
  apiKey: process.env.STRIPE_SECRET_KEY!,
  webhookHandlers: {
    'payment_intent.succeeded': async (event) => {
      console.log('Stripe payment succeeded:', event.data.object);
    },
    'payment_intent.payment_failed': async (event) => {
      console.log('Stripe payment failed:', event.data.object);
    }
  }
});

// Paystack webhooks
const paystackProvider = new PaystackProvider({
  secretKey: process.env.PAYSTACK_SECRET_KEY!,
  publicKey: process.env.PAYSTACK_PUBLIC_KEY!,
  webhookSecret: process.env.PAYSTACK_WEBHOOK_SECRET
});

Processing Webhooks

// In your webhook endpoint
app.post('/webhooks/:provider', async (req, res) => {
  const provider = req.params.provider as 'stripe' | 'paystack';
  const signature = req.headers['stripe-signature'] || req.headers['x-paystack-signature'];
  
  try {
    await paymentRouter.handleWebhook(provider, req.body, signature);
    res.json({ success: true });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

Error Handling

The package includes comprehensive error handling:

import { PaymentProviderError, ConfigurationError } from '@your-org/payments';

try {
  const transaction = await paymentRouter.createPayment(options);
} catch (error) {
  if (error instanceof PaymentProviderError) {
    console.error('Payment provider error:', error.code, error.message);
  } else if (error instanceof ConfigurationError) {
    console.error('Configuration error:', error.message);
  } else {
    console.error('Unknown error:', error);
  }
}

Environment Variables

# Stripe
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Paystack
PAYSTACK_SECRET_KEY=sk_test_...
PAYSTACK_PUBLIC_KEY=pk_test_...

# Environment
NODE_ENV=development

Examples

See the usage examples for comprehensive implementation examples including:

  • Express.js integration
  • Next.js API routes
  • React hooks for frontend
  • Webhook handling
  • Error management

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE file for details.