Completed
Branch php72 (c33fc7)
by John
01:32
created

AuthnetJsonRequest::process()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4888
c 0
b 0
f 0
cc 5
nc 3
nop 0
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * This file is part of the AuthnetJSON package.
6
 *
7
 * (c) John Conde <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace JohnConde\Authnet;
14
15
/**
16
 * Creates a request to the Authorize.Net JSON endpoints
17
 *
18
 * @package     AuthnetJSON
19
 * @author      John Conde <[email protected]>
20
 * @copyright   John Conde <[email protected]>
21
 * @license     http://www.apache.org/licenses/LICENSE-2.0.html Apache License, Version 2.0
22
 * @link        https://github.com/stymiee/authnetjson
23
 * @see         https://developer.authorize.net/api/reference/
24
 *
25
 * @method AuthnetJsonResponse createTransactionRequest(array $array)                                 process a payment
26
 * @method AuthnetJsonResponse sendCustomerTransactionReceiptRequest(array $array)                    get a list of unsettled transactions
27
 * @method AuthnetJsonResponse ARBCancelSubscriptionRequest(array $array)                             cancel a subscription
28
 * @method AuthnetJsonResponse ARBCreateSubscriptionRequest(array $array)                             create a subscription
29
 * @method AuthnetJsonResponse ARBGetSubscriptionStatusRequest(array $array)                          get a subscription's status
30
 * @method AuthnetJsonResponse ARBUpdateSubscriptionRequest(array $array)                             update a subscription
31
 * @method AuthnetJsonResponse createCustomerPaymentProfileRequest(array $array)                      create a payment profile
32
 * @method AuthnetJsonResponse createCustomerProfileRequest(array $array)                             create a customer profile
33
 * @method AuthnetJsonResponse createCustomerProfileTransactionRequest_authCapture(array $array)      process an Authorization and Capture transaction (Sale)
34
 * @method AuthnetJsonResponse createCustomerProfileTransactionRequest_authOnly(array $array)         process an Authorization Only transaction
35
 * @method AuthnetJsonResponse createCustomerProfileTransactionRequest_captureOnly(array $array)      process a Capture Only transaction
36
 * @method AuthnetJsonResponse createCustomerProfileTransactionRequest_priorAuthCapture(array $array) process a Prior Authorization Capture transaction
37
 * @method AuthnetJsonResponse createCustomerProfileTransactionRequest_refund(array $array)           process a Refund (credit)
38
 * @method AuthnetJsonResponse createCustomerProfileTransactionRequest_void(array $array)             void a transaction
39
 * @method AuthnetJsonResponse createCustomerShippingAddressRequest(array $array)                     create a shipping profile
40
 * @method AuthnetJsonResponse deleteCustomerPaymentProfileRequest(array $array)                      delete a payment profile
41
 * @method AuthnetJsonResponse deleteCustomerProfileRequest(array $array)                             delete a customer profile
42
 * @method AuthnetJsonResponse deleteCustomerShippingAddressRequest(array $array)                     delete a shipping profile
43
 * @method AuthnetJsonResponse getCustomerPaymentProfileRequest(array $array)                         retrieve a payment profile
44
 * @method AuthnetJsonResponse getCustomerProfileIdsRequest(array $array)                             retrieve a list of profile IDs
45
 * @method AuthnetJsonResponse getCustomerProfileRequest(array $array)                                retrieve a customer profile
46
 * @method AuthnetJsonResponse getCustomerShippingAddressRequest(array $array)                        retrieve a shipping address
47
 * @method AuthnetJsonResponse getHostedProfilePageRequest(array $array)                              retrieve a hosted payment page token
48
 * @method AuthnetJsonResponse updateCustomerPaymentProfileRequest(array $array)                      update a customer profile
49
 * @method AuthnetJsonResponse updateCustomerProfileRequest(array $array)                             update a customer profile
50
 * @method AuthnetJsonResponse updateCustomerShippingAddressRequest(array $array)                     update a shipping address
51
 * @method AuthnetJsonResponse updateSplitTenderGroupRequest(array $array)                            update a split tender transaction
52
 * @method AuthnetJsonResponse validateCustomerPaymentProfileRequest(array $array)                    validate a payment profile
53
 * @method AuthnetJsonResponse getBatchStatisticsRequest(array $array)                                get a summary of a settled batch
54
 * @method AuthnetJsonResponse getSettledBatchListRequest(array $array)                               get a list of settled batches
55
 * @method AuthnetJsonResponse getTransactionDetailsRequest(array $array)                             get the details of a transaction
56
 * @method AuthnetJsonResponse getTransactionListRequest(array $array)                                get a list of transaction in a batch
57
 * @method AuthnetJsonResponse getUnsettledTransactionListRequest(array $array)                       get a list of unsettled transactions
58
 */
