ng-bank-account-validator
Version:
Verify nigerian NUBAN bank accounts
268 lines (267 loc) • 10.3 kB
TypeScript
import { AccountValidationResponse, Bank, BankProperty, CardBinResponse, CardBrand, CardType, PaymentProvider } from "./types";
/**
* Nigerian NUBAN Account Validator
* @class Nuban
* @description Validates Nigerian bank account numbers using
* NUBAN algorithm and bank APIs
*/
declare class Nuban {
private readonly apiKey;
private readonly paymentProvider;
static banks: Bank[];
static weightedBanks: Bank[];
/**
* Creates an instance of NUBAN validator
* @param apiKey - The API key for the payment provider (Paystack or Flutterwave)
* @param paymentProvider - The payment provider to use (PAYSTACK or FLUTTERWAVE)
* @throws Will throw an error if apiKey is empty or payment provider is invalid
*
* @example
* ```typescript
* // Initialize with Paystack
* const nuban = new Nuban('sk_test_...', PaymentProvider.PAYSTACK);
*
* // Initialize with Flutterwave
* const nuban = new Nuban('FLWSECK_TEST-...', PaymentProvider.FLUTTERWAVE);
* ```
*/
constructor(apiKey: string, paymentProvider: PaymentProvider);
/**
* Validates a Nigerian NUBAN account number
* @param accountNumber - The account number to validate (10 digits)
* @param bankCode - The bank code (e.g., "000015" for Zenith Bank)
* @returns Promise<AccountValidationResponse>
*
* @example
* ```typescript
* const nuban = new Nuban('your-api-key', 'PAYSTACK');
*
* // Validate account using Paystack
* const result = await nuban.validateAccount('0123456789', '057');
* // { status: true, message: 'Account found', data: { account_name: 'John Doe', ... } }
*
* // Invalid account number
* const invalid = await nuban.validateAccount('12345', '057');
* // { status: false, message: 'Invalid account number, digits should be exactly 10' }
* ```
*/
validateAccount(accountNumber: string, bankCode: string): Promise<AccountValidationResponse>;
/**
* Resolves card BIN (Bank Identification Number) information
* @param firstSixDigits - First 6 digits of the card number
* @returns Promise<CardBinResponse> Card BIN information including brand, type, and issuing bank
*
* @throws Will throw an error if the card BIN resolution fails
*
* @example
* ```typescript
* const nuban = new Nuban('your-api-key', PaymentProvider.PAYSTACK);
*
* // Resolve card BIN
* const cardInfo = await nuban.resolveCardBin('123456');
* // {
* // status: true,
* // message: 'Card BIN resolved',
* // data: {
* // bin: '123456',
* // brand: 'VISA',
* // card_type: 'DEBIT',
* // bank: 'Access Bank'
* // }
* // }
* ```
*/
resolveCardBin(firstSixDigits: string): Promise<CardBinResponse>;
/**
* Gets all possible Nigerian banks that could have issued a NUBAN account number
* based on CBN's NUBAN algorithm standard
* @see {@link https://www.cbn.gov.ng/out/2020/psmd/revised%20standards%20on%20nigeria%20uniform%20bank%20account%20number%20(nuban)%20for%20banks%20and%20other%20financial%20institutions%20.pdf CBN NUBAN Standard}
*
* @param accountNumber - The 10-digit NUBAN account number to validate
* @param banks - Optional array of banks to check against (defaults to all Nigerian banks)
* @returns Array of banks that could have issued the account number
*
* @example
* ```typescript
* // Get all possible banks for an account number
* const possibleBanks = Nuban.getPossibleNubanBanks('0123456789');
* // [{ name: 'Access Bank', code: '000014' }, { name: 'Zenith Bank', code: '000015' }]
* ```
*
* Because of the irregularities in the NUBAN structure, a
* request to check a bank account can result in alot of banks
* returned, as I have 558 banks registered. So to streamline
* this for your use case you can pass custom banks to check.
*
* To this end I provided a default weightedBanks list that
* contains the most popular banks in the country that can be
* used to streammline your response to those banks.
* You can also pass custom banks.
*
* The optional weight param in the banks type is for you to
* filter the results by relevance to your specific need.
* @example
* ```typescript
* // Check against the default weighted banks
* const specificBanks = Nuban.getPossibleNubanBanks('0123456789', Nuban.weightedBanks);
*
* // Check against custom banks
* const specificBanks = Nuban.getPossibleNubanBanks('0123456789', [
* { id: '1', slug: '000014', name: 'Access Bank', code: '000014', weight: 1 }
* ]);
* ```
*/
static getPossibleNubanBanks(accountNumber: string, banks?: Bank[]): Bank[];
/**
* Get bank from slug, code or oldCode.
* @param value - The value to find (e.g., '000013')
* @param property - The bank property (e.g., BankProperty.CODE)
* @returns Bank
*
* @example
* ```typescript
* const bank = getBank('000013', BankProperty.CODE);
* // {
* // id: 11;
* // slug: 'bank_slug'
* // name: 'bank_name',
* // code: '000013'
* // }
* ```
*/
static getBank(value: string, property: BankProperty): Bank | undefined;
/**
* Makes an API request to Paystack to validate account details
* @param accountNumber - The account number to validate
* @param bankCode - The bank code to validate against
* @returns Promise<AccountValidationResponse>
* @throws Will throw an error if the API request fails
* @private
*/
private paystackQuery;
/**
* Makes an API request to Flutterwave to validate account details
* @param accountNumber - The account number to validate
* @param bankCode - The bank code to validate against
* @throws Will throw an error if the API request fails
* @private
*/
private flutterwaveQuery;
/**
* Validates NUBAN format
* @param accountNumber - The account number to validate
* @returns boolean
*/
private validateNuban;
/**
* Validates bank code format based on payment provider
* @param bankCode - The bank code to validate
* @returns boolean indicating if the bank code format is valid
* @private
*
* @example
* ```typescript
* // Paystack (exactly 3 digits)
* // Requires the old bank code
* validateBankCode('057', PaymentProvider.PAYSTACK); // true
* validateBankCode('000015', PaymentProvider.PAYSTACK); // false
*
* // Flutterwave (accepts 3 or 6 digits)
* // Accepts both the old and new bank codes.
* validateBankCode('057', PaymentProvider.FLUTTERWAVE); // true
* validateBankCode('000015', PaymentProvider.FLUTTERWAVE); // true
* ```
*/
private validateBankCode;
/**
* Formats Flutterwave's card BIN response to match the standard CardBinResponse interface
* @param response - Raw response from Flutterwave's card BIN API
* @returns CardBinResponse Formatted card BIN information
*
* @example
* ```typescript
* // Raw Flutterwave response
* const rawResponse = {
* status: true,
* message: "success",
* data: {
* issuing_country: "NIGERIA NG",
* bin: "123456",
* card_type: "DEBIT",
* issuer_info: "VISA Access Bank"
* }
* };
*
* const formatted = this.formatFlutterwaveCardBinResponse(rawResponse);
* // {
* // status: true,
* // message: "success",
* // data: {
* // bin: "123456",
* // country_code: "NG",
* // country_name: "NIGERIA",
* // card_type: "DEBIT",
* // brand: "VISA",
* // bank: "Access Bank"
* // }
* // }
* ```
*/
private formatFlutterwaveCardBinResponse;
/**
* Validates and type checks the API response
* @param response - Raw API response
* @returns AccountValidationResponse
* @throws Will throw an error if the response format is invalid
* @private
*/
private validateApiResponse;
/**
* Generates a seed array for NUBAN validation based on CBN's algorithm
* @param length - Length of the seed array to generate
* @returns Array of alternating numbers (3,7) based on the specified length
* @private
*
* @example
* [3, 7, 3, 3, 7, 3, 3, 7, 3]
*/
private static generateSeed;
/**
* Validates the NUBAN serial code format
* @param nubanSerialCode - 9-digit NUBAN serial code
* @throws {Error} If serial code is invalid or exceeds maximum length
* @returns true if the serial code is valid
* @private
*/
private static validateNubanSerialCode;
/**
* Generates the check digit for a NUBAN account number using CBN's algorithm
* @see {@link https://www.cbn.gov.ng/out/2020/psmd/revised%20standards%20on%20nigeria%20uniform%20bank%20account%20number%20(nuban)%20for%20banks%20and%20other%20financial%20institutions%20.pdf CBN NUBAN Standard}
* @param nubanSerialCode - First 9 digits of the account number
* @param bankCode - 6-digit bank code
* @returns The check digit (last digit) of the NUBAN
* @private
*
* @example
* ```typescript
* const checkDigit = Nuban.generateCheckDigit('123456789', '000014');
* // Returns a number between 0-9
* ```
*/
private static generateCheckDigit;
/**
* Checks if a bank could have issued a specific NUBAN account number
* @param accountNumber - Complete 10-digit NUBAN account number
* @param bankCode - 6-digit bank code to validate against
* @returns boolean indicating if the bank could have issued the account number
* @private
*
* @example
* ```typescript
* const isValid = Nuban.isPossibleNubanBank('0123456789', '000014');
* // Returns true if the check digit matches the bank's algorithm
* ```
*/
private static isPossibleNubanBank;
}
export { Nuban, PaymentProvider, Bank, BankProperty, AccountValidationResponse, CardType, CardBrand, CardBinResponse, };