Skip to content

A unified PaymentPackage for NestJs apps, that handles simple configs of different gateways through one single config file

License

Notifications You must be signed in to change notification settings

CISCODE-MA/PaymentKit

@ciscode/PaymentKit

PaymentKit is a flexible payment orchestration package for NestJS, designed to integrate Stripe and PayPal payment gateways with minimal configuration. This package simplifies the payment lifecycle while exposing a unified API for payment creation, status retrieval, refunds, and webhook handling.

npm version License: MIT TypeScript


Features

  • Unified API: Easy-to-integrate payment flow for Stripe and PayPal
  • Next Action Handling: Automatic routing for client-side actions (client_secret for Stripe, redirect URL for PayPal)
  • Complete Webhook Support: Built-in webhook signature verification, event normalization, and routing for both gateways
  • Type-Safe: Full TypeScript support with strict mode enabled
  • Error Normalization: Gateway-specific errors mapped to unified error codes
  • Idempotency & Retry Safe: Built-in idempotency key support for safe retries
  • Hexagonal Architecture: Clean separation of concerns with ports & adapters pattern
  • Production Ready: 85%+ test coverage with comprehensive unit tests

Architecture

PaymentKit implements a Modular architecture:

  1. PaymentKitModule: The central module for registering and wiring all payment logic.
  2. PaymentsService: The service used by the host app to manage the payment lifecycle.
  3. Gateways:
    • StripeGateway: Handles Stripe-specific payment flow.
    • PaypalGateway: Handles PayPal-specific payment flow.
  4. Webhook Handler: Automatically handles incoming webhooks from Stripe/PayPal and triggers the appropriate actions based on gateway events.
  5. Error Handling: Maps gateway-specific errors to a unified error structure.
  6. Next Action: Facilitates the next step of the payment process (either redirect URL or client secret for Stripe).

Install & Run

  1. Install the package: In your NestJS application, install PaymentKit via npm:

    npm install @ciscode/paymentkit@latest
  2. Configure the payment module: Import the PaymentKitModule in your AppModule and pass the necessary configuration (PayPal/Stripe).

    import { Module } from '@nestjs/common';
    import { PaymentKitModule } from '@ciscode/paymentkit';
    
    @Module({
      imports: [
        PaymentKitModule.register({
          environment: process.env.PAYMENTKIT_ENVIRONMENT ?? 'sandbox',
          gateways: {
            paypal: { enabled: true },
            stripe: { enabled: true },
          },
          webhooks: { mode: 'internal' }, // Optionally set to 'external' if required
        }),
      ],
    })
    export class AppModule {}
  3. Create payment Use the PaymentsService to create a payment:

    import { Injectable } from '@nestjs/common';
    import { PaymentsService } from '@ciscode/paymentkit';
    import { CreatePaymentCommand } from '@ciscode/paymentkit';
    
    @Injectable()
    export class MyPaymentService {
      constructor(private readonly paymentsService: PaymentsService) {}
    
      async createPayment() {
        const command: CreatePaymentCommand = {
          gateway: 'paypal', // or 'stripe'
          amount: { amount: 1000, currency: 'USD' },
          metadata: { orderId: 'o_1' },
        };
    
        const result = await this.paymentsService.createPayment(command);
    
        if (result.nextAction?.type === 'redirect') {
          // Redirect the user to PayPal
          console.log('Redirect to PayPal: ', result.nextAction.url);
        } else if (result.nextAction?.type === 'client_secret') {
          // Process Stripe payment with client_secret
          console.log('Stripe client secret: ', result.nextAction.clientSecret);
        }
      }
    }
  4. Start the app Start your NestJS app as usual:

    npm run start

Environment Variables

Set the following environment variables for gateway configuration:

Required Variables

# Environment
PAYMENTKIT_ENVIRONMENT=sandbox  # 'sandbox' or 'production'
PAYMENTKIT_DEFAULT_CURRENCY=USD # Default currency code

# Stripe Configuration
PAYMENTKIT_STRIPE_ENABLED=true
PAYMENTKIT_STRIPE_SECRET_KEY=sk_test_...  # Use sk_live_... for production
PAYMENTKIT_STRIPE_WEBHOOK_SECRET=whsec_...  # For webhook signature verification

