SepaCntryValidationBE::validateCI()   B
last analyzed

Complexity

Conditions 7
Paths 13

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 31
rs 8.6506
c 0
b 0
f 0
cc 7
nc 13
nop 1
1
<?php
2
namespace SKien\Sepa\CntryValidation;
3
4
use SKien\Sepa\Sepa;
5
/**
6
 * Validation class for belgian IBAN and CI
7
 *
8
 * #### Valid testvalues
9
 * <table><tbody>
10
 * <tr><td>   IBAN   </td><td> BE68 5390 0754 7034 </td></tr>
11
 * <tr><td>   BIC    </td><td> JCAEBE9AXXX </td></tr>
12
 * <tr><td>   CI     </td><td> BE69 ZZZ 050 D 000000008 / BE68 ZZZ 0123456789 </td></tr>
13
 * </tbody></table>
14
 *
15
 * #### IBAN format
16
 * #### ` CCpp bbbk kkkk kkPP `
17
 * <table><tbody>
18
 * <tr><td>   CC     </td><td> ISO Country Code </td></tr>
19
 * <tr><td>   pp     </td><td> 2 digits IBAN checksum </td></tr>
20
 * <tr><td>   b      </td><td> 3 digits numeric banking code </td></tr>
21
 * <tr><td>   k      </td><td> 7 digits numeric account number </td></tr>
22
 * <tr><td>   PP     </td><td> 2 digits numeric national check code </td></tr>
23
 * </tbody></table>
24
 *
25
 * Length: 16
26
 *
27
 * #### CI format
28
 * Belgium has a more complex format for the CI. For more information
29
 * see method SepaCntryValidationBE::validateCI()
30
 *
31
 * @package Sepa
32
 * @author Stefanius <[email protected]>
33
 * @copyright MIT License - see the LICENSE file for details
34
 */
35
class SepaCntryValidationBE extends SepaCntryValidationBase
36
{
37
    /**
38
     * Create instance of belgian validation.
39
     * @param string $strCntry  2 sign country code
40
     */
41
    public function __construct(string $strCntry)
42
    {
43
        $this->strCntry = 'BE';
44
        $this->iLenIBAN = 16;
45
        $this->strRegExIBAN = '/^([A-Z]){2}([0-9]){14}?$/';
46
47
        parent::__construct(strtoupper($strCntry));
48
    }
49
50
    /**
51
     * Validates given CI for belgium.
52
     *
53
     * In Belgium there are two different formats for the CI, depending on whether the holder
54
     * has an 'Enterprise' number or not
55
     *
56
     * #### 1. When the Creditor has an 'Enterprise Number'
57
     * #### ` CCpp ZZZ nnnnnnnnnn `
58
     * <table><tbody>
59
     * <tr><td>   C     </td><td> ISO Country Code </td></tr>
60
     * <tr><td>   p     </td><td> 2 digits IBAN checksum </td></tr>
61
     * <tr><td>   Z     </td><td> 3 digits alphanum creditor business code (CBC) </td></tr>
62
     * <tr><td>   n     </td><td> 10 digits numeric 'Enterprise Number' </td></tr>
63
     * </tbody></table>
64
     *
65
     * Length: 17
66
     *
67
     * <i>
68
     * For the national identifier 10 numeric positions fixed length are used.
69
     * It is called the 'Enterprise Number' (this number is also used as the VAT
70
     * number by the company).
71
     * </i>
72
     *
73
     * #### 2. When the Creditor does not have an 'Enterprise Number'
74
     * #### ` CCpp ZZZ bbbDnnnnnnnnn `
75
     * <table><tbody>
76
     * <tr><td>   C     </td><td> ISO Country Code </td></tr>
77
     * <tr><td>   p     </td><td> 2 digits IBAN checksum </td></tr>
78
     * <tr><td>   Z     </td><td> 3 digits alphanum creditor business code (CBC) </td></tr>
79
     * <tr><td>   b     </td><td> 3 digits numeric internal bank code (specific for Belgium) </td></tr>
80
     * <tr><td>   D     </td><td> 1 digit fixed 'D' character </td></tr>
81
     * <tr><td>   n     </td><td> 9 digits numeric increasing number issued by the Creditor Bank </td></tr>
82
     * </tbody></table>
83
     *
84
     * Length: 20
85
     *
86
     * <b>
87
     * The differentiation between the two formats is done through the length!
88
     * </b>
89
     *
90
     * @param string $strCI
91
     * @return int OK ( 0 ) or errorcode
92
     */
93
    public function validateCI(string $strCI) : int
94
    {
95
        // toupper, trim and remove containing blanks
96
        $strCheck = str_replace(' ', '', trim(strtoupper($strCI)));
97
        $strRegEx = '';
98
        $bAlphaNum = false;
99
        if (strlen($strCheck) == 17) {
100
            $strRegEx = '/^([A-Z]){2}([0-9]){2}([0-9A-Z]){3}([0-9]){10}?$/';
101
        } else if (strlen($strCheck) == 20) {
102
            $strRegEx = '/^([A-Z]){2}([0-9]){2}([0-9A-Z]){3}([0-9]){3}D([0-9]){9}?$/';
103
            $bAlphaNum = true;
104
        } else {
105
            return Sepa::ERR_CI_INVALID_LENGTH;
106
        }
107
108
        if (substr($strCheck, 0, 2) != $this->strCntry) {
109
            return Sepa::ERR_CI_INVALID_CNTRY;
110
        }
111
        if (!preg_match($strRegEx, $strCheck)) {
112
            return Sepa::ERR_CI_INVALID_SIGN;
113
        }
114
        $strCS = substr($strCheck, 2, 2);
115
        // NOTE: the CBC is not taken into account when calculating the checksum!
116
        $strCheck = substr($strCheck, 7);
117
        if ($bAlphaNum) {
118
            $strCheck = $this->replaceAlpha($strCheck);
119
        }
120
        if ($this->getCheckSum($strCheck) != $strCS) {
121
            return Sepa::ERR_CI_CHECKSUM;
122
        }
123
        return Sepa::OK;
124
    }
125
}