59
class AuthnetJsonRequest
60
{
61
    /**
62
     * @var     int     Maximum number of retires making HTTP request before failure
63
     */
64
    private const MAX_RETRIES = 3;
65
66
    /**
67
     * @var     string  Authorize.Net API login ID
68
     */
69
    private $login;
70
71
    /**
72
     * @var     string  Authorize.Net API Transaction Key
73
     */
74
    private $transactionKey;
75
76
    /**
77
     * @var     string  URL endpoint for processing a transaction
78
     */
79
    private $url;
80
81
    /**
82
     * @var     string  JSON formatted API request
83
     */
84
    private $requestJson;
85
86
    /**
87
     * @var     object  Wrapper object representing an endpoint
88
     */
89
    private $processor;
90
91
    /**
92
     * Creates the request object by setting the Authorize.Net credentials and URL of the endpoint to be used
93
     * for the API call
94
     *
95
     * @param   string  $login              Authorize.Net API login ID
96
     * @param   string  $transactionKey     Authorize.Net API Transaction Key
97
     * @param   string  $api_url            URL endpoint for processing a transaction
98
     */
99
    public function __construct(string $login, string $transactionKey, string $api_url)
100
    {
101
        $this->login          = $login;
102
        $this->transactionKey = $transactionKey;
103
        $this->url            = $api_url;
104
    }
105
106
    /**
107
     * Outputs the account credentials, endpoint URL, and request JSON in a human readable format
108
     *
109
     * @return  string  HTML table containing debugging information
110
     */
111
    public function __toString()
112
    {
113
        $output  = '<table id="authnet-request">'."\n";
114
        $output .= '<caption>Authorize.Net Request</caption>'."\n";
115
        $output .= '<tr>'."\n\t\t".'<th colspan="2"><b>Class Parameters</b></th>'."\n".'</tr>'."\n";
116
        $output .= '<tr>'."\n\t\t".'<td><b>API Login ID</b></td><td>'.$this->login.'</td>'."\n".'</tr>'."\n";
117
        $output .= '<tr>'."\n\t\t".'<td><b>Transaction Key</b></td><td>'.$this->transactionKey.'</td>'."\n".'</tr>'."\n";
118
        $output .= '<tr>'."\n\t\t".'<td><b>Authnet Server URL</b></td><td>'.$this->url.'</td>'."\n".'</tr>'."\n";
119
        $output .= '<tr>'."\n\t\t".'<th colspan="2"><b>Request JSON</b></th>'."\n".'</tr>'."\n";
120
        if (!empty($this->requestJson)) {
121
            $output .= '<tr><td colspan="2"><pre>'."\n";
122
            $output .= $this->requestJson."\n";
123
            $output .= '</pre></td></tr>'."\n";
124
        }
125
        $output .= '</table>';
126
127
        return $output;
128
    }
129
130
    /**
131
     * The __set() method should never be used as all values to be made in the APi call must be passed as an array
132
     *
133
     * @param   string  $name       unused
134
     * @param   mixed   $value      unused
135
     * @throws  AuthnetCannotSetParamsException
136
     */
137
    public function __set($name, $value)
138
    {
139
        throw new AuthnetCannotSetParamsException(sprintf('You cannot set parameters directly in %s.', __CLASS__));
140
    }
141
142
    /**
143
     * Magic method that dynamically creates our API call based on the name of the method in the client code and
144
     * the array passed as its parameter
145
     *
146
     * @param   string  $api_call   name of the API call to be made
147
     * @param   array   $args       the array to be passed to the API
148
     * @return  AuthnetJsonResponse
149
     * @throws  AuthnetCurlException
150
     * @throws  AuthnetInvalidJsonException
151
     */
152
    public function __call($api_call, Array $args)
153
    {
154
        $authentication = [
155
            'merchantAuthentication' => [
156
                'name'           => $this->login,
157
                'transactionKey' => $this->transactionKey,
158
            ]
159
        ];
160
        $call = [];
161
        if (count($args)) {
162
            $call = $args[0];
163
        }
164
        $parameters = [
165
            $api_call => $authentication + $call
166
        ];
167
        $this->requestJson = json_encode($parameters);
168
169
        $response = $this->process();
170
        return new AuthnetJsonResponse($response);
171
    }
172
173
    /**
174
     * Makes POST request with retry logic.
175
     */
176
    private function makeRequest() : void
177
    {
178
        $retries = 0;
179
        while ($retries < self::MAX_RETRIES) {
180
            $this->processor->post($this->url, $this->requestJson);
181
            if (!$this->processor->error) {
182
                break;
183
            }
184
            $retries++;
185
        }
186
    }
187
188
    /**
189
     * Tells the handler to make the API call to Authorize.Net
190
     *
191
     * @return  string  JSON string containing API response
192
     * @throws  AuthnetCurlException
193
     */
194
    private function process() : string
195
    {
196
        $this->makeRequest();
197
        if (!$this->processor->error && isset($this->processor->response)) {
198
            return $this->processor->response;
199
        }
200
        $error_message = null;
201
        $error_code    = null;
202
        if ($this->processor->error_code || $this->processor->error_message) {
203
            $error_message = $this->processor->error_message;
204
            $error_code    = $this->processor->error_code;
205
        }
206
        throw new AuthnetCurlException(sprintf('Connection error: %s (%s)', $error_message, $error_code));
207
    }
208
209
    /**
210
     * Sets the handler to be used to handle our API call. Mainly used for unit testing as Curl is used by default.
211
     *
212
     * @param   object  $processor
213
     */
214
    public function setProcessHandler($processor) : void
215
    {
216
        $this->processor = $processor;
217
    }
218
219
    /**
220
     * Gets the request sent to Authorize.Net in JSON format for logging purposes
221
     *
222
     * @return  string transaction request sent to Authorize.Net in JSON format
223
     */
224
    public function getRawRequest() : string
225
    {
226
        return $this->requestJson;
227
    }
228
}
229