Lenco Flutter

pub package License: MIT

A production-ready Flutter package for integrating Lenco payment gateway. This package provides a comprehensive, type-safe, and easy-to-use interface for Lenco's API.

Created by Wamunyima Mukelabai

Features

Account Management - Get accounts, balances, and account details
Transaction History - Fetch and filter transactions with pagination
Bank Transfers - Initiate single and bulk transfers
Account Verification - Verify account names before transfers
Bank List - Get all supported Nigerian banks
Type-Safe Models - Full type safety with generated JSON serialization
Error Handling - Comprehensive exception hierarchy
API v1 & v2 Support - Works with both API versions
Testing Support - Sandbox environment for development

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  lenco_flutter: ^1.0.0

Then run:

flutter pub get

Usage

Initialize the Client

import 'package:lenco_flutter/lenco_flutter.dart';

// Production environment
final lenco = LencoClient.production(
  apiKey: 'your-api-key',
);

// Sandbox environment (for testing)
final lenco = LencoClient.sandbox(
  apiKey: 'your-test-api-key',
);

// Custom configuration
final lenco = LencoClient(
  config: LencoConfig(
    apiKey: 'your-api-key',
    baseUrl: 'https://api.lenco.co',
    version: LencoApiVersion.v1,
    timeout: Duration(seconds: 30),
    debugMode: true,
  ),
);

Get All Accounts

