Issues (19)

src/Authnetjson/AuthnetJsonResponse.php (4 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of the AuthnetJSON package.
7
 *
8
 * (c) John Conde <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Authnetjson;
15
16
use Authnetjson\Exception\AuthnetCannotSetParamsException;
17
use Authnetjson\Exception\AuthnetInvalidJsonException;
18
use Authnetjson\Exception\AuthnetTransactionResponseCallException;
19
20
/**
21
 * Adapter for the Authorize.Net JSON API
22
 *
23
 * @package   AuthnetJSON
24
 * @author    John Conde <[email protected]>
25
 * @copyright 2015 - 2023 John Conde <[email protected]>
26
 * @license   http://www.apache.org/licenses/LICENSE-2.0.html Apache License, Version 2.0
27
 * @link      https://github.com/stymiee/authnetjson
28
 * @see       https://developer.authorize.net/api/reference/
29
 *
30
 * @property object $messages
31
 * @property string $directResponse
32
 * @property string $validationDirectResponseList
33
 * @property object $transactionResponse
34
 *
35
 * @method null authenticateTestRequest(array $array)
36
 * @method null createTransactionRequest(array $array)
37
 * @method null sendCustomerTransactionReceiptRequest(array $array)
38
 * @method null ARBCancelSubscriptionRequest(array $array)
39
 * @method null ARBCreateSubscriptionRequest(array $array)
40
 * @method null ARBGetSubscriptionStatusRequest(array $array)
41
 * @method null ARBUpdateSubscriptionRequest(array $array)
42
 * @method null createCustomerPaymentProfileRequest(array $array)
43
 * @method null createCustomerProfileRequest(array $array)
44
 * @method null createCustomerProfileTransactionRequest_authCapture(array $array)
45
 * @method null createCustomerProfileTransactionRequest_authOnly(array $array)
46
 * @method null createCustomerProfileTransactionRequest_captureOnly(array $array)
47
 * @method null createCustomerProfileTransactionRequest_priorAuthCapture(array $array)
48
 * @method null createCustomerProfileTransactionRequest_refund(array $array)
49
 * @method null createCustomerProfileTransactionRequest_void(array $array)
50
 * @method null createCustomerShippingAddressRequest(array $array)
51
 * @method null deleteCustomerPaymentProfileRequest(array $array)
52
 * @method null deleteCustomerProfileRequest(array $array)
53
 * @method null deleteCustomerShippingAddressRequest(array $array)
54
 * @method null getCustomerPaymentProfileRequest(array $array)
55
 * @method null getCustomerProfileIdsRequest(array $array)
56
 * @method null getCustomerProfileRequest(array $array)
57
 * @method null getCustomerShippingAddressRequest(array $array)
58
 * @method null getHostedProfilePageRequest(array $array)
59
 * @method null updateCustomerPaymentProfileRequest(array $array)
60
 * @method null updateCustomerProfileRequest(array $array)
61
 * @method null updateCustomerShippingAddressRequest(array $array)
62
 * @method null updateSplitTenderGroupRequest(array $array)
63
 * @method null validateCustomerPaymentProfileRequest(array $array)
64
 * @method null getBatchStatisticsRequest(array $array)
65
 * @method null getSettledBatchListRequest(array $array)
66
 * @method null getTransactionDetailsRequest(array $array)
67
 * @method null getTransactionListRequest(array $array)
68
 * @method null getUnsettledTransactionListRequest(array $array)
69
 */
70
class AuthnetJsonResponse
71
{
72
    /**
73
     * @const Indicates the status code of an approved transaction
74
     */
75
    public const STATUS_APPROVED = 1;
76
77
    /**
78
     * @const Indicates the status code of a declined transaction
79
     */
80
    public const STATUS_DECLINED = 2;
81
82
    /**
83
     * @const Indicates the status code of a transaction which has encountered an error
84
     */
85
    public const STATUS_ERROR = 3;
86
87
    /**
88
     * @const Indicates the status code of a transaction held for review
89
     */
90
    public const STATUS_HELD = 4;
91
92
    /**
93
     * @const Indicates the status code of a transaction held for review
94
     */
95
    public const STATUS_PAYPAL_NEED_CONSENT = 5;
96
97
    /**
98
     * @var object  SimpleXML object representing the API response
99
     */
100
    private $response;
101
102
    /**
103
     * @var string  JSON string that is the response sent by Authorize.Net
104
     */
105
    private $responseJson;
106
107
    /**
108
     * @var object  TransactionResponse
109
     */
110
    private $transactionInfo;
111
112
    /**
113
     * @var array  TransactionResponse
114
     */
115
    private $transactionInfoArray;
116
117
    /**
118
     * Creates the response object with the response json returned from the API call
119
     *
120
     * @param string $responseJson Response from Authorize.Net
121
     * @throws AuthnetInvalidJsonException
122
     */
123 4
    public function __construct(string $responseJson)
124
    {
125 4
        $this->responseJson = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $responseJson);
126 4
        if (($this->response = json_decode($this->responseJson, false)) === null) {
127 1
            throw new AuthnetInvalidJsonException('Invalid JSON returned by the API');
128
        }
129
130 3
        if ($this->directResponse
131 2
            || $this->validationDirectResponseList
132 3
            || isset($this->response->validationDirectResponse)
133
        ) {
134 3
            $response = $this->directResponse ?:
0 ignored issues
show
Expected 1 space after ":"; newline found
Loading history...
135 2
                $this->validationDirectResponseList ?:
0 ignored issues
show
Expected 1 space after ":"; newline found
Loading history...
136 3
                $this->response->validationDirectResponse;
137 3
            if (is_array($response)) {
138 1
                $this->transactionInfoArray = array_map(
139
                    static function ($r) {
140 1
                        return new TransactionResponse($r);
141 1
                    },
142 1
                    $response
143
                );
144
            } else {
145 2
                $this->transactionInfo = new TransactionResponse($response);
146 2
                $this->transactionInfoArray = [$this->transactionInfo];
147
            }
148
        }
149 3
    }
150
151
    /**
152
     * Outputs the response JSON in a human-readable format
153
     *
154
     * @return string  HTML table containing debugging information
155
     */
156 1
    public function __toString()
157
    {
158 1
        $output = '<table id="authnet-response">' . "\n";
159 1
        $output .= '<caption>Authorize.Net Response</caption>' . "\n";
160 1
        $output .= '<tr><th colspan="2"><b>Response JSON</b></th></tr>' . "\n";
161 1
        $output .= '<tr><td colspan="2"><pre>' . "\n";
162 1
        $output .= $this->responseJson . "\n";
163 1
        $output .= '</pre></td></tr>' . "\n";
164 1
        $output .= '</table>';
165
166 1
        return $output;
167
    }
168
169
    /**
170
     * Gets a response variable from the API response
171
     *
172
     * @param string $key Name of the response key to be retrieved if it exists
173
     * @return string requested variable from the API call response
174
     */
175 2
    public function __get(string $key)
176
    {
177 2
        return $this->response->{$key} ?? null;
178
    }
179
180
    /**
181
     * @throws AuthnetCannotSetParamsException
182
     */
183 1
    public function __set(string $key, $value)
184
    {
185 1
        throw new AuthnetCannotSetParamsException(sprintf('You cannot set parameters directly in %s.', __CLASS__));
186
    }
187
188
    /**
189
     * Checks if a value exists in the response JSON object
190
     *
191
     * @param string $key Name of the response key to check existence of
192
     * @return bool
193
     */
194 1
    public function __isset(string $key): bool
195
    {
196 1
        return isset($this->response->{$key});
197
    }
198
199
    /**
200
     * Checks if the API call is not in an error state
201
     *
202
     * @return bool    Whether the transaction was in a successful state
203
     */
204 2
    public function isSuccessful(): bool
205
    {
206 2
        return strtolower($this->messages->resultCode) === 'ok';
207
    }
208
209
    /**
210
     * Checks if the API is reporting an error with the API call
211
     *
212
     * @return bool    Whether the transaction was in an error state
213
     */
214 2
    public function isError(): bool
215
    {
216 2
        return strtolower($this->messages->resultCode) === 'error';
217
    }
218
219
    /**
220
     * Checks if a transaction was approved
221
     *
222
     * @return bool     true if the transaction is approved
223
     */
224 1
    public function isApproved(): bool
225
    {
226 1
        return $this->isSuccessful() && $this->checkTransactionStatus(self::STATUS_APPROVED);
227
    }
228
229
    /**
230
     * Checks if a transaction was completed using a prepaid card
231
     *
232
     * @return bool     true if the transaction was completed using a prepaid card
233
     */
234 1
    public function isPrePaidCard(): bool
235
    {
236 1
        return isset($this->transactionResponse->prePaidCard);
237
    }
238
239
    /**
240
     * Checks if a transaction was declined
241
     *
242
     * @return bool     true if the transaction is declined
243
     */
244 1
    public function isDeclined(): bool
245
    {
246 1
        return $this->isSuccessful() && $this->checkTransactionStatus(self::STATUS_DECLINED);
247
    }
248
249
    /**
250
     * Check to see if the ResponseCode matches the expected value
251
     *
252
     * @param int $status
253
     * @return bool Check to see if the ResponseCode matches the expected value
254
     */
255 2
    protected function checkTransactionStatus(int $status): bool
256
    {
257 2
        if ($this->transactionInfo instanceof TransactionResponse) {
258 1
            $match = (int)$this->transactionInfo->getTransactionResponseField('ResponseCode') === $status;
259
        } else {
260 1
            $match = (int)$this->transactionResponse->responseCode === $status;
261
        }
262 2
        return $match;
263
    }
264
265
    /**
266
     * Gets the transaction response field for AIM and CIM transactions.
267
     *
268
     * @param mixed $field Name or key of the transaction field to be retrieved
269
     * @return null|string Transaction field to be retrieved
270
     * @throws AuthnetTransactionResponseCallException
271
     */
272 2
    public function getTransactionResponseField($field): ?string
273
    {
274 2
        if ($this->transactionInfo instanceof TransactionResponse) {
275 1
            return $this->transactionInfo->getTransactionResponseField($field);
276
        }
277 1
        throw new AuthnetTransactionResponseCallException('This API call does not have any transaction response data');
278
    }
279
280
    /**
281
     * Returns the results of a test charge for each payment account provided when created a customer profile
282
     *
283
     * @return array
284
     */
285 1
    public function getTransactionResponses(): array
286
    {
287 1
        return $this->transactionInfoArray;
288
    }
289
290
    /**
291
     * Gets the transaction response from Authorize.Net in JSON format for logging purposes
292
     *
293
     * @return string transaction response from Authorize.Net in JSON format
294
     */
295 1
    public function getRawResponse(): string
296
    {
297 1
        return $this->responseJson;
298
    }
299
300
    /**
301
     * An alias of self::getErrorText()
302
     *
303
     * @return string Error response from Authorize.Net
304
     */
305 1
    public function getErrorMessage(): string
306
    {
307 1
        return $this->getErrorText();
308
    }
309
310
    /**
311
     * If an error has occurred, returns the error message
312
     *
313
     * @return string Error response from Authorize.Net
314
     */
315 2
    public function getErrorText(): string
316
    {
317 2
        return $this->getError('text');
318
    }
319
320
    /**
321
     * If an error has occurred, returns the error message
322
     *
323
     * @return string Error response from Authorize.Net
324
     */
325 2
    public function getErrorCode(): string
326
    {
327 2
        return $this->getError('code');
328
    }
329
330
    /**
331
     * @param string $type Whether to get the error code or text
332
     * @return string
333
     */
334 2
    private function getError(string $type): string
0 ignored issues
show
Private method name "AuthnetJsonResponse::getError" must be prefixed with an underscore
Loading history...
335
    {
336 2
        $msg = '';
337 2
        if ($this->isError()) {
338 2
            $prop = sprintf('error%s', ucfirst($type));
339 2
            $msg = $this->messages->message[0]->{$type};
340 2
            if (@$this->transactionResponse->errors[0]->{$prop}) {
0 ignored issues
show
Silencing errors is discouraged; found: @$this->transactionResponse...
Loading history...
341 1
                $msg = $this->transactionResponse->errors[0]->{$prop};
342
            }
343
        }
344 2
        return $msg;
345
    }
346
}
347