InstallmentPlan   A
last analyzed

Complexity

Total Complexity 39

Size/Duplication

Total Lines 366
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 132
dl 0
loc 366
rs 9.28
c 0
b 0
f 0
wmc 39

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getNumberFromString() 0 8 2
A getInstallmentPlanRatepay() 0 24 3
A formatInstallmentOptions() 0 24 4
A getPayDataArray() 0 13 2
A getInstallmentPlan() 0 24 6
A parseResponse() 0 23 6
A getInstallmentPlanBNPL() 0 20 2
A __construct() 0 24 1
A getAllowedMonths() 0 13 1
B checkForErrors() 0 14 10
A setInstallmentDraftDownloadLinks() 0 7 2
1
<?php
2
3
/**
4
 * PAYONE Magento 2 Connector is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * PAYONE Magento 2 Connector is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with PAYONE Magento 2 Connector. If not, see <http://www.gnu.org/licenses/>.
16
 *
17
 * PHP version 5
18
 *
19
 * @category  Payone
20
 * @package   Payone_Magento2_Plugin
21
 * @author    FATCHIP GmbH <[email protected]>
22
 * @copyright 2003 - 2017 Payone GmbH
23
 * @license   <http://www.gnu.org/licenses/> GNU Lesser General Public License
24
 * @link      http://www.payone.de
25
 */
26
27
namespace Payone\Core\Service\V1;
28
29
use Payone\Core\Api\InstallmentPlanInterface;
30
use Payone\Core\Helper\Api;
31
use Payone\Core\Service\V1\Data\InstallmentPlanResponse;
32
use Payone\Core\Api\Data\InstallmentPlanResponseInterfaceFactory;
0 ignored issues
show
Bug introduced by
The type Payone\Core\Api\Data\Ins...esponseInterfaceFactory was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use Magento\Checkout\Model\Session;
0 ignored issues
show
Bug introduced by
The type Magento\Checkout\Model\Session was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use Payone\Core\Model\Api\Request\Genericpayment\Calculation;
35
use Payone\Core\Model\Api\Request\Genericpayment\PreCheck;
36
use Payone\Core\Model\Api\Request\Genericpayment\InstallmentOptions;
37
use Payone\Core\Model\Methods\Payolution\Installment;
38
use Payone\Core\Block\Payolution\InstallmentPlan as Block;
39
use Payone\Core\Block\BNPL\InstallmentPlan as BNPLBlock;
40
use Payone\Core\Helper\Ratepay;
41
use Payone\Core\Model\Methods\Ratepay\Installment as RatepayInstallment;
42
43
/**
44
 * Web API model for the PAYONE addresscheck
45
 */