try {
  final accounts = await lenco.accounts.getAccounts();

  for (var account in accounts) {
    print('Account: ${account.name}');
    print('Balance: ${account.availableBalance} ${account.currency}');
    print('Account Number: ${account.bankAccount.accountNumber}');
    print('Bank: ${account.bankAccount.bank.name}');
    print('---');
  }
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Get Account Balance

try {
  final balance = await lenco.accounts.getAccountBalance('account-id');
  print('Available: ${balance['available']}');
  print('Current: ${balance['current']}');
} on LencoNotFoundException catch (e) {
  print('Account not found: ${e.message}');
}

Get Transactions

try {
  final transactions = await lenco.transactions.getTransactions(
    accountId: 'account-id',
    page: 1,
    limit: 50,
    type: 'credit', // Filter by type: 'credit' or 'debit'
    startDate: '2024-01-01T00:00:00Z',
    endDate: '2024-12-31T23:59:59Z',
  );

  for (var txn in transactions) {
    print('${txn.type}: ${txn.amount} ${txn.currency}');
    print('Description: ${txn.description}');
    print('Status: ${txn.status}');
    print('Date: ${txn.createdAt}');
  }
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Verify Account Name

Always verify account details before making a transfer:

try {
  final accountName = await lenco.payments.verifyAccountName(
    accountNumber: '1234567890',
    bankCode: '044', // Access Bank
  );

  print('Account Name: $accountName');
  // Proceed with transfer if name matches
} on LencoNotFoundException catch (e) {
  print('Account not found');
} on LencoException catch (e) {
  print('Verification failed: ${e.message}');
}

Get List of Banks

try {
  final banks = await lenco.payments.getBanks();

  for (var bank in banks) {
    print('${bank.name} - ${bank.code}');
  }
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Initiate Bank Transfer

try {
  final payment = await lenco.payments.initiatePayment(
    PaymentRequest(
      accountId: 'your-account-id',
      amount: '10000', // Amount in kobo/minor units
      recipientAccountNumber: '1234567890',
      recipientBankCode: '044',
      narration: 'Payment for services',
      reference: 'TXN-${DateTime.now().millisecondsSinceEpoch}', // Optional
    ),
  );

  print('Payment Reference: ${payment.reference}');
  print('Status: ${payment.status}');
  print('Amount: ${payment.amount}');
} on LencoValidationException catch (e) {
  print('Validation Error: ${e.message}');
  print('Errors: ${e.errors}');
} on LencoAuthenticationException catch (e) {
  print('Authentication failed: ${e.message}');
} on LencoException catch (e) {
  print('Payment failed: ${e.message}');
}

Check Payment Status

try {
  final payment = await lenco.payments.getPaymentStatus(
    reference: 'PAY-REF-123',
  );

  if (payment.status == 'success') {
    print('Payment completed successfully');
  } else if (payment.status == 'pending') {
    print('Payment is still processing');
  } else {
    print('Payment failed: ${payment.message}');
  }
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Bulk Transfers

try {
  final transfers = [
    PaymentRequest(
      accountId: 'account-id',
      amount: '5000',
      recipientAccountNumber: '1111111111',
      recipientBankCode: '044',
      narration: 'Salary - John',
    ),
    PaymentRequest(
      accountId: 'account-id',
      amount: '7500',
      recipientAccountNumber: '2222222222',
      recipientBankCode: '058',
      narration: 'Salary - Jane',
    ),
  ];

  final result = await lenco.payments.initiateBulkTransfer(
    accountId: 'account-id',
    transfers: transfers,
  );

  print('Bulk transfer initiated: $result');
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Get Transfer Fee

try {
  final fee = await lenco.payments.getTransferFee(
    amount: '10000',
    bankCode: '044',
  );

  print('Transfer fee: $fee');
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Download Statement

try {
  final downloadUrl = await lenco.transactions.downloadStatement(
    accountId: 'account-id',
    startDate: '2024-01-01T00:00:00Z',
    endDate: '2024-12-31T23:59:59Z',
    format: 'pdf', // Options: 'pdf', 'csv', 'xlsx'
  );

  print('Download statement from: $downloadUrl');
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Error Handling

The package includes a comprehensive exception hierarchy:

try {
  await lenco.payments.initiatePayment(request);
} on LencoAuthenticationException catch (e) {
  // Handle authentication errors (401)
  print('Invalid API key: ${e.message}');
} on LencoValidationException catch (e) {
  // Handle validation errors (400)
  print('Validation failed: ${e.message}');
  print('Field errors: ${e.errors}');
} on LencoNotFoundException catch (e) {
  // Handle not found errors (404)
  print('Resource not found: ${e.message}');
} on LencoRateLimitException catch (e) {
  // Handle rate limiting (429)
  print('Too many requests: ${e.message}');
} on LencoServerException catch (e) {
  // Handle server errors (500+)
  print('Server error: ${e.message}');
} on LencoNetworkException catch (e) {
  // Handle network errors
  print('Network error: ${e.message}');
} on LencoException catch (e) {
  // Handle all other Lenco errors
  print('Lenco error: ${e.message}');
} catch (e) {
  // Handle unexpected errors
  print('Unexpected error: $e');
}

Best Practices

1. Always Verify Account Names

// ✅ Good
final name = await lenco.payments.verifyAccountName(...);
if (name == expectedName) {
  await lenco.payments.initiatePayment(...);
}

// ❌ Bad
await lenco.payments.initiatePayment(...); // Without verification

2. Use Unique References

// ✅ Good - Generate unique references
final reference = 'TXN-${DateTime.now().millisecondsSinceEpoch}';

// ❌ Bad - Reusing references can cause issues
final reference = 'payment-1';

3. Handle Errors Gracefully

// ✅ Good - Specific error handling
try {
  await lenco.payments.initiatePayment(...);
} on LencoValidationException catch (e) {
  // Show field-specific errors to user
} on LencoNetworkException catch (e) {
  // Show network error, retry option
}

// ❌ Bad - Generic error handling
try {
  await lenco.payments.initiatePayment(...);
} catch (e) {
  print('Error: $e');
}

4. Close the Client

// Close when done to free resources
lenco.close();

5. Use Sandbox for Testing

// ✅ Development
final lenco = LencoClient.sandbox(apiKey: testKey);

// ✅ Production
final lenco = LencoClient.production(apiKey: prodKey);

Testing

The package is designed to be easily testable. You can mock the HTTP client:

import 'package:http/http.dart' as http;
import 'package:mockito/mockito.dart';

// Create mock
class MockClient extends Mock implements http.Client {}

// Use in tests
final mockClient = MockClient();
final lenco = LencoClient(
  config: LencoConfig(apiKey: 'test-key'),
  httpClient: mockClient,
);

API Documentation

For complete API documentation, visit:

Support

Contributing

Contributions are welcome! Please read our Contributing Guide for details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

See CHANGELOG.md for a list of changes.

Author

Wamunyima Mukelabai - GitHub

Acknowledgments

  • Thanks to Lenco for providing the payment gateway API
  • Built with ❤️ for the Flutter community

Libraries

lenco_flutter
A production-ready Flutter package for integrating Lenco payment gateway.