Payment::currencyCode()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace DummyGenerator\Core;
6
7
use DummyGenerator\Definitions\Extension\Awareness\GeneratorAwareExtensionInterface;
8
use DummyGenerator\Definitions\Extension\Awareness\GeneratorAwareExtensionTrait;
9
use DummyGenerator\Definitions\Extension\Awareness\IbanCalculatorAwareExtensionInterface;
10
use DummyGenerator\Definitions\Extension\Awareness\IbanCalculatorAwareExtensionTrait;
11
use DummyGenerator\Definitions\Extension\Awareness\LuhnCalculatorAwareExtensionInterface;
12
use DummyGenerator\Definitions\Extension\Awareness\LuhnCalculatorAwareExtensionTrait;
13
use DummyGenerator\Definitions\Extension\Awareness\RandomizerAwareExtensionInterface;
14
use DummyGenerator\Definitions\Extension\Awareness\RandomizerAwareExtensionTrait;
15
use DummyGenerator\Definitions\Extension\Awareness\ReplacerAwareExtensionInterface;
16
use DummyGenerator\Definitions\Extension\Awareness\ReplacerAwareExtensionTrait;
17
use DummyGenerator\Definitions\Extension\PaymentExtensionInterface;
18
19
class Payment implements
20
    PaymentExtensionInterface,
21
    GeneratorAwareExtensionInterface,
22
    RandomizerAwareExtensionInterface,
23
    IbanCalculatorAwareExtensionInterface,
24
    LuhnCalculatorAwareExtensionInterface,
25
    ReplacerAwareExtensionInterface
