lenco_flutter 2.2.0 copy "lenco_flutter: ^2.2.0" to clipboard
lenco_flutter: ^2.2.0 copied to clipboard

A production-ready Flutter package for integrating Lenco payment gateway. Support for accounts, transactions, payments, collections, virtual accounts, and mobile money.

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
Accept Payments - Collections (card, mobile money) - NEW!
Virtual Accounts - Receive payments via dedicated accounts - NEW!
Recipient Management - Save and manage payment recipients - NEW!
Settlements - Track payouts and settlements - NEW!
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}');
}

Accept Payment (Collections) - v2 #

Accept payments from cards or mobile money:

try {
  // Accept card payment
  final collection = await lenco.collections.createCardCollection(
    CollectionRequest(
      amount: '10000',
      currency: 'NGN',
      reference: 'ORDER-123',
      callbackUrl: 'https://yourapp.com/callback',
    ),
    cardNumber: '4532015112830366',
    expiryMonth: '12',
    expiryYear: '25',
    cvv: '123',
  );

  print('Payment authorized: ${collection.authorizationUrl}');
  print('Status: ${collection.status}');
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Or accept mobile money (v2):

try {
  final collection = await lenco.collections.createMobileMoneyCollectionV2(
    request: CollectionRequest(
      amount: '10000',
      currency: 'USD',
      reference: 'ORDER-456',
    ),
    phone: '260971234567', // MSISDN (no +)
    operator: 'mtn',       // 'airtel' | 'mtn' | 'zamtel'
    country: 'ZM',
  );

  // Submit OTP if required
  final result = await lenco.collections.submitMobileMoneyOtpV2(
    collectionId: collection.id,
    otp: '123456',
  );

  print('Payment status: ${result.status}');
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Create Virtual Account - NEW! #

Create a virtual account for receiving payments:

try {
  final virtualAccount = await lenco.virtualAccounts.createVirtualAccount(
    accountName: 'John Doe',
    bvn: '12345678901', // Optional
  );

  print('Virtual Account: ${virtualAccount.accountNumber}');
  print('Account Name: ${virtualAccount.accountName}');
  print('Bank: ${virtualAccount.bank.name}');
  print('Reference: ${virtualAccount.accountReference}');

  // Get virtual account transactions
  final transactions = await lenco.virtualAccounts.getTransactions(
    accountReference: virtualAccount.accountReference,
  );
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Manage Recipients - v2 #

Save and reuse payment recipients:

try {
  // Create a recipient
  final recipient = await lenco.recipients.createRecipient(
    accountName: 'John Doe',
    accountNumber: '1234567890',
    bankCode: '044',
  );

  print('Recipient created: ${recipient.name}');

  // Get all recipients
  final recipients = await lenco.recipients.getRecipients();

  for (var recipient in recipients) {
    print('${recipient.name} - ${recipient.accountNumber}');
  }
} on LencoException catch (e) {
  print('Error: ${e.message}');
}

Track Settlements - NEW! #

Monitor your settlement history:

try {
  final settlements = await lenco.settlements.getSettlements(
    page: 1,
    limit: 20,
    status: 'completed', // Optional filter
  );

  for (var settlement in settlements) {
    print('Amount: ${settlement.amount} ${settlement.currency}');
    print('Status: ${settlement.status}');
    print('Date: ${settlement.createdAt}');
  }
} 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,
);

Test suites #

  • Unit tests: cover models, utilities, error mapping and service happy-paths.
  • Contract tests (v2): validate request paths and payload shapes against the docs for endpoints such as collections, transfers, resolve, accounts, transactions, banks, settlements, transfer-recipients, and encryption-key. See test/v2_contract_test.dart.

Run tests locally #

flutter test

Developer notes #

  • Use LencoConfig.sandbox(..., version: LencoApiVersion.v2) in tests to ensure versioned base path /access/v2.
  • MSISDN normalization: pass any Zambia phone format; SDK normalizes to MSISDN (e.g., +260971234567 -> 260971234567).
  • Error handling: the HTTP client maps 4xx/5xx to specific exceptions. Assert types rather than messages.
  • Reference: Lenco v2 API docs link.

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
1
likes
160
points
131
downloads

Publisher

unverified uploader

Weekly Downloads

A production-ready Flutter package for integrating Lenco payment gateway. Support for accounts, transactions, payments, collections, virtual accounts, and mobile money.

Homepage
Repository (GitHub)
View/report issues
Contributing

Topics

#payment #gateway #lenco #fintech #api

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

equatable, flutter, http, json_annotation, meta

More

Packages that depend on lenco_flutter