# PayPal Configuration
PAYMENTKIT_PAYPAL_ENABLED=true
PAYMENTKIT_PAYPAL_CLIENT_ID=your-paypal-client-id
PAYMENTKIT_PAYPAL_SECRET=your-paypal-secret
PAYMENTKIT_PAYPAL_WEBHOOK_ID=your-webhook-id  # For webhook verification

Optional Variables

# Webhook Configuration
PAYMENTKIT_WEBHOOK_MODE=internal  # 'internal' (default) or 'external'

# Stripe Advanced
PAYMENTKIT_STRIPE_API_VERSION=2023-10-16  # Specific API version

# PayPal Advanced
PAYMENTKIT_PAYPAL_WEBHOOK_VERIFICATION_URL=https://api-m.paypal.com/v1/notifications/verify-webhook-signature

Security Note: Never commit secrets to version control. Use environment variables or secret management services.


Usage Example

This example creates a payment via PayPal or Stripe.

const command = {
  gateway: 'paypal', // or 'stripe'
## API Reference

### Core Methods

#### `createPayment(command: CreatePaymentCommand): Promise<CreatePaymentResult>`

Creates a new payment through the specified gateway.

#### `getPaymentStatus(query: GetPaymentStatusQuery): Promise<GetPaymentStatusResult>`

Retrieves the current status of a payment.

#### `refundPayment(command: RefundPaymentCommand): Promise<RefundPaymentResult>`

Processes a full or partial refund for a completed payment.

See [examples](./examples) directory for detailed usage patterns.

---

## Security Best Practices

1. **Webhook Verification**: PaymentKit includes built-in HMAC signature verification for both Stripe and PayPal webhooks
2. **Secret Management**: Never hardcode API keys - use environment variables or secret managers
3. **HTTPS Only**: Always use HTTPS in production for webhook endpoints
4. **Idempotency Keys**: Use unique idempotency keys to prevent duplicate charges
5. **Error Handling**: Never expose raw gateway errors to end users - use the normalized error codes

---

## Troubleshooting

### Payment Creation Fails

**Problem**: `createPayment` returns an error

**Solutions**:
- Verify environment variables are correctly set
- Check gateway is enabled in configuration
- Ensure amount is in correct format (integer cents for Stripe, dollars for PayPal)
- Verify API keys are valid for the environment (test/production)

### Webhooks Not Working

**Problem**: Webhook events not being received or verified

**Solutions**:
- Confirm webhook secret is correctly set in environment variables
- For Stripe: Use Stripe CLI for local testing: `stripe listen --forward-to localhost:3000/webhooks/stripe`
- For PayPal: Ensure webhook ID is registered in PayPal developer dashboard
- Check webhook endpoint is publicly accessible (use ngrok for local testing)
- Verify webhook signature verification is not failing (check logs)

### Gateway Not Configured Error

**Problem**: `Gateway not configured` error when creating payments

**Solutions**:
- Ensure gateway is enabled: `PAYMENTKIT_STRIPE_ENABLED=true`
- Verify all required environment variables for the gateway are set
- Check `PaymentKitModule.register()` configuration includes the gateway

---

## Performance

- **Average Latency**: 200-500ms per payment operation (depends on gateway API response time)
- **Webhook Processing**: < 50ms for signature verification and event normalization
- **Memory Footprint**: ~15MB base + gateway client overhead

---

## Contributing

We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.

---

## Changelog

See [CHANGELOG.md](./CHANGELOG.md) for version history and release notes.

---

## License

MIT License - see [LICENSE](./LICENSE) for details.

---

## Maintainer

**Zaiid Moumni** ([@TheVlpha](https://github.com/Zaiidmo))

---

## Links

- [Documentation](./docs)
- [Examples](./examples)
- [GitHub Issues](https://github.com/CISCODE-MA/PaymentKit/issues)
- [npm Package](https://www.npmjs.com/package/@ciscode/paymentkit)

## Changelog

This package uses automated changelog generation. All releases are tagged and documented in the changelog.

---

## Known Issues & Limitations

 Stripe webhook signature verification is not included in this package. Please ensure your webhook handling is secure.
 Only supports Stripe PaymentIntent flow, not Checkout Sessions yet (we’ll add this in future versions).

---

## Maintainer

[TheVlpha](https://gihub.com/Zaiidmo)

About

A unified PaymentPackage for NestJs apps, that handles simple configs of different gateways through one single config file

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks