Completed
Push — master ( 9be2e3...3a8fde )
by Gaël
14:21
created

PaymentRequest   A

Complexity

Total Complexity 41

Size/Duplication

Total Lines 332
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 108
dl 0
loc 332
rs 9.1199
c 1
b 0
f 0
wmc 41

19 Methods

Rating   Name   Duplication   Size   Complexity  
A fieldsToArray() 0 7 1
A setDisable3DS() 0 3 2
A getRequestUri() 0 3 1
A setBillingAddress() 0 3 1
A setSignLabel() 0 3 1
A validate() 0 15 4
A setDisabledPaymentWays() 0 11 3
A setClient() 0 3 1
A setCardAlias() 0 3 1
A setForceCard() 0 3 2
B optionsFields() 0 9 7
A urlFields() 0 5 1
A baseFields() 0 13 1
A setThreeDSecureChallenge() 0 7 2
A setCart() 0 3 1
A __construct() 0 15 1
A setShippingAddress() 0 3 1
A commitmentsFields() 0 13 5
A orderContextBase64() 0 10 5

How to fix   Complexity   

Complex Class

Complex classes like PaymentRequest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PaymentRequest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace DansMaCulotte\Monetico\Requests;
4
5
use DansMaCulotte\Monetico\Exceptions\Exception;
6
use DansMaCulotte\Monetico\Exceptions\PaymentException;
7
use DansMaCulotte\Monetico\Resources\BillingAddressResource;
8
use DansMaCulotte\Monetico\Resources\CartResource;
9
use DansMaCulotte\Monetico\Resources\ClientResource;
10
use DansMaCulotte\Monetico\Resources\ShippingAddressResource;
11
use DateTime;
12
13
class PaymentRequest extends AbstractRequest
14
{
15
    /** @var string */
16
    public $reference;
17
18
    /** @var string */
19
    public $description;
20
21
    /** @var string */
22
    public $language;
23
24
    /** @var string */
25
    public $email;
26
27
    /** @var float */
28
    public $amount;
29
30
    /** @var string */
31
    public $currency;
32
33
    /** @var \DateTime */
34
    public $dateTime;
35
36
    /** @var */
37
    public $successUrl;
38
39
    /** @var */
40
    public $errorUrl;
41
42
    /** @var array */
43
    public $options;
44
45
    /** @var BillingAddressResource */
46
    public $billingAddress;
47
48
    /** @var ShippingAddressResource */
49
    public $shippingAddress;
50
51
    /** @var ClientResource */
52
    public $client;
53
54
    /** @var CartResource */
55
    public $cart;
56
57
    /** @var array */
58
    public $commitments;
59
60
    /** @var int */
61
    const MAC_COMMITMENTS = 4;
62
63
    /** @var array */
64
    const PAYMENT_WAYS = [
65
        '1euro',
66
        '3xcb',
67
        '4xcb',
68
        'fivory',
69
        'paypal'
70
    ];
71
72
    /** @var array */
73
    const THREE_D_SECURE_CHALLENGES = [
74
        'no_preference',
75
        'challenge_preferred',
76
        'challenge_mandated',
77
        'no_challenge_requested',
78
        'no_challenge_requested_strong_authentication',
79
        'no_challenge_requested_trusted_third_party',
80
        'no_challenge_requested_risk_analysis'
81
    ];
82
83
    /** @var string */
84
    const DATETIME_FORMAT = 'd/m/Y:H:i:s';
85
86
    /** @var string */
87
    const REQUEST_URI = 'paiement.cgi';
88
89
    /**
90
     * InputPayload constructor.
91
     *
92
     * @param array $data
93
     * @param array $commitments
94
     * @param array $options
95
     * @throws Exception
96
     */
97
    public function __construct(array $data = [], array $commitments = [], array $options = [])
98
    {
99
        $this->reference = $data['reference'];
100
        $this->language = $data['language'];
101
        $this->dateTime = $data['dateTime'];
102
        $this->description = $data['description'];
103
        $this->email = $data['email'];
104
        $this->amount = $data['amount'];
105
        $this->currency = $data['currency'];
106
        $this->successUrl = $data['successUrl'];
107
        $this->errorUrl = $data['errorUrl'];
108
        $this->options = $options;
109
        $this->commitments = $commitments;
110
111
        $this->validate();
112
    }
113
114
    /**
115
     * @throws Exception
116
     */
117
    public function validate(): bool
118
    {
119
        if (strlen($this->reference) > 12) {
120
            throw Exception::invalidReference($this->reference);
121
        }
122
123
        if (strlen($this->language) != 2) {
124
            throw Exception::invalidLanguage($this->language);
125
        }
126
127
        if (!$this->dateTime instanceof DateTime) {
0 ignored issues
show
introduced by
$this->dateTime is always a sub-type of DateTime.
Loading history...
128
            throw Exception::invalidDatetime();
129
        }
130
131
        return true;
132
    }
133
134
    /**
135
     * @return string
136
     */
137
    protected static function getRequestUri(): string
138
    {
139
        return self::REQUEST_URI;
140
    }
141
142
    /**
143
     * Define card alias in case of an express payment
144
     *
145
     * @param string $alias Alias card name
146
     */
147
    public function setCardAlias(string $alias): void
148
    {
149
        $this->options['aliascb'] = $alias;
150
    }
151
152
    /**
153
     * Force submission of card informations in case of an express payment
154
     *
155
     * @param bool $value Enable or disable submission
156
     */
157
    public function setForceCard(bool $value = true): void
158
    {
159
        $this->options['forcesaisiecb'] = ($value) ? '1' : '0';
160
    }
161
162
    /**
163
     * Bypass 3DSecure check
164
     *
165
     * @param bool $value Enable or disable bypass
166
     */
167
    public function setDisable3DS(bool $value = true): void
168
    {
169
        $this->options['3dsdebrayable'] = ($value) ? '1' : '0';
170
    }
171
172
    /**
173
     * 3DSecure V2 Choice
174
     *
175
     * @param string $choice
176
     * @throws PaymentException
177
     */
178
    public function setThreeDSecureChallenge(string $choice): void
179
    {
180
        if (!in_array($choice, self::THREE_D_SECURE_CHALLENGES)) {
181
            throw PaymentException::invalidThreeDSecureChallenge($choice);
182
        }
183
184
        $this->options['threeDsecureChallenge'] = $choice;
185
    }
186
187
    /**
188
     * Change company sign label on payment interface
189
     *
190
     * @param string $label New sign label content
191
     */
192
    public function setSignLabel(string $label): void
193
    {
194
        $this->options['libelleMonetique'] = $label;
195
    }
196
197
    /**
198
     * @param BillingAddressResource $billingAddress
199
     */
200
    public function setBillingAddress(BillingAddressResource $billingAddress): void
201
    {
202
        $this->billingAddress = $billingAddress;
203
    }
204
205
206
    /**
207
     * @param ShippingAddressResource $shippingAddress
208
     */
209
    public function setShippingAddress(ShippingAddressResource $shippingAddress): void
210
    {
211
        $this->shippingAddress = $shippingAddress;
212
    }
213
214
    /**
215
     * @param ClientResource $client
216
     */
217
    public function setClient(ClientResource $client): void
218
    {
219
        $this->client = $client;
220
    }
221
222
    /**
223
     * @param CartResource $cart
224
     */
225
    public function setCart(CartResource $cart): void
226
    {
227
        $this->cart = $cart;
228
    }
229
230
    /**
231
     * Disable ways of payment on payment interface
232
     *
233
     * @param array[string] $ways List of payment ways to disable
0 ignored issues
show
Documentation Bug introduced by
The doc comment array[string] at position 1 could not be parsed: Expected ']' at position 1, but found '['.
Loading history...
234
     */
235
    public function setDisabledPaymentWays(array $ways = []): void
236
    {
237
        $_ways = [];
238
239
        foreach ($ways as $way) {
240
            if (in_array($way, self::PAYMENT_WAYS)) {
241
                array_push($_ways, $way);
242
            }
243
        }
244
245
        $this->options['desactivemoyenpaiement'] = join(',', $_ways);
246
    }
247
248
    /**
249
     * Get order context
250
     *
251
     * @return string
252
     */
253
    public function orderContextBase64(): string
254
    {
255
        $contextCommand = [
256
            'billing' => $this->billingAddress ? $this->billingAddress->getParameters() : [],
257
            'shipping' => $this->shippingAddress ? $this->shippingAddress->getParameters() : [],
258
            'client' => $this->client ? $this->client->getParameters() : [],
259
            'shoppingCart' => $this->cart ? $this->cart->getParameters() : [],
260
        ];
261
262
        return base64_encode(json_encode($contextCommand));
263
    }
264
265
    /**
266
     * @param string $eptCode
267
     * @param string $companyCode
268
     * @param string $version
269
     * @return array
270
     */
271
    private function baseFields(string $eptCode, string $companyCode, string $version): array
272
    {
273
        return [
274
            'TPE' => $eptCode,
275
            'date' => $this->dateTime->format(self::DATETIME_FORMAT),
276
            'contexte_commande' => $this->orderContextBase64(),
277
            'lgue' => $this->language,
278
            'mail' => $this->email,
279
            'montant' => $this->amount . $this->currency,
280
            'reference' => $this->reference,
281
            'societe' => $companyCode,
282
            'texte-libre' => $this->description,
283
            'version' => $version
284
        ];
285
    }
286
287
    /**
288
     * @return array
289
     */
290
    private function urlFields(): array
291
    {
292
        return [
293
            'url_retour_ok' => $this->successUrl,
294
            'url_retour_err' => $this->errorUrl,
295
        ];
296
    }
297
298
    /**
299
     * @return array
300
     */
301
    private function commitmentsFields(): array
302
    {
303
        $commitmentsCount = count($this->commitments);
304
        $commitments = [
305
            'nbrech' => ($commitmentsCount > 0) ? $commitmentsCount : ''
306
        ];
307
308
        for ($i = 1; $i <= self::MAC_COMMITMENTS; $i++) {
309
            $commitments["dateech${i}"] = ($commitmentsCount >= $i) ? $this->commitments[$i - 1]['date'] : '';
310
            $commitments["montantech${i}"] = ($commitmentsCount >= $i) ? $this->commitments[$i - 1]['amount'] . $this->currency : '';
311
        }
312
313
        return $commitments;
314
    }
315
316
    /**
317
     * @return array
318
     */
319
    private function optionsFields(): array
320
    {
321
        return [
322
            'ThreeDSecureChallenge' => (isset($this->options['threeDsecureChallenge'])) ? $this->options['threeDsecureChallenge'] : '',
323
            '3dsdebrayable' => (isset($this->options['3dsdebrayable'])) ? $this->options['3dsdebrayable'] : '',
324
            'aliascb' => (isset($this->options['aliascb'])) ? $this->options['aliascb'] : '',
325
            'desactivemoyenpaiement' => (isset($this->options['desactivemoyenpaiement'])) ? $this->options['desactivemoyenpaiement'] : '',
326
            'forcesaisiecb' => (isset($this->options['forcesaisiecb'])) ? $this->options['forcesaisiecb'] : '',
327
            'libelleMonetique' => (isset($this->options['libelleMonetique'])) ? $this->options['libelleMonetique'] : '',
328
        ];
329
    }
330
331
    /**
332
     * @param string $eptCode
333
     * @param string $companyCode
334
     * @param string $version
335
     * @param array $options
336
     * @return array
337
     */
338
    public function fieldsToArray(string $eptCode, string $companyCode, string $version): array
339
    {
340
        return array_merge(
341
            $this->baseFields($eptCode, $companyCode, $version),
342
            $this->optionsFields(),
343
            $this->commitmentsFields(),
344
            $this->urlFields()
345
        );
346
    }
347
}
348