@scwar/nestjs-monnify
A comprehensive NestJS module for integrating with the Monnify API. This package provides a clean, type-safe interface for all Monnify services including collections, disbursements, wallets, and customer verification.
Features
- ๐ Full Monnify API Coverage - Collections, Disbursements, Wallets, Verification
- ๐ Type Safety - Full TypeScript support with comprehensive interfaces
- ๐๏ธ NestJS Native - Built specifically for NestJS applications
- ๐ Automatic Retries - Configurable retry logic with exponential backoff
- ๐ Environment Support - Sandbox and production environments
- ๐ Comprehensive Documentation - Well-documented methods and interfaces
- ๐งช Test Coverage - Extensive test suite for reliability
Installation
npm install @scwar/nestjs-monnify
Quick Start
1. Import the Module
import { Module } from '@nestjs/common';
import { MonnifyModule } from '@scwar/nestjs-monnify';
@Module({
imports: [
MonnifyModule.forRoot({
secretKey: 'your-secret-key',
publicKey: 'your-public-key',
contractCode: 'your-contract-code',
environment: 'sandbox',
}),
],
})
export class AppModule {}
2. Use the Service
import { Injectable } from '@nestjs/common';
import { MonnifyService } from '@scwar/nestjs-monnify';
@Injectable()
export class PaymentService {
constructor(private readonly monnifyService: MonnifyService) {}
async initializePayment() {
const payment = await this.monnifyService.collections.initializeTransaction({
amount: 1000,
customerName: 'John Doe',
customerEmail: 'john@example.com',
paymentReference: 'REF-123',
paymentDescription: 'Payment for services',
currencyCode: 'NGN',
contractCode: 'your-contract-code',
redirectUrl: 'https://yourapp.com/callback',
});
return payment;
}
}
Configuration Options
secretKey | string | โ
| - | Your Monnify secret key |
publicKey | string | โ
| - | Your Monnify public key |
contractCode | string | โ
| - | Your Monnify contract code |
environment | 'sandbox' | 'production' | โ | 'sandbox' | API environment |
baseUrl | string | โ | Auto-detected | Custom API base URL |
timeout | number | โ | 30000 | Request timeout in ms |
retries | number | โ | 3 | Number of retry attempts |
retryDelay | number | โ | 1000 | Initial retry delay in ms |
maxRetryDelay | number | โ | 10000 | Maximum retry delay in ms |
Services
Collections Service
Handle payment collections and customer reserved accounts.
const transaction = await monnifyService.collections.initializeTransaction({
amount: 1000,
customerName: 'John Doe',
customerEmail: 'john@example.com',
paymentReference: 'REF-123',
paymentDescription: 'Payment for services',
currencyCode: 'NGN',
contractCode: 'your-contract-code',
});
const status = await monnifyService.collections.getTransactionStatus('transaction-ref');
const account = await monnifyService.collections.createReservedAccount({
accountReference: 'ACC-123',
accountName: 'John Doe Account',
customerEmail: 'john@example.com',
customerName: 'John Doe',
contractCode: 'your-contract-code',
});
Disbursements Service
Handle money transfers and disbursements.
const transfer = await monnifyService.disbursements.initiateSingleTransfer({
amount: 1000,
reference: 'TRF-123',
narration: 'Transfer to John',
destinationBankCode: '044',
destinationAccountNumber: '1234567890',
destinationAccountName: 'John Doe',
currency: 'NGN',
sourceAccountNumber: '0987654321',
});
const bulkTransfer = await monnifyService.disbursements.initiateBulkTransfer({
title: 'Bulk Transfer',
batchReference: 'BATCH-123',
narration: 'Bulk transfer to employees',
sourceAccountNumber: '0987654321',
currency: 'NGN',
onValidationFailure: 'CONTINUE',
notificationInterval: 30,
transactions: [
{
amount: 1000,
reference: 'TRF-001',
narration: 'Transfer to John',
destinationBankCode: '044',
destinationAccountNumber: '1234567890',
destinationAccountName: 'John Doe',
},
],
});
Wallets Service
Manage digital wallets and balance operations.
const wallet = await monnifyService.wallets.createWallet({
walletReference: 'WALLET-123',
walletName: 'John Doe Wallet',
customerEmail: 'john@example.com',
customerName: 'John Doe',
currencyCode: 'NGN',
contractCode: 'your-contract-code',
});
const balance = await monnifyService.wallets.getWalletBalance('WALLET-123');
const statement = await monnifyService.wallets.getWalletStatement({
walletReference: 'WALLET-123',
fromDate: '2024-01-01',
toDate: '2024-12-31',
pageSize: 10,
pageNumber: 1,
});
Verification Service
Verify customer information including BVN, bank accounts, and phone numbers.
const bvn = await monnifyService.verification.verifyBvn({
bvn: '12345678901',
dateOfBirth: '1990-01-01',
});
const account = await monnifyService.verification.verifyBankAccount({
accountNumber: '1234567890',
bankCode: '044',
});
const phone = await monnifyService.verification.verifyPhoneNumber({
phoneNumber: '+2348012345678',
});
Async Configuration
For dynamic configuration (e.g., from environment variables):
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
MonnifyModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
secretKey: configService.get('MONNIFY_SECRET_KEY'),
publicKey: configService.get('MONNIFY_PUBLIC_KEY'),
contractCode: configService.get('MONNIFY_CONTRACT_CODE'),
environment: configService.get('MONNIFY_ENVIRONMENT'),
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}
Error Handling
The package provides comprehensive error handling:
try {
const result = await monnifyService.collections.initializeTransaction(request);
} catch (error) {
if (error.response?.data) {
console.error('Monnify Error:', error.response.data.responseMessage);
} else {
console.error('Error:', error.message);
}
}
Testing
import { Test, TestingModule } from '@nestjs/testing';
import { MonnifyModule } from '@scwar/nestjs-monnify';
describe('PaymentService', () => {
let service: PaymentService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
MonnifyModule.forRoot({
secretKey: 'test-secret',
publicKey: 'test-public',
contractCode: 'test-contract',
environment: 'sandbox',
}),
],
providers: [PaymentService],
}).compile();
service = module.get<PaymentService>(PaymentService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
)
- Commit your changes (
git commit -m 'Add some amazing feature'
)
- Push to the branch (
git push origin feature/amazing-feature
)
- Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
Changelog
See CHANGELOG.md for a list of changes and version history.