sofri-tms
v1.2.1
Published
A comprehensive Node.js npm package for integrating with the Transaction Monitoring System (TMS). Features include real-time transaction monitoring, fraud detection, queue processing, webhook management, compliance review, and comprehensive analytics. Bui
Maintainers
Readme
Sofri TMS - Transaction Monitoring System Client
A comprehensive Node.js npm package for integrating with the Transaction Monitoring System (TMS). This package provides a complete client for real-time transaction monitoring, fraud detection, queue processing, webhook management, compliance review, and comprehensive analytics.
🚀 Features
- Real-time Transaction Monitoring - Direct and queue-based processing
- Fraud Detection Integration - Seamless integration with Regfyl's fraud detection engine
- Queue Processing - FIFO processing for high-volume transactions
- Webhook Management - Real-time event notifications and webhook configuration
- Compliance Review - Manual transaction review system for soft-flagged transactions
- Comprehensive Analytics - Transaction statistics and queue monitoring
- API Key Authentication - Secure server-to-server authentication
- TypeScript Support - Complete type definitions and type safety
- Framework Compatibility - Full support for Express.js and NestJS
- Production Ready - Error handling, retry logic, and comprehensive logging
📦 Installation
npm install sofri-tms🚀 Quick Start
Basic Setup
import {
configureTMS,
monitorTransactionDirect,
monitorTransactionQueue,
} from 'sofri-tms';
// Configure the TMS client
configureTMS({
apiKey: 'your-api-key',
baseUrl: 'https://api.tms.example.com',
timeout: 30000,
retries: 3,
});
// Monitor transaction directly (synchronous)
const directResult = await monitorTransactionDirect({
customerID: '12345',
companyName: 'Example Corp',
rcNumber: 'RC123456',
customerNationality: 'Nigerian',
idNumber: '12345678901',
phoneNo: '+2348012345678',
customerEmail: '[email protected]',
customerGender: 'Male',
customerFI: 'Example Bank',
customerAccountNumber: '1234567890',
transactionAmount: '100000',
currency: 'NGN',
walletBalance: '500000',
walletCurrency: 'NGN',
transactionStatus: 'PENDING',
transactionChannel: 'MOBILE_APP',
transactionType: 'TRANSFER',
purpose: 'Business transfer',
sourceFunds: 'Salary',
customerLongitude: '3.3792',
customerLatitude: '6.5244',
ipAddress: '192.168.1.1',
transactionCountry: 'Nigeria',
destinationCountry: 'Nigeria',
vpnUsed: 'No',
trustedDevice: 'Yes',
authenticated: 'Yes',
environment: 'PRODUCTION',
langPref: 'ENGLISH',
customerType: 'INDIVIDUAL',
});
// Monitor transaction via queue (asynchronous)
const queueResult = await monitorTransactionQueue({
// ... same transaction data
});
console.log('Direct monitoring result:', directResult);
console.log('Queue monitoring result:', queueResult);Express.js Integration
import express from 'express';
import {
configureTMS,
monitorTransactionDirect,
getTransactionByRef,
getMonitoringStatistics,
} from 'sofri-tms';
const app = express();
app.use(express.json());
// Configure TMS
configureTMS({
apiKey: process.env.TMS_API_KEY,
baseUrl: process.env.TMS_BASE_URL,
});
// Monitor transaction endpoint
app.post('/api/transactions/monitor', async (req, res) => {
try {
const result = await monitorTransactionDirect(req.body);
res.json({
success: true,
data: result,
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message,
});
}
});
// Get transaction by reference
app.get('/api/transactions/:transactionRef', async (req, res) => {
try {
const transaction = await getTransactionByRef(req.params.transactionRef);
res.json({
success: true,
data: transaction,
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message,
});
}
});
// Get monitoring statistics
app.get('/api/transactions/statistics', async (req, res) => {
try {
const stats = await getMonitoringStatistics();
res.json({
success: true,
data: stats,
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message,
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});NestJS Integration
import { Injectable } from '@nestjs/common';
import {
configureTMS,
TMSClient,
MonitorTransactionDto,
TransactionMonitoringResponseDto,
} from 'sofri-tms';
@Injectable()
export class TransactionService {
private tmsClient: TMSClient;
constructor() {
configureTMS({
apiKey: process.env.TMS_API_KEY,
baseUrl: process.env.TMS_BASE_URL,
});
this.tmsClient = new TMSClient({
apiKey: process.env.TMS_API_KEY,
baseUrl: process.env.TMS_BASE_URL,
});
}
async monitorTransaction(
data: MonitorTransactionDto
): Promise<TransactionMonitoringResponseDto> {
return await this.tmsClient.monitorTransactionDirect(data);
}
async getTransactionByRef(transactionRef: string) {
return await this.tmsClient.getTransactionByRef(transactionRef);
}
async getStatistics() {
return await this.tmsClient.getMonitoringStatistics();
}
}📚 API Reference
Configuration
configureTMS(config: TMSConfig)
Configure the TMS client with your API credentials.
interface TMSConfig {
apiKey: string; // Your TMS API key
baseUrl: string; // TMS API base URL
timeout?: number; // Request timeout (default: 30000ms)
retries?: number; // Retry attempts (default: 3)
}Transaction Monitoring
monitorTransactionDirect(data: MonitorTransactionDto)
Monitor a transaction directly (synchronous processing).
const result = await monitorTransactionDirect({
customerID: '12345',
companyName: 'Example Corp',
// ... other required fields
});monitorTransactionQueue(data: MonitorTransactionDto)
Monitor a transaction via queue (asynchronous processing).
const result = await monitorTransactionQueue({
customerID: '12345',
companyName: 'Example Corp',
// ... other required fields
});Transaction Management
getTransactionByRef(transactionRef: string)
Get transaction details by reference.
const transaction = await getTransactionByRef('TX-20250729-ABC123');getTransactionsByStatus(status, page?, limit?)
Get transactions by monitoring status.
const transactions = await getTransactionsByStatus('APPROVED', 1, 50);getTransactionsByCustomer(customerID, page?, limit?)
Get transactions by customer ID.
const transactions = await getTransactionsByCustomer('12345', 1, 50);Queue Management
getQueueStatistics()
Get queue processing statistics.
const stats = await getQueueStatistics();getProcessingStatus(messageId)
Get processing status by message ID.
const status = await getProcessingStatus('msg_1754488157824_foj8ndlc1');retryFailedTransaction(messageId)
Retry a failed transaction.
const result = await retryFailedTransaction('msg_1754488157824_foj8ndlc1');Compliance Review
getSoftFlaggedTransactions(page?, limit?)
Get transactions flagged for manual review.
const transactions = await getSoftFlaggedTransactions(1, 50);approveRejectTransaction(reviewData)
Approve or reject a transaction in compliance review.
const result = await approveRejectTransaction({
transactionRef: 'TX-20250729-ABC123',
action: 'APPROVE',
reviewNotes: 'Transaction appears legitimate',
analystId: 'analyst-001',
});Webhook Management
updateWebhookUrl(apiKeyId, webhookUrl)
Update webhook URL for an API key.
const result = await updateWebhookUrl(
'api-key-id',
'https://your-service.com/webhooks'
);getWebhookUrl(apiKeyId)
Get webhook URL for an API key.
const { webhookUrl } = await getWebhookUrl('api-key-id');Analytics
getMonitoringStatistics()
Get comprehensive monitoring statistics.
const stats = await getMonitoringStatistics();🔧 Webhook Handling
Webhook Events
The TMS sends the following webhook events:
Queue Processing Complete
{
"eventType": "queue_processing_complete",
"messageId": "msg_1754488157824_foj8ndlc1",
"transactionRef": "TX-20250729-ABC123",
"status": "completed",
"data": {
"result": {
/* processing result */
},
"processingTime": 1500,
"message": "Transaction processing completed successfully"
},
"timestamp": "2025-08-06T21:30:00Z",
"processingTime": 1500
}Regfyl Decision
{
"eventType": "regfyl_decision",
"transactionRef": "TX-20250729-ABC123",
"status": "approved",
"data": {
"regfylDecision": {
/* Regfyl response */
},
"message": "Transaction approved by Regfyl",
"riskLevel": "LOW",
"confidenceScore": "HIGH"
},
"timestamp": "2025-08-06T21:30:00Z"
}Webhook Handler Example
import express from 'express';
import { handleWebhookEvent } from 'sofri-tms';
const app = express();
app.use(express.json());
app.post('/webhooks/tms', (req, res) => {
try {
// Handle the webhook event
handleWebhookEvent(req.body);
// Process based on event type
switch (req.body.eventType) {
case 'queue_processing_complete':
console.log('Queue processing completed:', req.body.transactionRef);
break;
case 'regfyl_decision':
console.log('Regfyl decision received:', req.body.transactionRef);
break;
case 'processing_failed':
console.log('Processing failed:', req.body.transactionRef);
break;
}
res.status(200).json({ received: true });
} catch (error) {
console.error('Webhook processing error:', error);
res.status(500).json({ error: 'Webhook processing failed' });
}
});🛡️ Security Features
- API Key Authentication - Secure server-to-server authentication
- IP Restrictions - Configurable IP allowlists per API key
- Role-Based Access - Granular permission control
- Scope Validation - Fine-grained API access control
- Request Logging - Comprehensive audit trail
- Error Masking - Sensitive data protection in error responses
📊 Error Handling
The package provides comprehensive error handling:
try {
const result = await monitorTransactionDirect(transactionData);
console.log('Success:', result);
} catch (error) {
if (error.status === 401) {
console.error('Authentication failed - check your API key');
} else if (error.status === 400) {
console.error('Validation error:', error.data?.errors);
} else if (error.status === 429) {
console.error('Rate limit exceeded');
} else {
console.error('Unexpected error:', error.message);
}
}🔄 Retry Logic
The package includes built-in retry logic for failed requests:
// Configure with custom retry settings
configureTMS({
apiKey: 'your-api-key',
baseUrl: 'https://api.tms.example.com',
retries: 5, // Retry up to 5 times
timeout: 60000, // 60 second timeout
});📈 Performance Optimization
Queue Processing for High Volume
For high-volume scenarios, use queue processing:
// Enqueue transaction for processing
const queueResult = await monitorTransactionQueue(transactionData);
// Wait for completion (optional)
const status = await waitForQueueCompletion(queueResult.messageId);
console.log('Processing completed:', status);Batch Processing
// Process multiple transactions
const transactions = [
/* array of transaction data */
];
const results = [];
for (const transaction of transactions) {
try {
const result = await monitorTransactionQueue(transaction);
results.push(result);
} catch (error) {
console.error('Transaction failed:', error);
}
}🧪 Testing
Unit Tests
import { configureTMS, monitorTransactionDirect } from 'sofri-tms';
describe('TMS Integration', () => {
beforeEach(() => {
configureTMS({
apiKey: 'test-api-key',
baseUrl: 'https://api.test.com',
});
});
it('should monitor transaction successfully', async () => {
const result = await monitorTransactionDirect({
customerID: '12345',
// ... other required fields
});
expect(result.status).toBe('200');
expect(result.transactionRef).toBeDefined();
});
});📋 Environment Variables
# TMS Configuration
TMS_API_KEY=your-api-key
TMS_BASE_URL=https://api.tms.example.com
TMS_TIMEOUT=30000
TMS_RETRIES=3
# Webhook Configuration
WEBHOOK_SECRET=your-webhook-secret
WEBHOOK_URL=https://your-service.com/webhooks/tms🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🆘 Support
- Documentation: GitHub Wiki
- Issues: GitHub Issues
- Discussions: GitHub Discussions
🔗 Related Links
Built with ❤️ for secure transaction monitoring
