Passed
Pull Request — master (#395)
by
unknown
02:44
created

Debit::getCreditMemoData()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 13
c 1
b 0
f 0
nc 9
nop 1
dl 0
loc 19
rs 9.2222
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 - 2016 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\Model\Api\Request;
28
29
use Magento\Framework\Exception\LocalizedException;
0 ignored issues
show
Bug introduced by
The type Magento\Framework\Exception\LocalizedException 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...
30
use Magento\Sales\Model\Order;
0 ignored issues
show
Bug introduced by
The type Magento\Sales\Model\Order 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...
31
use Magento\Sales\Model\Order\Creditmemo;
0 ignored issues
show
Bug introduced by
The type Magento\Sales\Model\Order\Creditmemo 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...
32
use Payone\Core\Model\Methods\PayoneMethod;
33
use Magento\Payment\Model\InfoInterface;
0 ignored issues
show
Bug introduced by
The type Magento\Payment\Model\InfoInterface 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
35
/**
36
 * Class for the PAYONE Server API request "debit"
37
 */
38
class Debit extends Base
39
{
40
    /**
41
     * @var \Payone\Core\Model\Api\Invoice $invoiceGenerator
42
     */
43
    protected $invoiceGenerator;
44
45
    /**
46
     * PAYONE database helper
47
     *
48
     * @var \Payone\Core\Helper\Database
49
     */
50
    protected $databaseHelper;
51
52
    /**
53
     * PAYONE toolkit helper
54
     *
55
     * @var \Payone\Core\Helper\Toolkit
56
     */
57
    protected $toolkitHelper;
58
59
60
    const AREA_CODE = \Magento\Framework\App\Area::AREA_ADMINHTML;
0 ignored issues
show
Bug introduced by
The type Magento\Framework\App\Area 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...
61
62
    /**
63
     * State resolving
64
     *
65
     * @var \Magento\Framework\App\State
0 ignored issues
show
Bug introduced by
The type Magento\Framework\App\State 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...
66
     */
67
    protected $state;
68
69
    /**
70
     * Constructor
71
     *
72
     * @param \Payone\Core\Helper\Shop                $shopHelper
73
     * @param \Payone\Core\Helper\Environment         $environmentHelper
74
     * @param \Payone\Core\Helper\Api                 $apiHelper
75
     * @param \Payone\Core\Model\ResourceModel\ApiLog $apiLog
76
     * @param \Payone\Core\Model\Api\Invoice          $invoiceGenerator
77
     * @param \Payone\Core\Helper\Database            $databaseHelper
78
     * @param \Payone\Core\Helper\Toolkit             $toolkitHelper
79
     * @param \Magento\Framework\App\State            $state
80
     */
81
    public function __construct(
82
        \Payone\Core\Helper\Shop $shopHelper,
83
        \Payone\Core\Helper\Environment $environmentHelper,
84
        \Payone\Core\Helper\Api $apiHelper,
85
        \Payone\Core\Model\ResourceModel\ApiLog $apiLog,
86
        \Payone\Core\Model\Api\Invoice $invoiceGenerator,
87
        \Payone\Core\Helper\Database $databaseHelper,
88
        \Payone\Core\Helper\Toolkit $toolkitHelper,
89
        \Magento\Framework\App\State $state
90
    ) {
91
        parent::__construct($shopHelper, $environmentHelper, $apiHelper, $apiLog);
92
        $this->invoiceGenerator = $invoiceGenerator;
93
        $this->databaseHelper = $databaseHelper;
94
        $this->toolkitHelper = $toolkitHelper;
95
        $this->state = $state;
96
    }
97
98
    /**
99
     * Get creditmemo array from request parameters
100
     *
101
     * @return mixed
102
     */
103
    protected function getCreditmemoRequestParams()
104
    {
105
        return $this->shopHelper->getRequestParameter('creditmemo');
106
    }
107
108
    /**
109
     * Generate position list for invoice data transmission
110
     *
111
     * @param  Order      $oOrder
112
     * @param  Creditmemo $oCreditmemo
113
     * @return array|false
114
     */
115
    protected function getInvoiceList(Order $oOrder, Creditmemo $oCreditmemo)
116
    {
117
        $aCreditmemo = $this->getCreditmemoRequestParams();
118
119
        if (empty($aCreditmemo) && $this->state->getAreaCode() != self::AREA_CODE) {
120
            $aCreditmemo = $this->getCreditMemoData($oCreditmemo);
121
        }
122
123
        $aPositions = [];
124
        $blFull = true;
125
        if ($aCreditmemo && array_key_exists('items', $aCreditmemo) !== false) {
126
            foreach ($oOrder->getAllItems() as $oItem) {
127
                if (isset($aCreditmemo['items'][$oItem->getItemId()]) && $aCreditmemo['items'][$oItem->getItemId()]['qty'] > 0) {
128
                    $aPositions[$oItem->getProductId().$oItem->getSku()] = $aCreditmemo['items'][$oItem->getItemId()]['qty'];
129
                    if ($aCreditmemo['items'][$oItem->getItemId()]['qty'] != $oItem->getQtyOrdered()) {
130
                        $blFull = false;
131
                    }
132
                } elseif (!$oItem->getParentItemId()) { // dont set invoice list to not full on variant dummy items
133
                    $blFull = false;
134
                }
135
            }
136
        }
137
        if (isset($aCreditmemo['shipping_amount']) && $aCreditmemo['shipping_amount'] != 0) {
138
            $aPositions['delcost'] = $oCreditmemo->getBaseShippingInclTax();
139
            if ($this->shopHelper->getConfigParam('currency', 'global', 'payone_general', $this->storeCode) == 'display') {
140
                $aPositions['delcost'] = $oCreditmemo->getShippingInclTax();
141
            }
142
        }
143
        if ($blFull !== true && $oCreditmemo->getBaseDiscountAmount() != 0) {
144
            $aPositions['discount'] = $oCreditmemo->getBaseDiscountAmount();
145
            if ($this->shopHelper->getConfigParam('currency', 'global', 'payone_general', $this->storeCode) == 'display') {
146
                $aPositions['discount'] = $oCreditmemo->getDiscountAmount();
147
            }
148
        }
149
        if ($blFull === true && (!isset($aCreditmemo['shipping_amount']) || $aCreditmemo['shipping_amount'] == $oOrder->getBaseShippingInclTax())) {
150
            $aPositions = false; // false = full debit
151
        }
152
        return $aPositions;
153
    }
154
155
    /**
156
     * Send request "debit" to PAYONE server API
157
     *
158
     * @param  PayoneMethod  $oPayment
159
     * @param  InfoInterface $oPaymentInfo
160
     * @param  float         $dAmount
161
     * @return array
162
     */
163
    public function sendRequest(PayoneMethod $oPayment, InfoInterface $oPaymentInfo, $dAmount)
164
    {
165
        $oOrder = $oPaymentInfo->getOrder();
166
167
        $this->setStoreCode($oOrder->getStore()->getCode());
168
169
        $oCreditmemo = $oPaymentInfo->getCreditmemo();
170
        $aPositions = $this->getInvoiceList($oOrder, $oCreditmemo);
171
172
        $iTxid = $oPaymentInfo->getParentTransactionId();
173
        if (strpos($iTxid, '-') !== false) {
174
            $iTxid = substr($iTxid, 0, strpos($iTxid, '-')); // clean the txid from the magento-suffixes
175
        }
176
177
        $this->setOrderId($oOrder->getRealOrderId());
178
179
        $this->addParameter('request', 'debit'); // Request method
180
        $this->addParameter('mode', $oPayment->getOperationMode()); // PayOne Portal Operation Mode (live or test)
181
        $this->addParameter('txid', $iTxid); // PayOne Transaction ID
182
        $this->addParameter('sequencenumber', $this->databaseHelper->getSequenceNumber($iTxid));
183
184
        // Total order sum in smallest currency unit
185
        $this->addParameter('amount', number_format((-1 * $dAmount), 2, '.', '') * 100); // add price to request
186
        $this->addParameter('currency', $this->apiHelper->getCurrencyFromOrder($oOrder)); // add currency to request
187
188
        $this->addParameter('transactiontype', 'GT');
189
190
        $sRefundAppendix = $this->getRefundAppendix($oOrder, $oPayment);
191
        if (!empty($sRefundAppendix)) {
192
            $this->addParameter('invoiceappendix', $sRefundAppendix);
193
        }
194
195
        if ($this->apiHelper->isInvoiceDataNeeded($oPayment, $aPositions)) {
0 ignored issues
show
Bug introduced by
It seems like $aPositions can also be of type false; however, parameter $aPositions of Payone\Core\Helper\Api::isInvoiceDataNeeded() does only seem to accept array|null, 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

195
        if ($this->apiHelper->isInvoiceDataNeeded($oPayment, /** @scrutinizer ignore-type */ $aPositions)) {
Loading history...
196
            $this->invoiceGenerator->addProductInfo($this, $oOrder, $aPositions, true); // add invoice parameters
0 ignored issues
show
Bug introduced by
It seems like $aPositions can also be of type false; however, parameter $aPositions of Payone\Core\Model\Api\Invoice::addProductInfo() does only seem to accept array, 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

196
            $this->invoiceGenerator->addProductInfo($this, $oOrder, /** @scrutinizer ignore-type */ $aPositions, true); // add invoice parameters
Loading history...
197
        }
198
199
        $aCreditmemo = $this->getCreditmemoRequestParams();
200
        $sIban = false;
201
        $sBic = false;
202
        if (!empty($oOrder->getPayoneRefundIban()) && !empty($oOrder->getPayoneRefundBic())) {
203
            $sIban = $oOrder->getPayoneRefundIban();
204
            $sBic = $oOrder->getPayoneRefundBic();
205
        } elseif (isset($aCreditmemo['payone_iban']) && isset($aCreditmemo['payone_bic'])) {
206
            $sIban = $aCreditmemo['payone_iban'];
207
            $sBic = $aCreditmemo['payone_bic'];
208
        }
209
210
        if ($sIban !== false && $sBic !== false && $this->isSepaDataValid($sIban, $sBic)) {
211
            $this->addParameter('iban', $sIban);
212
            $this->addParameter('bic', $sBic);
213
        }
214
215
        $this->aParameters = array_merge($this->aParameters, $oPayment->getPaymentSpecificDebitParameters($oOrder));
216
217
        $aResponse = $this->send($oPayment);
218
219
        return $aResponse;
220
    }
221
222
    /**
223
     * Get substituted refund appendix text
224
     *
225
     * @param  Order        $oOrder
226
     * @param  PayoneMethod $oPayment
227
     * @return string
228
     */
229
    protected function getRefundAppendix(Order $oOrder, PayoneMethod $oPayment)
230
    {
231
        $sText = $this->shopHelper->getConfigParam('invoice_appendix_refund', 'invoicing', 'payone_general', $this->storeCode);
232
        $sCreditMemoIncrId = '';
233
        $sInvoiceIncrementId = '';
234
        $sInvoiceId = '';
235
236
        $oCreditmemo = $oPayment->getCreditmemo();
237
        if ($oCreditmemo) {
238
            $sCreditMemoIncrId = $oCreditmemo->getIncrementId();
239
            $oInvoice = $oCreditmemo->getInvoice();
240
            if ($oInvoice) {
241
                $sInvoiceIncrementId = $oInvoice->getIncrementId();
242
                $sInvoiceId = $oInvoice->getId();
243
            }
244
        }
245
246
        $aSubstitutionArray = [
247
            '{{order_increment_id}}' => $oOrder->getIncrementId(),
248
            '{{order_id}}' => $oOrder->getId(),
249
            '{{customer_id}}' => $oOrder->getCustomerId(),
250
            '{{creditmemo_increment_id}}' => $sCreditMemoIncrId,
251
            '{{invoice_increment_id}}' => $sInvoiceIncrementId,
252
            '{{invoice_id}}' => $sInvoiceId,
253
        ];
254
        $sRefundAppendix = $this->toolkitHelper->handleSubstituteReplacement($sText, $aSubstitutionArray, 255);
0 ignored issues
show
Bug introduced by
$aSubstitutionArray of type array is incompatible with the type string expected by parameter $aSubstitutionArray of Payone\Core\Helper\Toolk...SubstituteReplacement(). ( Ignorable by Annotation )

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

254
        $sRefundAppendix = $this->toolkitHelper->handleSubstituteReplacement($sText, /** @scrutinizer ignore-type */ $aSubstitutionArray, 255);
Loading history...
255
        return $sRefundAppendix;
256
    }
257
258
    /**
259
     * Validate IBAN
260
     *
261
     * @param  string $sIban
262
     * @return bool
263
     */
264
    protected function isIbanValid($sIban)
265
    {
266
        $sRegex = '/^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}(?:[a-zA-Z0-9]?){0,16}$/';
267
        return $this->checkRegex($sRegex, $sIban);
268
    }
269
270
    /**
271
     * Check if the regex validates correctly
272
     *
273
     * @param  string $sRegex
274
     * @param  string $sValue
275
     * @return bool
276
     */
277
    protected function checkRegex($sRegex, $sValue)
278
    {
279
        preg_match($sRegex, str_replace(' ', '', $sValue), $aMatches);
280
        if (empty($aMatches)) {
281
            return false;
282
        }
283
        return true;
284
    }
285
286
    /**
287
     * Validate IBAN
288
     *
289
     * @param  string $sBic
290
     * @return bool
291
     */
292
    protected function isBicValid($sBic)
293
    {
294
        $sRegex = '/^([a-zA-Z]{4}[a-zA-Z]{2}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?)$/';
295
        return $this->checkRegex($sRegex, $sBic);
296
    }
297
298
    /**
299
     * Check IBAN and BIC fields
300
     *
301
     * @param  string $sIban
302
     * @param  string $sBic
303
     * @return bool
304
     * @throws LocalizedException
305
     */
306
    public function isSepaDataValid($sIban, $sBic)
307
    {
308
        if (!$this->isIbanValid($sIban)) {
309
            throw new LocalizedException(__('The given IBAN is invalid!'));
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

309
            throw new LocalizedException(/** @scrutinizer ignore-call */ __('The given IBAN is invalid!'));
Loading history...
310
        }
311
        if (!$this->isBicValid($sBic)) {
312
            throw new LocalizedException(__('The given BIC is invalid!'));
313
        }
314
        return true;
315
    }
316
317
    /**
318
     * Emulate the getCreditmemoRequestParams method for creditmemos that are not created via adminhtml
319
     *
320
     * @param $oCreditmemo
321
     * @return array
322
     */
323
    protected function getCreditMemoData($oCreditmemo)
324
    {
325
        $data = [];
326
        foreach ($oCreditmemo->getItems() as $item) {
327
            if ($item->getQty() <= 0 || $item->getOrderItem()->isDummy()){
328
                continue;
329
            }
330
            $data['items'][$item->getOrderItemId()]['qty'] = $item->getQty();
331
        }
332
        $data['do_offline'] = 0;
333
        $data['comment_text'] = '';
334
        $data['shipping_amount'] = 0;
335
        if ($oCreditmemo->getAdjustment() > 0) {
336
            $data['adjustment_positive'] = $oCreditmemo->getAdjustment();
337
        } else if ($oCreditmemo->getAdjustment() < 0) {
338
            $data['adjustment_negative'] = $oCreditmemo->getAdjustment() * -1;
339
        }
340
341
        return $data;
342
    }
343
}
344