1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\AuthorizenetAcceptjs\Gateway\Validator;
use Magento\AuthorizenetAcceptjs\Gateway\SubjectReader;
use Magento\Payment\Gateway\Validator\AbstractValidator;
use Magento\Payment\Gateway\Validator\ResultInterface;
use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
/**
* Validates the status of an attempted transaction
*/
class TransactionResponseValidator extends AbstractValidator
{
private const RESPONSE_CODE_APPROVED = 1;
private const RESPONSE_CODE_HELD = 4;
private const RESPONSE_REASON_CODE_APPROVED = 1;
private const RESPONSE_REASON_CODE_PENDING_REVIEW_AUTHORIZED = 252;
private const RESPONSE_REASON_CODE_PENDING_REVIEW = 253;
/**
* @var SubjectReader
*/
private $subjectReader;
/**
* @param ResultInterfaceFactory $resultFactory
* @param SubjectReader $subjectReader
*/
public function __construct(ResultInterfaceFactory $resultFactory, SubjectReader $subjectReader)
{
parent::__construct($resultFactory);
$this->subjectReader = $subjectReader;
}
/**
* @inheritdoc
*/
public function validate(array $validationSubject): ResultInterface
{
$response = $this->subjectReader->readResponse($validationSubject);
$transactionResponse = $response['transactionResponse'];
if ($this->isResponseCodeAnError($transactionResponse)) {
$errorCodes = [];
$errorMessages = [];
if (isset($transactionResponse['messages']['message']['code'])) {
$errorCodes[] = $transactionResponse['messages']['message']['code'];
$errorMessages[] = $transactionResponse['messages']['message']['text'];
} elseif ($transactionResponse['messages']['message']) {
foreach ($transactionResponse['messages']['message'] as $message) {
$errorCodes[] = $message['code'];
$errorMessages[] = $message['description'];
}
} elseif (isset($transactionResponse['errors'])) {
foreach ($transactionResponse['errors'] as $message) {
$errorCodes[] = $message['errorCode'];
$errorMessages[] = $message['errorCode'];
}
}
return $this->createResult(false, $errorMessages, $errorCodes);
}
return $this->createResult(true);
}
/**
* Determines if the response code is actually an error
*
* @param array $transactionResponse
* @return bool
*/
private function isResponseCodeAnError(array $transactionResponse): bool
{
$code = $transactionResponse['messages']['message']['code']
?? $transactionResponse['messages']['message'][0]['code']
?? $transactionResponse['errors'][0]['errorCode']
?? null;
return in_array($transactionResponse['responseCode'], [self::RESPONSE_CODE_APPROVED, self::RESPONSE_CODE_HELD])
&& $code
&& !in_array(
$code,
[
self::RESPONSE_REASON_CODE_APPROVED,
self::RESPONSE_REASON_CODE_PENDING_REVIEW,
self::RESPONSE_REASON_CODE_PENDING_REVIEW_AUTHORIZED
]
);
}
}