46
class InstallmentPlan implements InstallmentPlanInterface
47
{
48
    /**
49
     * Factory for the response object
50
     *
51
     * @var InstallmentPlanResponseInterfaceFactory
52
     */
53
    protected $responseFactory;
54
55
    /**
56
     * Checkout session object
57
     *
58
     * @var Session
59
     */
60
    protected $checkoutSession;
61
62
    /**
63
     * Calculation Genericpayment request object
64
     *
65
     * @var Calculation
66
     */
67
    protected $calculation;
68
69
    /**
70
     * Payone Payolution Installment payment method
71
     *
72
     * @var Installment
73
     */
74
    protected $payolution;
75
76
    /**
77
     * InstallmentRate Block object
78
     *
79
     * @var Block
80
     */
81
    protected $block;
82
83
    /**
84
     * PreCheck Genericpayment request object
85
     *
86
     * @var PreCheck
87
     */
88
    protected $precheck;
89
90
    /**
91
     * @var Ratepay
92
     */
93
    protected $ratepayHelper;
94
95
    /**
96
     * @var RatepayInstallment
97
     */
98
    protected $ratepayInstallment;
99
100
    /**
101
     * @var Api
102
     */
103
    protected $apiHelper;
104
105
    /**
106
     * InstallmentOptions Genericpayment request object
107
     *
108
     * @var InstallmentOptions
109
     */
110
    protected $installmentOptions;
111
112
    /**
113
     * @var BNPLBlock
114
     */
115
    protected $bnplBlock;
116
117
    /**
118
     * Constructor.
119
     *
120
     * @param InstallmentPlanResponseInterfaceFactory $responseFactory
121
     * @param Session                                 $checkoutSession
122
     * @param PreCheck                                $precheck
123
     * @param Calculation                             $calculation
124
     * @param Installment                             $payolution
125
     * @param Block                                   $block
126
     * @param Ratepay                                 $ratepayHelper
127
     * @param RatepayInstallment                      $ratepayInstallment
128
     * @param Api                                     $apiHelper
129
     * @param InstallmentOptions                      $installmentOptions
130
     * @param BNPLBlock                               $bnplBlock
131
     */
132
    public function __construct(
133
        InstallmentPlanResponseInterfaceFactory $responseFactory,
134
        Session $checkoutSession,
135
        PreCheck $precheck,
136
        Calculation $calculation,
137
        Installment $payolution,
138
        Block $block,
139
        Ratepay $ratepayHelper,
140
        RatepayInstallment $ratepayInstallment,
141
        Api $apiHelper,
142
        InstallmentOptions $installmentOptions,
143
        BNPLBlock $bnplBlock
144
    ) {
145
        $this->responseFactory = $responseFactory;
146
        $this->checkoutSession = $checkoutSession;
147
        $this->precheck = $precheck;
148
        $this->calculation = $calculation;
149
        $this->payolution = $payolution;
150
        $this->block = $block;
151
        $this->ratepayInstallment = $ratepayInstallment;
152
        $this->ratepayHelper = $ratepayHelper;
153
        $this->apiHelper = $apiHelper;
154
        $this->installmentOptions = $installmentOptions;
155
        $this->bnplBlock = $bnplBlock;
156
    }
157
158
    /**
159
     * Write installment draft download link array to session
160
     *
161
     * @param  $aInstallmentData
162
     * @return void
163
     */
164
    protected function setInstallmentDraftDownloadLinks($aInstallmentData)
165
    {
166
        $aDownloadLinks = array();
167
        foreach ($aInstallmentData as $aInstallment) {
168
            $aDownloadLinks[$aInstallment['duration']] = $aInstallment['standardcreditinformationurl'];
169
        }
170
        $this->checkoutSession->setInstallmentDraftLinks($aDownloadLinks);
171
    }
172
173
    /**
174
     * Check responses for errors and add them to the response object if needed
175
     *
176
     * @param  InstallmentPlanResponse $oResponse
177
     * @param  array                   $aResponsePreCheck
178
     * @param  array                   $aResponseCalculation
179
     * @return InstallmentPlanResponse
180
     */
181
    protected function checkForErrors($oResponse, $aResponsePreCheck, $aResponseCalculation)
182
    {
183
        $sErrorMessage = false;
184
        if (isset($aResponsePreCheck['status']) && $aResponsePreCheck['status'] == 'ERROR') {
185
            $sErrorMessage = __($aResponsePreCheck['errorcode'] . ' - ' . $aResponsePreCheck['customermessage']);
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

185
            $sErrorMessage = /** @scrutinizer ignore-call */ __($aResponsePreCheck['errorcode'] . ' - ' . $aResponsePreCheck['customermessage']);
Loading history...
186
        } elseif (isset($aResponseCalculation['status']) && $aResponseCalculation['status'] == 'ERROR') {
187
            $sErrorMessage = __($aResponseCalculation['errorcode'] . ' - ' . $aResponseCalculation['customermessage']);
188
        } elseif (!$aResponsePreCheck || (isset($aResponsePreCheck['status']) && $aResponsePreCheck['status'] == 'OK' && !$aResponseCalculation)) {
189
            $sErrorMessage = __('An unknown error occurred');
190
        }
191
        if ($sErrorMessage !== false) {
192
            $oResponse->setData('errormessage', $sErrorMessage);
193
        }
194
        return $oResponse;
195
    }
196
197
    /**
198
     * PAYONE addresscheck
199
     * The full class-paths must be given here otherwise the Magento 2 WebApi
200
     * cant handle this with its fake type system!
201
     *
202
     * @param  string $cartId
203
     * @param  string $birthday
204
     * @param  string $email
205
     * @return \Payone\Core\Service\V1\Data\InstallmentPlanResponse
206
     */
207
    public function getInstallmentPlan($cartId, $birthday, $email = false)
208
    {
209
        $oResponse = $this->responseFactory->create();
210
        $oResponse->setData('success', false); // set success to false as default, set to true later if true
211
212
        $oQuote = $this->checkoutSession->getQuote();
213
        $aResponsePreCheck = $this->precheck->sendRequest($this->payolution, $oQuote, false, $birthday, $email);
214
        $aResponseCalculation = false;
215
        if (isset($aResponsePreCheck['status']) && $aResponsePreCheck['status'] == 'OK') {
216
            $aResponseCalculation = $this->calculation->sendRequest($this->payolution, $oQuote);
217
            $aInstallmentData = $this->parseResponse($aResponseCalculation);
218
            if (isset($aResponseCalculation['status']) && $aResponseCalculation['status'] == 'OK' && $aInstallmentData !== false) {
219
                $oResponse->setData('success', true); // set success to false as default, set to true later if true
220
                $this->setInstallmentDraftDownloadLinks($aInstallmentData);
221
                $this->checkoutSession->setInstallmentWorkorderId($aResponseCalculation['workorderid']);
222
223
                $this->block->setInstallmentData($aInstallmentData);
224
                $this->block->setCode($this->payolution->getCode());
225
226
                $oResponse->setData('installmentPlanHtml', $this->block->toHtml());
227
            }
228
        }
229
        $oResponse = $this->checkForErrors($oResponse, $aResponsePreCheck, $aResponseCalculation);
230
        return $oResponse;
231
    }
232
233
    /**
234
     * PAYONE addresscheck
235
     * The full class-paths must be given here otherwise the Magento 2 WebApi
236
     * cant handle this with its fake type system!
237
     *
238
     * @param  string $cartId
239
     * @param  string $calcType
240
     * @param  int $calcValue
241
     * @return \Payone\Core\Service\V1\Data\InstallmentPlanResponse
242
     */
243
    public function getInstallmentPlanRatepay($cartId, $calcType, $calcValue)
244
    {
245
        $oResponse = $this->responseFactory->create();
246
        $oResponse->setData('success', false); // set success to false as default, set to true later if true
247
248
        $oQuote = $this->checkoutSession->getQuote();
249
250
        $sRatepayShopId = $this->ratepayHelper->getRatepayShopId($this->ratepayInstallment->getCode(), $oQuote->getBillingAddress()->getCountryId(), $this->apiHelper->getCurrencyFromQuote($oQuote), $this->apiHelper->getQuoteAmount($oQuote));
251
252
        $aResponseCalculation = $this->calculation->sendRequestRatepay($this->ratepayInstallment, $oQuote, $sRatepayShopId, $calcType, $calcValue);
253
        if ($aResponseCalculation['status'] == "OK") {
254
            unset($aResponseCalculation['status']);
255
            unset($aResponseCalculation['workorderid']);
256
            $aInstallmentPlan = [];
257
            foreach ($aResponseCalculation as $sKey => $sValue) {
258
                $sKey = str_replace("add_paydata", "", $sKey);
259
                $sKey = str_replace(["[", "]"], "", $sKey);
260
                $sKey = str_replace("-", "_", $sKey);
261
                $aInstallmentPlan[$sKey] = $sValue;
262
            }
263
            $oResponse->setData('installmentPlan', json_encode($aInstallmentPlan));
264
            $oResponse->setData('success', true);
265
        }
266
        return $oResponse;
267
    }
268
269
    /**
270
     * Extract number from given string
271
     *
272
     * @param  string $sString
273
     * @return string|false
274
     */
275
    protected function getNumberFromString($sString)
276
    {
277
        preg_match('/^[^0-9]*_([0-9])$/m', $sString, $matches);
278
279
        if (count($matches) == 2) {
280
            return $matches[1];
281
        }
282
        return false;
283
    }
284
285
    protected function formatInstallmentOptions($aResponse)
286
    {
287
        unset($aResponse['status']);
288
        unset($aResponse['workorderid']);
289
290
        $aInstallmentOptions = ['runtimes' => []];
291
292
        foreach ($aResponse as $sKey => $sValue) {
293
            $sKey = str_replace("add_paydata", "", $sKey);
294
            $sKey = str_replace(["[", "]"], "", $sKey);
295
            $sKey = str_replace("-", "_", $sKey);
296
297
            $iIndex = $this->getNumberFromString($sKey);
298
            if ($iIndex !== false) {
299
                $sKey = str_replace("_".$iIndex, "", $sKey);
300
                if (!isset($aInstallmentOptions['runtimes'][$iIndex])) {
301
                    $aInstallmentOptions['runtimes'][$iIndex] = [];
302
                }
303
                $aInstallmentOptions['runtimes'][$iIndex][$sKey] = $sValue;
304
            } else {
305
                $aInstallmentOptions[$sKey] = $sValue;
306
            }
307
        }
308
        return $aInstallmentOptions;
309
    }
310
311
    /**
312
     * PAYONE BNPL installment plan getter
313
     * The full class-paths must be given here otherwise the Magento 2 WebApi
314
     * cant handle this with its fake type system!
315
     *
316
     * @param  string $cartId
317
     * @param  string $paymentCode
318
     * @return \Payone\Core\Service\V1\Data\InstallmentPlanResponse
319
     */
320
    public function getInstallmentPlanBNPL($cartId, $paymentCode)
321
    {
322
        $oResponse = $this->responseFactory->create();
323
        $oResponse->setData('success', false); // set success to false as default, set to true later if true
324
325
        $oQuote = $this->checkoutSession->getQuote();
326
327
        $aResponseCalculation = $this->installmentOptions->sendRequest($oQuote, $paymentCode);
328
329
        if ($aResponseCalculation['status'] == "OK") {
330
            $this->checkoutSession->setInstallmentWorkorderId($aResponseCalculation['workorderid']);
331
            $aInstallmentPlan = $this->formatInstallmentOptions($aResponseCalculation);
332
333
            $this->bnplBlock->setInstallmentData($aInstallmentPlan);
334
            $this->bnplBlock->setCode($paymentCode);
335
336
            $oResponse->setData('installmentPlanHtml', $this->bnplBlock->toHtml());
337
            $oResponse->setData('success', true);
338
        }
339
        return $oResponse;
340
    }
341
342
    /**
343
     * Collects allowed runtimes afterwards
344
     * Needed for guest checkout since the billing country is not known when checkout is loaded
345
     *
346
     * @param  string $cartId
347
     * @return \Payone\Core\Service\V1\Data\InstallmentPlanResponse
348
     */
349
    public function getAllowedMonths($cartId)
350
    {
351
        $oResponse = $this->responseFactory->create();
352
        $oResponse->setData('success', false); // set success to false as default, set to true later if true
353
354
        $oQuote = $this->checkoutSession->getQuote();
355
356
        $aAllowedMonths = $this->ratepayInstallment->getAllowedMonths($oQuote);
357
358
        $oResponse->setData('allowedMonths', json_encode($aAllowedMonths));
359
        $oResponse->setData('success', true);
360
361
        return $oResponse;
362
    }
363
364
    /**
365
     * @param array $aResponse
366
     * @return array
367
     */
368
    public function getPayDataArray($aResponse)
369
    {
370
        $aPayData = array();
371
        foreach($aResponse as $sKey => $sValue) {
372
            $sCorrectedKey = str_ireplace('add_paydata[', '', $sKey);
373
            $sCorrectedKey = rtrim($sCorrectedKey, ']');
0 ignored issues
show
Bug introduced by
It seems like $sCorrectedKey can also be of type array; however, parameter $string of rtrim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

373
            $sCorrectedKey = rtrim(/** @scrutinizer ignore-type */ $sCorrectedKey, ']');
Loading history...
374
            $sCorrectedKey = strtolower($sCorrectedKey);
375
            $sCorrectedKey = str_replace('-', '_', $sCorrectedKey);
376
            $aPayData[$sCorrectedKey] = $sValue;
377
        }
378
379
        ksort($aPayData);
380
        return $aPayData;
381
    }
382
383
    /**
384
     * Parse the response array into a readable array
385
     *
386
     * @param $aResponse
387
     * @return array|false
388
     */
389
    protected function parseResponse($aResponse)
390
    {
391
        $aInstallmentData = array();
392
393
        $aPayData = $this->getPayDataArray($aResponse);
394
        foreach ($aPayData as $sKey => $sValue) {
395
            $aSplit = explode('_', $sKey);
396
            for($i = count($aSplit); $i > 0; $i--) {
397
                if($i == count($aSplit)) {
398
                    $aTmp = array($aSplit[$i-1] => $sValue);
399
                } else {
400
                    $aTmp = array($aSplit[$i-1] => $aTmp);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $aTmp does not seem to be defined for all execution paths leading up to this point.
Loading history...
401
                }
402
            }
403
404
            $aInstallmentData = array_replace_recursive($aInstallmentData, $aTmp);
405
        }
406
407
        if(isset($aInstallmentData['paymentdetails']) && count($aInstallmentData['paymentdetails']) > 0) {
408
            return $aInstallmentData['paymentdetails'];
409
        }
410
411
        return false;
412
    }
413
}
414