Skip to content

Commit 7f668f5

Browse files
committed
initial commit
0 parents  commit 7f668f5

File tree

9 files changed

+1075
-0
lines changed

9 files changed

+1075
-0
lines changed

LICENSE

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Nigeria Uniform Bank Account Number (NUBAN)
2+
3+
This is an easy to use PHP package for verifying and generating NUBAN numbers for all Nigerian financial institutions in accordance with the CBN revised standard 2020.
4+
5+
There are two categories of financial institutions, Deposit Money Banks (DMB) with 3 digit bank code, and Other Financial Institutions (OFI) with 5 digit bank code. The account number to validate must be 10 digits, while serial number for account number generation must be 9 digits.
6+
7+
## How to use
8+
9+
There are two use cases for this package. 'Validation' and 'Generation'
10+
11+
### Validation
12+
13+
Follow these steps to validate an account number.
14+
15+
> Get a valid bank code (DMB or OFI) and an account number you wish to verify belonging to the bank.
16+
17+
> Import the Nuban class using the 'use Emyu/Nuban/Nuban'
18+
19+
> Call the Nuban class with it's static method as 'Nuban::validate($bankCode, $accountNumber)' to validate your account number.
20+
21+
> It returns 'Valid' if account number is correct and belongs to the bank with the code. Returns 'Invalid' otherwise.
22+
23+
```php
24+
25+
use Emyu\Nuban\Nuban;
26+
27+
class ExampleClass {
28+
29+
public $bankCode = '011';
30+
31+
public $accountNumber = '0000014579';
32+
33+
function exampleFunction($bankCode, $accountNumber){
34+
35+
// validate a Deposit Money Bank account number
36+
$status = Nuban::validate($bankCode, $accountNumber);
37+
38+
// value of $status = 'Valid'
39+
}
40+
}
41+
```
42+
43+
### Generation
44+
45+
Follow these steps to generate an account number.
46+
47+
> Get a valid bank code (DMB or OFI) and a 9 digit serial number you wish to use as an account number.
48+
49+
> Import the Nuban class using the 'use Emyu/Nuban/Nuban'
50+
51+
> Call the Nuban class with it's static method as 'Nuban::generate($bankCode, $serialNumber)' to generate a valid account number.
52+
53+
> It returns valid account number for the bank with the code if bank code is valid. Throws an error message if otherwise.
54+
55+
```php
56+
57+
use Emyu\Nuban\Nuban;
58+
59+
class ExampleClass {
60+
61+
public $bankCode = '011';
62+
63+
public $serialNumber = '000001457';
64+
65+
function exampleFunction($bankCode, $serialNumber){
66+
67+
// generate a Deposit Money Bank account number
68+
$accountNumber = Nuban::generate($bankCode, $serialNumber);
69+
70+
// value of $accountNumber = '0000014579'
71+
}
72+
}
73+
```
74+
75+
### Incoming features
76+
77+
- Get bank name from a NUBAN number
78+
- Support for more financial institutions
79+
- Ability to input bank alias in place of bank code
80+
- much more
81+
82+
### Want to Contribute?
83+
84+
- Create an issue or
85+
86+
- Make a fork of this repository
87+
- Create a new branch on your repository.
88+
- Make contributions on that branch.
89+
- Add tests for new features.
90+
- Commit your changes and Push.
91+
- Make a pull request to the base branch. VOILA!!
92+
93+
### Love this package?
94+
95+
> Please star this repo.
96+
97+
Follow me on [Twitter](https://twitter.com/iemyu_) for more updates!

composer.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "emyu/nuban",
3+
"description": "A PHP/laravel package for validating and generating nigerian nuban account numbers based CBN guidelines 2021",
4+
"type": "library",
5+
"keywords": ["nuban", "nigerian banks", "central bank of nigeria"],
6+
"authors": [
7+
{
8+
"name": "Umar Madugu",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"minimum-stability": "dev",
13+
"require": {
14+
"php": "^7.0"
15+
},
16+
"autoload": {
17+
"psr-4": {
18+
"Emyu\\Nuban\\": "src"
19+
}
20+
},
21+
"autoload-dev": {
22+
"psr-4": {
23+
"Emyu\\Nuban\\Tests\\": "tests"
24+
}
25+
}
26+
}

src/Generate.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Emyu\Nuban;
4+
5+
/**
6+
* Generate class for generation of nigerian account numbers
7+
*
8+
* @method static string generateDMB()
9+
*
10+
* @method static string generateOFI()
11+
*
12+
*/
13+
class Generate
14+
{
15+
public static function generateDMB($bankCode, $serialNumber)
16+
{
17+
if (strlen($bankCode) == 3 && strlen($serialNumber) == 9) {
18+
19+
$bankCodeSplit = str_split('000' . $bankCode);
20+
21+
$serialNumberSplit = str_split($serialNumber);
22+
23+
$nubanAlgo = $bankCodeSplit[0] * 3 + $bankCodeSplit[1] * 7 + $bankCodeSplit[2] * 3 + $bankCodeSplit[3] * 3 + $bankCodeSplit[4] * 7 + $bankCodeSplit[5] * 3 + $serialNumberSplit[0] * 3 + $serialNumberSplit[1] * 7 + $serialNumberSplit[2] * 3 + $serialNumberSplit[3] * 3 + $serialNumberSplit[4] * 7 + $serialNumberSplit[5] * 3 + $serialNumberSplit[6] * 3 + $serialNumberSplit[7] * 7 + $serialNumberSplit[8] * 3;
24+
25+
$standardLength = 10;
26+
27+
$modulus = $nubanAlgo % $standardLength;
28+
29+
$checkDigit = $standardLength - $modulus;
30+
if ($checkDigit == 10) {
31+
$checkDigit = 0;
32+
}
33+
return $serialNumber . $checkDigit;
34+
}
35+
throw new \Exception('Error, invalid bankcode or serial number');
36+
}
37+
38+
public static function generateOFI($bankcode, $serialNumber)
39+
{
40+
if (strlen($bankcode) == 5 && strlen($serialNumber) == 9) {
41+
42+
$bankCodeSplit = str_split('9' . $bankcode);
43+
44+
$serialNumberSplit = str_split($serialNumber);
45+
46+
$nubanAlgo = $bankCodeSplit[0] * 3 + $bankCodeSplit[1] * 7 + $bankCodeSplit[2] * 3 + $bankCodeSplit[3] * 3 + $bankCodeSplit[4] * 7 + $bankCodeSplit[5] * 3 + $serialNumberSplit[0] * 3 + $serialNumberSplit[1] * 7 + $serialNumberSplit[2] * 3 + $serialNumberSplit[3] * 3 + $serialNumberSplit[4] * 7 + $serialNumberSplit[5] * 3 + $serialNumberSplit[6] * 3 + $serialNumberSplit[7] * 7 + $serialNumberSplit[8] * 3;
47+
48+
$standardLength = 10;
49+
50+
$modulus = $nubanAlgo % $standardLength;
51+
52+
$checkDigit = $standardLength - $modulus;
53+
if ($checkDigit == 10) {
54+
$checkDigit = 0;
55+
}
56+
return $serialNumber . $checkDigit;
57+
}
58+
throw new \Exception('Error, invalid bankcode or serial number');
59+
}
60+
}

src/Institutions.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Emyu\Nuban;
4+
5+
class Institutions
6+
{
7+
//OFI source: https://www.cbn.gov.ng/out/2014/ofisd/mfb%20codes.pdf
8+
//DMB source: https://trade.gov.ng/help/reference/bank/search.do
9+
10+
protected const INSTITUTIONS = [
11+
'044' => 'Access Bank',
12+
'023' => 'Citibank',
13+
'050' => 'Ecobank',
14+
'011' => 'First Bank of Nigeria',
15+
'214' => 'FCMB',
16+
'070' => 'Fidelity Bank',
17+
'058' => 'Guaranty Trust Bank',
18+
'030' => 'Heritage Bank',
19+
'082' => 'Keystone Bank',
20+
'221' => 'StanbicIBTC',
21+
'301' => 'Jaiz Bank',
22+
'068' => 'Standard Chartered Bank',
23+
'232' => 'Sterling Bank',
24+
'033' => 'United Bank For Africa',
25+
'032' => 'Union Bank',
26+
'035' => 'Wema Bank',
27+
'057' => 'Zenith Bank',
28+
'076' => 'Polaris Bank',
29+
'215' => 'Unity Bank Plc',
30+
'103' => 'Globus Bank Limited',
31+
'101' => 'Providus Bank',
32+
'102' => 'Titan Bank',
33+
'100' => 'SunTrust Bank',
34+
'302' => 'TAJ Bank limited',
35+
'50547' => 'LAPO Microfinance Bank'
36+
];
37+
}

src/Nuban.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace Emyu\Nuban;
4+
5+
6+
/**
7+
* NUBAN class for validation and generation of nigerian account numbers
8+
*
9+
* @property-read array VALID_CODE_LENGTHS valid lengths of codes for each category of institution
10+
*
11+
* @property-read array INSTITUTIONS list of all financial institutions in Nigeria
12+
*
13+
* @method static string validate()
14+
*
15+
* @method static string generate()
16+
*
17+
* @author Umar Madugu
18+
*
19+
*/
20+
class Nuban extends Institutions
21+
{
22+
23+
private const VALID_CODE_LENGTHS = [
24+
'3' => 'DMB',
25+
'5' => 'OFI'
26+
];
27+
28+
public static function validate($institution_code, $accountNumber): string
29+
{
30+
$type = static::validate_code($institution_code);
31+
32+
switch ($type) {
33+
case 'DMB':
34+
return
35+
Validate::validateDMB($institution_code, $accountNumber);
36+
case 'OFI':
37+
return Validate::validateOFI($institution_code, $accountNumber);
38+
default:
39+
throw new \Exception("Institution not found");
40+
}
41+
}
42+
43+
public static function generate($institution_code, $serialNumber): string
44+
{
45+
$type = static::validate_code($institution_code);
46+
47+
switch ($type) {
48+
case 'DMB':
49+
return
50+
Generate::generateDMB($institution_code, $serialNumber);
51+
case 'OFI':
52+
return Generate::generateOFI($institution_code, $serialNumber);
53+
default:
54+
throw new \Exception("Institution not found");
55+
}
56+
}
57+
58+
private static function validate_code($institution_code): string
59+
{
60+
$code_length = strlen($institution_code);
61+
if (array_key_exists((string)$code_length, static::VALID_CODE_LENGTHS) && array_key_exists($institution_code, self::INSTITUTIONS)) {
62+
return static::VALID_CODE_LENGTHS[$code_length];
63+
}
64+
throw new \Exception("invalid code");
65+
}
66+
}

src/Validate.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace Emyu\Nuban;
4+
5+
/**
6+
* Validate class for validation of nigerian account numbers
7+
*
8+
* @method static string validateDMB()
9+
*
10+
* @method static string validateOFI()
11+
*
12+
*/
13+
class Validate
14+
{
15+
public static function validateDMB($bankCode, $accountNumber)
16+
{
17+
if (strlen($bankCode) == 3 && strlen($accountNumber) == 10) {
18+
19+
$serialNumber = substr($accountNumber, 0, -1);
20+
$checkDigit = substr($accountNumber, -1);
21+
$nubanFormat = '000' . $bankCode . $serialNumber;
22+
23+
$nubanArray = str_split($nubanFormat);
24+
$algoDigits = [3, 7, 3, 3, 7, 3, 3, 7, 3, 3, 7, 3, 3, 7, 3];
25+
26+
$checkSum = 0;
27+
28+
foreach ($nubanArray as $key => $value) {
29+
$checkSum += ($value * $algoDigits[$key]);
30+
}
31+
32+
$calculatedCheckDigit = 10 - ($checkSum % 10);
33+
$validatedCheckDigit = $calculatedCheckDigit == 10 ? 0 : $calculatedCheckDigit;
34+
35+
return $checkDigit == $validatedCheckDigit ? 'Valid' : 'Invalid';
36+
} else {
37+
throw new \Exception("Error, Invalid Bank Code or Account Number");
38+
}
39+
}
40+
41+
public static function validateOFI($bankCode, $accountNumber)
42+
{
43+
if (strlen($bankCode) == 5 && strlen($accountNumber) == 10) {
44+
45+
$serialNumber = substr($accountNumber, 0, -1);
46+
$checkDigit = substr($accountNumber, -1);
47+
$nubanFormat = '9' . $bankCode . $serialNumber;
48+
49+
$nubanArray = str_split($nubanFormat);
50+
$algoDigits = [3, 7, 3, 3, 7, 3, 3, 7, 3, 3, 7, 3, 3, 7, 3];
51+
52+
$checkSum = 0;
53+
54+
foreach ($nubanArray as $key => $value) {
55+
$checkSum += ($value * $algoDigits[$key]);
56+
}
57+
58+
$calculatedCheckDigit = 10 - ($checkSum % 10);
59+
$validatedCheckDigit = $calculatedCheckDigit == 10 ? 0 : $calculatedCheckDigit;
60+
61+
return $checkDigit == $validatedCheckDigit ? 'Valid' : 'Invalid';
62+
} else {
63+
throw new \Exception("Error, Invalid Bank Code or Account Number");
64+
}
65+
}
66+
}

tests/GenerationTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Emyu\Nuban\Tests;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Emyu\Nuban\Nuban;
7+
8+
/**
9+
* @covers \Emyu\Nuban\Generation
10+
*/
11+
class GenerationTest extends TestCase
12+
{
13+
public function testGenerationDMB()
14+
{
15+
$accountNumber = Nuban::generate('011', '000001457');
16+
$this->assertSame('0000014579', $accountNumber);
17+
}
18+
19+
public function testGenerationOFI()
20+
{
21+
$accountNumber = Nuban::generate('50547', '000021457');
22+
$this->assertSame('0000214579', $accountNumber);
23+
}
24+
}

0 commit comments

Comments
 (0)