26
{
27
    use GeneratorAwareExtensionTrait;
28
    use RandomizerAwareExtensionTrait;
29
    use IbanCalculatorAwareExtensionTrait;
30
    use LuhnCalculatorAwareExtensionTrait;
31
    use ReplacerAwareExtensionTrait;
32
33
    public string $expirationDateFormat = 'm/y';
34
35
    /** @var string[] */
36
    protected array $cardVendors = [
37
        'Visa', 'Visa', 'Visa', 'Visa', 'Visa',
38
        'MasterCard', 'MasterCard', 'MasterCard', 'MasterCard', 'MasterCard',
39
        'American Express', 'Discover Card', 'Visa Retired', 'JCB',
40
    ];
41
42
    /**
43
     * @var array<string, mixed> List of card brand masks for generating valid credit card numbers
44
     *
45
     * @see https://en.wikipedia.org/wiki/Payment_card_number Reference for existing prefixes
46
     * @see https://www.mastercard.us/en-us/issuers/get-support/2-series-bin-expansion.html MasterCard 2017 2-Series BIN Expansion
47
     */
48
    protected array $cardParams = [
49
        'Visa' => [
50
            '4539###########',
51
            '4556###########',
52
            '4916###########',
53
            '4532###########',
54
            '4929###########',
55
            '40240071#######',
56
            '4485###########',
57
            '4716###########',
58
            '4##############',
59
        ],
60
        'Visa Retired' => [
61
            '4539########',
62
            '4556########',
63
            '4916########',
64
            '4532########',
65
            '4929########',
66
            '40240071####',
67
            '4485########',
68
            '4716########',
69
            '4###########',
70
        ],
71
        'MasterCard' => [
72
            '2221###########',
73
            '23#############',
74
            '24#############',
75
            '25#############',
76
            '26#############',
77
            '2720###########',
78
            '51#############',
79
            '52#############',
80
            '53#############',
81
            '54#############',
82
            '55#############',
83
        ],
84
        'American Express' => [
85
            '34############',
86
            '37############',
87
        ],
88
        'Discover Card' => [
89
            '6011###########',
90
        ],
91
        'JCB' => [
92
            '3528###########',
93
            '3589###########',
94
        ],
95
    ];
96
97
    /** @var array<string, mixed> list of IBAN formats, source: @see https://www.swift.com/standards/data-standards/iban */
98
    protected array $ibanFormats = [
99
        'AD' => [['n', 4], ['n', 4], ['c', 12]],
100
        'AE' => [['n', 3], ['n', 16]],
101
        'AL' => [['n', 8], ['c', 16]],
102
        'AT' => [['n', 5], ['n', 11]],
103
        'AZ' => [['a', 4], ['c', 20]],
104
        'BA' => [['n', 3], ['n', 3], ['n', 8], ['n', 2]],
105
        'BE' => [['n', 3], ['n', 7], ['n', 2]],
106
        'BG' => [['a', 4], ['n', 4], ['n', 2], ['c', 8]],
107
        'BH' => [['a', 4], ['c', 14]],
108
        'BR' => [['n', 8], ['n', 5], ['n', 10], ['a', 1], ['c', 1]],
109
        'CH' => [['n', 5], ['c', 12]],
110
        'CR' => [['n', 4], ['n', 14]],
111
        'CY' => [['n', 3], ['n', 5], ['c', 16]],
112
        'CZ' => [['n', 4], ['n', 6], ['n', 10]],
113
        'DE' => [['n', 8], ['n', 10]],
114
        'DK' => [['n', 4], ['n', 9], ['n', 1]],
115
        'DO' => [['c', 4], ['n', 20]],
116
        'EE' => [['n', 2], ['n', 2], ['n', 11], ['n', 1]],
117
        'EG' => [['n', 4], ['n', 4], ['n', 17]],
118
        'ES' => [['n', 4], ['n', 4], ['n', 1], ['n', 1], ['n', 10]],
119
        'FI' => [['n', 6], ['n', 7], ['n', 1]],
120
        'FR' => [['n', 5], ['n', 5], ['c', 11], ['n', 2]],
121
        'GB' => [['a', 4], ['n', 6], ['n', 8]],
122
        'GE' => [['a', 2], ['n', 16]],
123
        'GI' => [['a', 4], ['c', 15]],
124
        'GR' => [['n', 3], ['n', 4], ['c', 16]],
125
        'GT' => [['c', 4], ['c', 20]],
126
        'HR' => [['n', 7], ['n', 10]],
127
        'HU' => [['n', 3], ['n', 4], ['n', 1], ['n', 15], ['n', 1]],
128
        'IE' => [['a', 4], ['n', 6], ['n', 8]],
129
        'IL' => [['n', 3], ['n', 3], ['n', 13]],
130
        'IS' => [['n', 4], ['n', 2], ['n', 6], ['n', 10]],
131
        'IT' => [['a', 1], ['n', 5], ['n', 5], ['c', 12]],
132
        'KW' => [['a', 4], ['n', 22]],
133
        'KZ' => [['n', 3], ['c', 13]],
134
        'LB' => [['n', 4], ['c', 20]],
135
        'LI' => [['n', 5], ['c', 12]],
136
        'LT' => [['n', 5], ['n', 11]],
137
        'LU' => [['n', 3], ['c', 13]],
138
        'LV' => [['a', 4], ['c', 13]],
139
        'MC' => [['n', 5], ['n', 5], ['c', 11], ['n', 2]],
140
        'MD' => [['c', 2], ['c', 18]],
141
        'ME' => [['n', 3], ['n', 13], ['n', 2]],
142
        'MK' => [['n', 3], ['c', 10], ['n', 2]],
143
        'MR' => [['n', 5], ['n', 5], ['n', 11], ['n', 2]],
144
        'MT' => [['a', 4], ['n', 5], ['c', 18]],
145
        'MU' => [['a', 4], ['n', 2], ['n', 2], ['n', 12], ['n', 3], ['a', 3]],
146
        'NL' => [['a', 4], ['n', 10]],
147
        'NO' => [['n', 4], ['n', 6], ['n', 1]],
148
        'PK' => [['a', 4], ['c', 16]],
149
        'PL' => [['n', 8], ['n', 16]],
150
        'PS' => [['a', 4], ['c', 21]],
151
        'PT' => [['n', 4], ['n', 4], ['n', 11], ['n', 2]],
152
        'RO' => [['a', 4], ['c', 16]],
153
        'RS' => [['n', 3], ['n', 13], ['n', 2]],
154
        'SA' => [['n', 2], ['c', 18]],
155
        'SE' => [['n', 3], ['n', 16], ['n', 1]],
156
        'SI' => [['n', 5], ['n', 8], ['n', 2]],
157
        'SK' => [['n', 4], ['n', 6], ['n', 10]],
158
        'SM' => [['a', 1], ['n', 5], ['n', 5], ['c', 12]],
159
        'TN' => [['n', 2], ['n', 3], ['n', 13], ['n', 2]],
160
        'TR' => [['n', 5], ['n', 1], ['c', 16]],
161
        'VG' => [['a', 4], ['n', 16]],
162
    ];
163
164
    /**
165
     * @var string[]
166
     *
167
     * @link https://en.wikipedia.org/wiki/ISO_4217
168
     * On date of 2019-09-27
169
     *
170
     * With the following exceptions:
171
     * SVC has been replaced by the USD in 2001: https://en.wikipedia.org/wiki/Salvadoran_col%C3%B3n
172
     * ZWL has been suspended since 2009: https://en.wikipedia.org/wiki/Zimbabwean_dollar
173
     */
174
    protected array $currencyCode = array(
175
        'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN',
176
        'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BOV',
177
        'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BZD', 'CAD', 'CDF', 'CHE', 'CHF',
178
        'CHW', 'CLF', 'CLP', 'CNY', 'COP', 'COU', 'CRC', 'CUC', 'CUP', 'CVE',
179
        'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB', 'EUR', 'FJD',
180
        'FKP', 'GBP', 'GEL', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD',
181
        'HNL', 'HTG', 'HUF', 'IDR', 'ILS', 'INR', 'IQD', 'IRR', 'ISK', 'JMD',
182
        'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD',
183
        'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA',
184
        'MKD', 'MMK', 'MNT', 'MOP', 'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MXV',
185
        'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB',
186
        'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB',
187
        'RWF', 'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLE', 'SOS',
188
        'SRD', 'SSP', 'STN', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', 'TMT', 'TND',
189
        'TOP', 'TRY', 'TTD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'USN', 'UYI',
190
        'UYU', 'UYW', 'UZS', 'VED', 'VES', 'VND', 'VUV', 'WST', 'XAF', 'XAG',
191
        'XAU', 'XBA', 'XBB', 'XBC', 'XBD', 'XCD', 'XDR', 'XOF', 'XPD', 'XPF',
192
        'XPT', 'XSU', 'XTS', 'XUA', 'XXX', 'YER', 'ZAR', 'ZMW', 'ZWG',
193
    );
194
195 2
    public function creditCardType(): string
196
    {
197 2
        return $this->randomizer->randomElement($this->cardVendors);
198
    }
199
200 2
    public function creditCardNumber(?string $type = null, bool $formatted = false, string $separator = '-'): string
201
    {
202
203 2
        if (null === $type || !array_key_exists($type, $this->cardParams)) {
204 1
            $type = $this->creditCardType();
205
        }
206
207 2
        $mask = $this->randomizer->randomElement($this->cardParams[$type]);
208
209 2
        $number = $this->replacer->numerify($mask);
210 2
        $number .= $this->luhnCalculator->computeCheckDigit($number);
211
212 2
        if ($formatted) {
213 1
            $p1 = substr($number, 0, 4);
214 1
            $p2 = substr($number, 4, 4);
215 1
            $p3 = substr($number, 8, 4);
216 1
            $p4 = substr($number, 12);
217 1
            $number = $p1 . $separator . $p2 . $separator . $p3 . $separator . $p4;
218
        }
219
220 2
        return $number;
221
    }
222
223 1
    public function currencyCode(): string
224
    {
225 1
        return $this->randomizer->randomElement($this->currencyCode);
226
    }
227
228 2
    public function creditCardExpirationDate(bool $inFuture = true): string
229
    {
230 2
        if ($inFuture) {
231
            // @phpstan-ignore-next-line
232 1
            return $this->generator->dateTimeBetween('now', '36 months')->format($this->expirationDateFormat);
0 ignored issues
show
Bug introduced by
The method dateTimeBetween() does not exist on DummyGenerator\DummyGenerator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

232
            return $this->generator->/** @scrutinizer ignore-call */ dateTimeBetween('now', '36 months')->format($this->expirationDateFormat);
Loading history...
233
        }
234
235
        // @phpstan-ignore-next-line
236 1
        return $this->generator->dateTimeBetween('-36 months', '36 months')->format($this->expirationDateFormat);
237
    }
238
239 1
    public function creditCardDetails(bool $valid = true): array
240
    {
241 1
        $type = $this->creditCardType();
242
243 1
        return [
244 1
            'type' => $type,
245 1
            'number' => $this->creditCardNumber($type),
246
            // @phpstan-ignore-next-line
247 1
            'name' => $this->generator->name(),
0 ignored issues
show
Bug introduced by
The method name() does not exist on DummyGenerator\DummyGenerator. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
            'name' => $this->generator->/** @scrutinizer ignore-call */ name(),
Loading history...
248 1
            'expirationDate' => $this->creditCardExpirationDate($valid),
249 1
        ];
250
    }
251
252 4
    public function iban(?string $alpha2 = null, string $prefix = ''): string
253
    {
254 4
        $countryCode = null === $alpha2 ? $this->randomizer->randomKey($this->ibanFormats) : $this->replacer->toUpper($alpha2);
255
256 4
        $format = $this->ibanFormats[$countryCode] ?? null;
257
258 4
        if ($format === null) {
259 1
            $length = 24;
260 1
            $format = [['n', $length]];
261
        } else {
262 3
            $length = 0;
263
264 3
            foreach ($format as $part) {
265 3
                [$class, $groupCount] = $part;
266 3
                $length += $groupCount;
267
            }
268
        }
269
270 4
        $expandedFormat = '';
271
272 4
        foreach ($format as $item) {
273 4
            [$class, $length] = $item;
274 4
            $expandedFormat .= str_repeat($class, $length);
275
        }
276
277 4
        $result = $prefix;
278 4
        $expandedFormat = substr($expandedFormat, $this->replacer->strlen($result));
279
280 4
        foreach (str_split($expandedFormat) as $class) {
281
            switch ($class) {
282
                default:
283 4
                case 'c':
284 2
                    $result .= $this->randomizer->getBool() ? $this->randomizer->getInt(0, 9) : $this->replacer->toUpper($this->randomizer->randomLetter());
285
286 2
                    break;
287
288 3
                case 'a':
289 1
                    $result .= $this->replacer->toUpper($this->randomizer->randomLetter());
290
291 1
                    break;
292
293 2
                case 'n':
294 2
                    $result .= $this->randomizer->getInt(0, 9);
295
296 2
                    break;
297
            }
298
        }
299
300 4
        $checksum = $this->ibanCalculator->checksum($countryCode . '00' . $result);
301
302 4
        return $countryCode . $checksum . $result;
303
    }
304
305 1
    public function swiftBicNumber(): string
306
    {
307 1
        $bankCode = $this->replacer->lexify('????');
308 1
        $countryCode = $this->randomizer->randomElement(array_keys($this->ibanFormats));
309 1
        $locationCode = $this->replacer->lexify('??');
310 1
        $branchCode = $this->randomizer->getInt(100, 999);
311
312 1
        return $this->replacer->toUpper($bankCode . $countryCode . $locationCode) . $branchCode;
313
    }
314
}
315