Passed
Pull Request — master (#49)
by Dmitri
05:33
created

processTransactionStatusUpdateTransfer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 14
rs 10
1
<?php
2
3
/**
4
 * MIT License
5
 * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
6
 */
7
8
namespace SprykerEco\Zed\Payone\Business\TransactionStatus;
9
10
use Generated\Shared\Transfer\PayoneStandardParameterTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfe...andardParameterTransfer 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...
11
use Generated\Shared\Transfer\PayoneTransactionStatusUpdateTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfe...ionStatusUpdateTransfer 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...
12
use Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLog;
0 ignored issues
show
Bug introduced by
The type Orm\Zed\Payone\Persisten...oneTransactionStatusLog 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...
13
use Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLogOrderItem;
0 ignored issues
show
Bug introduced by
The type Orm\Zed\Payone\Persisten...ctionStatusLogOrderItem 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...
14
use SprykerEco\Shared\Payone\Dependency\TransactionStatusUpdateInterface;
15
use SprykerEco\Shared\Payone\PayoneTransactionStatusConstants;
16
use SprykerEco\Zed\Payone\Business\Api\TransactionStatus\TransactionStatusRequest;
17
use SprykerEco\Zed\Payone\Business\Api\TransactionStatus\TransactionStatusResponse;
18
use SprykerEco\Zed\Payone\Business\Key\HashGenerator;
19
use SprykerEco\Zed\Payone\Persistence\PayoneQueryContainerInterface;
20
21
class TransactionStatusUpdateManager implements TransactionStatusUpdateManagerInterface
22
{
23
    /**
24
     * @var \SprykerEco\Zed\Payone\Persistence\PayoneQueryContainerInterface
25
     */
26
    protected $queryContainer;
27
28
    /**
29
     * @var \Generated\Shared\Transfer\PayoneStandardParameterTransfer
30
     */
31
    protected $standardParameter;
32
33
    /**
34
     * @var \SprykerEco\Zed\Payone\Business\Key\HashGenerator
35
     */
36
    protected $hashGenerator;
37
38
    /**
39
     * @param \SprykerEco\Zed\Payone\Persistence\PayoneQueryContainerInterface $queryContainer
40
     * @param \Generated\Shared\Transfer\PayoneStandardParameterTransfer $standardParameter
41
     * @param \SprykerEco\Zed\Payone\Business\Key\HashGenerator $hashGenerator
42
     */
43
    public function __construct(
44
        PayoneQueryContainerInterface $queryContainer,
45
        PayoneStandardParameterTransfer $standardParameter,
46
        HashGenerator $hashGenerator
47
    ) {
48
49
        $this->queryContainer = $queryContainer;
50
        $this->standardParameter = $standardParameter;
51
        $this->hashGenerator = $hashGenerator;
52
    }
53
54
    /**
55
     * @deprecated use processTransactionStatusUpdateTransfer() instead
56
     *
57
     * @param \SprykerEco\Shared\Payone\Dependency\TransactionStatusUpdateInterface $request
58
     *
59
     * @return \SprykerEco\Zed\Payone\Business\Api\TransactionStatus\TransactionStatusResponse
60
     */
61
    public function processTransactionStatusUpdate(TransactionStatusUpdateInterface $request)
62
    {
63
        $validationResult = $this->validate($request);
64
65
        if ($validationResult instanceof TransactionStatusResponse) {
66
            return $validationResult;
67
        }
68
69
        $this->transformCurrency($request);
70
        $this->persistRequest($request);
71
72
        return $this->createSuccessResponse();
73
    }
74
75
    /**
76
     * @param \Generated\Shared\Transfer\PayoneTransactionStatusUpdateTransfer $transactionStatusUpdateTransfer
77
     *
78
     * @return \Generated\Shared\Transfer\PayoneTransactionStatusUpdateTransfer
79
     */
80
    public function processTransactionStatusUpdateTransfer(PayoneTransactionStatusUpdateTransfer $transactionStatusUpdateTransfer)
81
    {
82
        $transactionStatusRequest = new TransactionStatusRequest($transactionStatusUpdateTransfer->toArray());
83
84
        $validationResult = $this->validate($transactionStatusRequest);
85
86
        if ($validationResult instanceof TransactionStatusResponse) {
87
            return $this->assignResponseToTransactionStatusUpdateTransfer($transactionStatusUpdateTransfer, $validationResult);
88
        }
89
90
        $this->transformCurrency($transactionStatusRequest);
91
        $this->persistRequest($transactionStatusRequest);
92
93
        return $this->assignResponseToTransactionStatusUpdateTransfer($transactionStatusUpdateTransfer, $this->createSuccessResponse());
94
    }
95
96
    /**
97
     * @param \Generated\Shared\Transfer\PayoneTransactionStatusUpdateTransfer $transactionStatusUpdateTransfer
98
     *
99
     * @param \Generated\Shared\Transfer\PayoneTransactionStatusUpdateTransfer
100
     */
101
    protected function assignResponseToTransactionStatusUpdateTransfer(PayoneTransactionStatusUpdateTransfer $transactionStatusUpdateTransfer, TransactionStatusResponse $response)
102
    {
103
        $transactionStatusUpdateTransfer->setIsSuccess($response->isSuccess());
104
        $transactionStatusUpdateTransfer->setResponse($response->getStatus() . ($response->getErrorMessage() ? ': ' . $response->getErrorMessage() : ''));
105
106
        return $transactionStatusUpdateTransfer;
107
    }
108
109
    /**
110
     * @param \SprykerEco\Shared\Payone\Dependency\TransactionStatusUpdateInterface $request
111
     *
112
     * @return void
113
     */
114
    protected function persistRequest(TransactionStatusUpdateInterface $request)
115
    {
116
        $entity = new SpyPaymentPayoneTransactionStatusLog();
117
118
        $entity->setSpyPaymentPayone($this->findPaymentByTransactionId($request->getTxid()));
119
        $entity->setTransactionId($request->getTxid());
120
        $entity->setReferenceId($request->getReference());
121
        $entity->setMode($request->getMode());
122
        $entity->setStatus($request->getTxaction());
123
        $entity->setTransactionTime($request->getTxtime());
124
        $entity->setSequenceNumber($request->getSequencenumber());
125
        $entity->setClearingType($request->getClearingtype());
126
        $entity->setPortalId($request->getPortalid());
127
        $entity->setPrice($request->getPrice());
128
        $entity->setBalance($request->getBalance());
129
        $entity->setReceivable($request->getReceivable());
130
        $entity->setReminderLevel($request->getReminderlevel());
131
132
        $entity->setRawRequest($request);
133
134
        $entity->save();
135
    }
136
137
    /**
138
     * @param int $idSalesOrder
139
     * @param int $idSalesOrderItem
140
     *
141
     * @return bool
142
     */
143
    public function isPaymentNotificationAvailable($idSalesOrder, $idSalesOrderItem)
144
    {
145
        return $this->hasUnprocessedTransactionStatusLogs($idSalesOrder, $idSalesOrderItem);
146
    }
147
148
    /**
149
     * @param \SprykerEco\Shared\Payone\Dependency\TransactionStatusUpdateInterface $request
150
     *
151
     * @return void
152
     */
153
    protected function transformCurrency(TransactionStatusUpdateInterface $request)
154
    {
155
        $balance = $request->getBalance();
156
        $balanceAmountInCents = round($balance * 100);
157
        $request->setBalance($balanceAmountInCents);
0 ignored issues
show
Bug introduced by
The method setBalance() does not exist on SprykerEco\Shared\Payone...onStatusUpdateInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to SprykerEco\Shared\Payone...onStatusUpdateInterface. ( Ignorable by Annotation )

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

157
        $request->/** @scrutinizer ignore-call */ 
158
                  setBalance($balanceAmountInCents);
Loading history...
158
159
        $receivable = $request->getReceivable();
160
        $receivableAmountInCents = round($receivable * 100);
161
        $request->setReceivable($receivableAmountInCents);
0 ignored issues
show
Bug introduced by
The method setReceivable() does not exist on SprykerEco\Shared\Payone...onStatusUpdateInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to SprykerEco\Shared\Payone...onStatusUpdateInterface. ( Ignorable by Annotation )

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

161
        $request->/** @scrutinizer ignore-call */ 
162
                  setReceivable($receivableAmountInCents);
Loading history...
162
163
        $price = $request->getPrice();
164
        $priceAmountInCents = round($price * 100);
165
        $request->setPrice($priceAmountInCents);
0 ignored issues
show
Bug introduced by
The method setPrice() does not exist on SprykerEco\Shared\Payone...onStatusUpdateInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to SprykerEco\Shared\Payone...onStatusUpdateInterface. ( Ignorable by Annotation )

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

165
        $request->/** @scrutinizer ignore-call */ 
166
                  setPrice($priceAmountInCents);
Loading history...
166
    }
167
168
    /**
169
     * @param \SprykerEco\Shared\Payone\Dependency\TransactionStatusUpdateInterface $request
170
     *
171
     * @return bool|\SprykerEco\Zed\Payone\Business\Api\TransactionStatus\TransactionStatusResponse
172
     */
173
    protected function validate(TransactionStatusUpdateInterface $request)
174
    {
175
        $systemHashedKey = $this->hashGenerator->hash($this->standardParameter->getKey());
176
        if ($request->getKey() !== $systemHashedKey) {
177
            return $this->createErrorResponse('Payone transaction status update: Given and internal key do not match!');
178
        }
179
180
        if ((int)$request->getAid() !== (int)$this->standardParameter->getAid()) {
181
            return $this->createErrorResponse('Payone transaction status update: Invalid Aid! System: ' . $this->standardParameter->getAid() . ' Request: ' . $request->getAid());
182
        }
183
184
        if ((int)$request->getPortalid() !== (int)$this->standardParameter->getPortalId()) {
185
            return $this->createErrorResponse('Payone transaction status update: Invalid Portalid! System: ' . $this->standardParameter->getPortalId() . ' Request: ' . $request->getPortalid());
186
        }
187
188
        return true;
189
    }
190
191
    /**
192
     * @param string $errorMessage
193
     *
194
     * @return \SprykerEco\Zed\Payone\Business\Api\TransactionStatus\TransactionStatusResponse
195
     */
196
    protected function createErrorResponse($errorMessage)
197
    {
198
        $response = new TransactionStatusResponse(false);
199
        $response->setErrorMessage($errorMessage);
200
201
        return $response;
202
    }
203
204
    /**
205
     * @return \SprykerEco\Zed\Payone\Business\Api\TransactionStatus\TransactionStatusResponse
206
     */
207
    protected function createSuccessResponse()
208
    {
209
        $response = new TransactionStatusResponse(true);
210
211
        return $response;
212
    }
213
214
    /**
215
     * @param string $transactionId
216
     *
217
     * @return \Orm\Zed\Payone\Persistence\SpyPaymentPayone
0 ignored issues
show
Bug introduced by
The type Orm\Zed\Payone\Persistence\SpyPaymentPayone 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...
218
     */
219
    protected function findPaymentByTransactionId($transactionId)
220
    {
221
        return $this->queryContainer->createPaymentByTransactionIdQuery($transactionId)->findOne();
0 ignored issues
show
Bug introduced by
$transactionId of type string is incompatible with the type integer expected by parameter $transactionId of SprykerEco\Zed\Payone\Pe...tByTransactionIdQuery(). ( Ignorable by Annotation )

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

221
        return $this->queryContainer->createPaymentByTransactionIdQuery(/** @scrutinizer ignore-type */ $transactionId)->findOne();
Loading history...
222
    }
223
224
    /**
225
     * @param int $idSalesOrder
226
     * @param int $idSalesOrderItem
227
     *
228
     * @return bool
229
     */
230
    public function isPaymentPaid($idSalesOrder, $idSalesOrderItem)
231
    {
232
        $status = PayoneTransactionStatusConstants::TXACTION_PAID;
233
        $statusLog = $this->getFirstUnprocessedTransactionStatusLog($idSalesOrder, $idSalesOrderItem, $status);
234
        if ($statusLog === null) {
235
            return false;
236
        }
237
        if ($statusLog->getBalance() > 0) {
238
            return false;
239
        }
240
241
        $this->saveSpyPaymentPayoneTransactionStatusLogOrderItem($idSalesOrderItem, $statusLog);
242
243
        return true;
244
    }
245
246
    /**
247
     * @param int $idSalesOrder
248
     * @param int $idSalesOrderItem
249
     *
250
     * @return bool
251
     */
252
    public function isPaymentCapture($idSalesOrder, $idSalesOrderItem)
253
    {
254
        $status = PayoneTransactionStatusConstants::TXACTION_CAPTURE;
255
256
        return $this->isPayment($idSalesOrder, $idSalesOrderItem, $status);
257
    }
258
259
    /**
260
     * @param int $idSalesOrder
261
     * @param int $idSalesOrderItem
262
     *
263
     * @return bool
264
     */
265
    public function isPaymentOverpaid($idSalesOrder, $idSalesOrderItem)
266
    {
267
        $status = PayoneTransactionStatusConstants::TXACTION_PAID;
268
        $statusLog = $this->getFirstUnprocessedTransactionStatusLog($idSalesOrder, $idSalesOrderItem, $status);
269
        if ($statusLog === null) {
270
            return false;
271
        }
272
        if ($statusLog->getBalance() >= 0) {
273
            return false;
274
        }
275
276
        $this->saveSpyPaymentPayoneTransactionStatusLogOrderItem($idSalesOrderItem, $statusLog);
277
278
        return true;
279
    }
280
281
    /**
282
     * @param int $idSalesOrder
283
     * @param int $idSalesOrderItem
284
     *
285
     * @return bool
286
     */
287
    public function isPaymentUnderpaid($idSalesOrder, $idSalesOrderItem)
288
    {
289
        $status = PayoneTransactionStatusConstants::TXACTION_UNDERPAID;
290
291
        return $this->isPayment($idSalesOrder, $idSalesOrderItem, $status);
292
    }
293
294
    /**
295
     * @param int $idSalesOrder
296
     * @param int $idSalesOrderItem
297
     *
298
     * @return bool
299
     */
300
    public function isPaymentRefund($idSalesOrder, $idSalesOrderItem)
301
    {
302
        $status = PayoneTransactionStatusConstants::TXACTION_REFUND;
303
304
        return $this->isPayment($idSalesOrder, $idSalesOrderItem, $status);
305
    }
306
307
    /**
308
     * @param int $idSalesOrder
309
     * @param int $idSalesOrderItem
310
     *
311
     * @return bool
312
     */
313
    public function isPaymentAppointed($idSalesOrder, $idSalesOrderItem)
314
    {
315
        $status = PayoneTransactionStatusConstants::TXACTION_APPOINTED;
316
317
        return $this->isPayment($idSalesOrder, $idSalesOrderItem, $status);
318
    }
319
320
    /**
321
     * @param int $idSalesOrder
322
     * @param int $idSalesOrderItem
323
     *
324
     * @return bool
325
     */
326
    public function isPaymentOther($idSalesOrder, $idSalesOrderItem)
327
    {
328
        $statusLogs = $this->getUnprocessedTransactionStatusLogs($idSalesOrder, $idSalesOrderItem);
329
        if (empty($statusLogs)) {
330
            return false;
331
        }
332
333
        /** @var \Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLog $statusLog */
334
        $statusLog = array_shift($statusLogs);
335
336
        $statuses = [
337
            PayoneTransactionStatusConstants::TXACTION_PAID,
338
            PayoneTransactionStatusConstants::TXACTION_APPOINTED,
339
            PayoneTransactionStatusConstants::TXACTION_UNDERPAID,
340
        ];
341
        if (in_array($statusLog->getStatus(), $statuses)) {
342
            return false;
343
        }
344
345
        $this->saveSpyPaymentPayoneTransactionStatusLogOrderItem($idSalesOrderItem, $statusLog);
346
347
        return true;
348
    }
349
350
    /**
351
     * @param int $idSalesOrder
352
     * @param int $idSalesOrderItem
353
     * @param string $status
354
     *
355
     * @return bool
356
     */
357
    protected function isPayment($idSalesOrder, $idSalesOrderItem, $status)
358
    {
359
        $statusLog = $this->getFirstUnprocessedTransactionStatusLog($idSalesOrder, $idSalesOrderItem, $status);
360
        if ($statusLog === null) {
361
            return false;
362
        }
363
364
        $this->saveSpyPaymentPayoneTransactionStatusLogOrderItem($idSalesOrderItem, $statusLog);
365
366
        return true;
367
    }
368
369
    /**
370
     * @param int $idSalesOrder
371
     * @param int $idSalesOrderItem
372
     *
373
     * @return bool
374
     */
375
    protected function hasUnprocessedTransactionStatusLogs($idSalesOrder, $idSalesOrderItem)
376
    {
377
        $records = $this->getUnprocessedTransactionStatusLogs($idSalesOrder, $idSalesOrderItem);
0 ignored issues
show
Unused Code introduced by
The assignment to $records is dead and can be removed.
Loading history...
378
379
        return !empty($transactionStatusLogs);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $transactionStatusLogs seems to never exist and therefore empty should always be true.
Loading history...
380
    }
381
382
    /**
383
     * @param int $idSalesOrder
384
     * @param int $idSalesOrderItem
385
     * @param string $status
386
     *
387
     * @return \Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLog|null
388
     */
389
    protected function getFirstUnprocessedTransactionStatusLog($idSalesOrder, $idSalesOrderItem, $status)
390
    {
391
        $transactionStatusLogs = $this->getUnprocessedTransactionStatusLogs($idSalesOrder, $idSalesOrderItem);
392
393
        if (empty($transactionStatusLogs)) {
394
            return null;
395
        }
396
397
        while (count($transactionStatusLogs)) {
398
            /** @var \Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLog $transactionStatusLog */
399
            $transactionStatusLog = array_shift($transactionStatusLogs);
400
401
            if ($transactionStatusLog->getStatus() == $status) {
402
                return $transactionStatusLog;
403
            }
404
        }
405
406
        return null;
407
    }
408
409
    /**
410
     * @param int $idSalesOrder
411
     * @param int $idSalesOrderItem
412
     *
413
     * @return \Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLog[]
414
     */
415
    protected function getUnprocessedTransactionStatusLogs($idSalesOrder, $idSalesOrderItem)
416
    {
417
        $transactionStatusLogs = $this->queryContainer->createTransactionStatusLogsBySalesOrder($idSalesOrder)->find();
418
419
        $ids = [];
420
421
        /** @var \Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLog $transactionStatusLog */
422
        foreach ($transactionStatusLogs as $transactionStatusLog) {
423
            $ids[$transactionStatusLog->getIdPaymentPayoneTransactionStatusLog()] = $transactionStatusLog;
424
        }
425
426
        $relations = $this->queryContainer
427
            ->createTransactionStatusLogOrderItemsByLogIds($idSalesOrderItem, array_keys($ids))
428
            ->find();
429
430
        /** @var \Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLogOrderItem $relation */
431
        foreach ($relations as $relation) {
432
            unset($ids[$relation->getIdPaymentPayoneTransactionStatusLog()]);
433
        }
434
435
        return $ids;
436
    }
437
438
    /**
439
     * @param int $idSalesOrderItem
440
     * @param \Orm\Zed\Payone\Persistence\SpyPaymentPayoneTransactionStatusLog $statusLog
441
     *
442
     * @return void
443
     */
444
    protected function saveSpyPaymentPayoneTransactionStatusLogOrderItem($idSalesOrderItem, SpyPaymentPayoneTransactionStatusLog $statusLog)
445
    {
446
        $entity = new SpyPaymentPayoneTransactionStatusLogOrderItem();
447
        $entity->setSpyPaymentPayoneTransactionStatusLog($statusLog);
448
        $entity->setIdSalesOrderItem($idSalesOrderItem);
449
        $entity->save();
450
    }
451
}
452